最近在编写的一个Apache  kafka 的C/C++客户端,,在看他写的 example中,他的编译是用librdkafka++.a和librdkafka.a    静态库编译的,,,而我们这边要求使用动态库方法编译,,,所以简单了解一下,静态库编译的动态库编译的区别,下边是一个网上搜的一篇文章,到最后有一点简单介绍!

【转】在Linux下如何使用GCC编译程序、简单生成 静态库及动态库。

 

本文适用于Linux下开发初学者。本文初步讲解在Linux下如何使用GCC编译程序、简单生成静态库及动态库。

一、关于安装。一般系统默认是安装好编译器的,并且网络上有大量资料介绍不同发行版本下的安装问题,本文不再描述。

二、C编程中的文件后缀名介绍
    .a 静态库(打包文件)
    .c 未经过预处理的C源码
    .h C头文件   
    .i 经过预处理的C源码
    .o 编译之后产生的目标文件
    .s 生成的汇编语言代码
    .so 动态库(动态链接库)
    解释:*.a是我们在编译过后用ar打包生成的静态库;*.c一般使我们自己编辑的代码,使我们劳动的结晶;*.h一般是 我们手工生成的接口文件,如果愿意,也可在*.c完成后用GCC的选项-aux-info帮我们生成;*.i是经过预处理后的源码,是由GCC在选项-E编译下自动生成 的文件;*.o是编 译后产生的目标文件;*.s是GCC在选项-S编译下生成的汇编语言代码,对于性能要求很高的程序可以先生成汇编语言文件并对汇编做优化,然后用优 化后的汇编生成目标文件并链接;*.so是动态库,通过GCC的-fpic -shared选项生成。

三、hello.c的编译过程

本小节的演示都针对文件 hello.c 进行

  1. /*
  2. * hello.c
  3. */
  4. #include <stdio.h>
  5. int  main()
  6. {
  7. printf("hello, world!/n");
  8. return 0;
  9. }

1. 直接生成可执行程序

  1. $ gcc -o hello hello.c
  2. $ ./hello
  3. hello, world!
  4. 如 下编译方式 结果相同:
  5. $ gcc hello.c -o hello
  6. $ ./hello
  7. hello, world!
  8. 如 下编译方式 有别于以上编译方 案(具体查找ELF和a.out文件格式差别的网络资料,对于此处结果是无任何区别的):
  9. $ gcc hello.c
  10. $ ./a.out
  11. hello, world!

2. 生成预处理后的文件 hello.i

  1. $ gcc -E hello.c -o hello.i
  2. $ ls
  3. a.out  hello  hello.c  hello.i
  4. hello.i 就 是新生成的文件
  5. 如下语句结果相同:
  6. $ gcc -E -o hello.i hello.c
  7. 如 果不设定输出文件,则打印到标准终端,此时我们可以用 less 查看:
  8. $ gcc -E hello.c | less
  9. # 1 "hello.c"
  10. # 1 "<built-in>"
  11. # 1 "<command line>"
  12. # 1 "hello.c"
  13. # 1 "/usr/include/stdio.h" 1 3 4
  14. # 28 "/usr/include/stdio.h" 3 4
  15. # 1 "/usr/include/features.h" 1 3 4
  16. # 329 "/usr/include/features.h" 3 4
  17. ..............................
  18. 或 者执行:
  19. $ gcc -E hello.c -o hello.i
  20. $ vi hello.i
  21. 1 # 1 "hello.c"
  22. 2 # 1 "<built-in>"
  23. 3 # 1 "<command line>"
  24. 4 # 1 "hello.c"
  25. 5 # 1 "/usr/include/stdio.h" 1 3 4
  26. 6 # 28 "/usr/include/stdio.h" 3 4
  27. 7 # 1 "/usr/include/features.h" 1 3 4
  28. 8 # 329 "/usr/include/features.h" 3 4
  29. .......... < 中间部分略> ..................
  30. 929 # 844 "/usr/include/stdio.h" 3 4
  31. 930
  32. 931 # 2 "hello.c" 2
  33. 932
  34. 933 int main()
  35. 934 {
  36. 935         printf("hello, world!/n");
  37. 936
  38. 937         return 0;
  39. 938 }
  40. 可 见,将近1000行的代码,我们的只占了最末8行。

3.生成汇编语言文件 hello.s

  1. $ gcc -S hello.c -o hello.s
  2. $ ls
  3. a.out  hello  hello.c  hello.i  hello.s
  4. hello.s 就是新生成的文件
  5. 如下语句结果相同:
  6. $ gcc -S -o hello.s hello.c
  7. 如 下语句结果相同:
  8. $ gcc -S hello.c
  9. 也 可以采用前一步骤产生的中间文件生成汇编文件:
  10. $ gcc -S hello.i -o hello.s
  11. $ gcc -S -o hello.s hello.i
  12. $ gcc -S hello.i
  13. 生 成的汇编部分代码如下:
  14. $ vi hello.s
  15. 1         .file   "hello.c"
  16. 2         .section        .rodata
  17. 3 .LC0:
  18. 4         .string "hello, world!"
  19. 5         .text
  20. 6 .globl main
  21. 7         .type   main, @function
  22. 8 main:
  23. 9         leal    4(%esp), %ecx
  24. 10         andl    $-16, %esp
  25. 11         pushl   -4(%ecx)
  26. 12         pushl   %ebp
  27. // 注释:如果你熟悉,就可以对部分汇编优化以达到更好效果。

4.生成目标文件 hello.o

  1. $ gcc -c hello.c -o hello.o
  2. $ ls
  3. a.out  hello  hello.c  hello.i  hello.o  hello.s
  4. hello.o 就是新生成的目标文件:
  5. 如下语句结果相同:
  6. $ gcc -c -o hello.o hello.c
  7. 如 下语句结果相同:
  8. $ gcc -c hello.c
  9. 也 可以采用前面步骤产生的中间文件hello.i或hello.s来生成目标文件:
  10. $ gcc -c hello.i
  11. $ gcc -c hello.s
  12. 我 们可以用 objdump 查看 hello.o 的二进制码:
  13. $ objdump -s hello.o
  14. hello.o:     file format elf32-i386
  15. Contents of section .text:
  16. 0000 8d4c2404 83e4f0ff 71fc5589 e55183ec  .L$.....q.U..Q..
  17. 0010 04c70424 00000000 e8fcffff ffb80000  ...$............
  18. 0020 000083c4 04595d8d 61fcc3             .....Y].a..
  19. Contents of section .rodata:
  20. 0000 68656c6c 6f2c2077 6f726c64 2100      hello, world!.
  21. Contents of section .comment:
  22. 0000 00474343 3a202847 4e552920 342e312e  .GCC: (GNU) 4.1.
  23. 0010 31203230 30373031 30352028 52656420  1 20070105 (Red
  24. 0020 48617420 342e312e 312d3532 2900      Hat 4.1.1-52).

5. 采用中间级文件生成可执行程序

  1. $ gcc -o hello hello.i
  2. $ ./hello
  3. hello, world!
  4. $ gcc -o hello hello.s
  5. $ ./hello
  6. hello, world!
  7. $ gcc -o hello hello.o
  8. $ ./hello
  9. hello, world!

四、 静态库的生成
    linux下静态库的生成比较方便。在生成目标文件后用 ar 打包即可。在中大型项目中一个模块一般会做成一个静态库,以方便管理、提高编译、链接效率。
    本小节的展示针对 main.c、func1.c、func2.c三个文件

  1. /*
  2. * main.c
  3. */
  4. #include <stdio.h>
  5. extern int func1();
  6. extern int func2();
  7. int main()
  8. {
  9. int i;
  10. i = func1();
  11. printf("func1 return = %d/n",i);
  12. i = func2();
  13. printf("func2 return = %d/n",i);
  14. return 0;
  15. }

-----------------------------------------------------

  1. /*
  2. * func1.c
  3. */
  4. int func1()
  5. {
  6. return 100;
  7. }

-----------------------------------------------------

  1. /*
  2. * func2.c
  3. */
  4. int func2()
  5. {
  6. return 200;
  7. }

一 下是编译指 令:

  1. $ gcc -c func1.c
  2. $ gcc -c func2.c
  3. $ ls
  4. func1.c  func1.o  func2.c  func2.o  main.c
  5. func1.o 和 func2.o 是 我们生成的目标文件。打包指令如下:
  6. $ ar -r libfunc.a func1.o func2.o
  7. 我 们查看 libfunc.a 中的文件:
  8. $ ar -t libfunc.a
  9. func1.o
  10. func2.o
  11. 现 在用静态库和 main.c 共同生成目标程序:
  12. $ gcc -o main main.c libfunc.a
  13. $ ./main
  14. func1 return = 100
  15. func2 return = 200
  16. 和 我们的预期相符合。下面我们进入动态库。

五、动态库的生成
    linux下动态库的生成通过GCC选项实现。案例程序和静态库中的相同。一下是操作指令:

  1. 首 先我们生成目标文件,但是需要加编译器选项 -fpic 和链接器选项 -shared
  2. $ gcc -fpic -c func1.c                 注:许多地方动态库的编译是使用-fPIC选项  而不是小写-fpic
  3. $ gcc -fpic -c func2.c
  4. $ gcc -shared -o libfunc.so func1.o func2.o
  5. $ ls
  6. func1.c  func1.o  func2.c  func2.o  libfunc.so  main.c
  7. libfunc.so 就是我们生成的目标动态库。我们用动态库和 main.c 生成目标程序:
  8. $ gcc -o main main.c -L. -lfunc
  9. 注 意,我们用 -L. -lfunc 作为编译选项。-L. 表从当前目录查找需要的动态库,-lfunc 是动态库的调用规则。Linux系统下的动态库命名方 式是 lib*.so,而在链接时表示位 -l* , *是自己起的库名。下面我们运行它:
  10. $ ./main
  11. ./main: error while loading shared libraries: libfunc.so: cannot open shared object file: No such file or directory
  12. 提 示一个错误, 指示无法找到动态库。在linux下最方便的解决方案是拷贝libfunc.so到绝对目录 /lib 下。但是只有超级用户才有这个权限。另外一个方案 是更改环境变量 LD_LIBRARY_PATH。如下:
  13. $ $ export LD_LIBRARY_PATH=`pwd`
  14. $ ./main
  15. func1 return = 100
  16. func2 return = 200
  17. 运 行成功。现在我们更改动态库的函数而不重新链接。如下:
  18. 更改 func1.c 为:
  19. int func1()
  20. {
  21. return 101;
  22. }
  23. 更 改 func2.c 为:
  24. int func2()
  25. {
  26. return 202;
  27. }
  28. 重 新生成库:
  29. $ gcc -fpic -shared func1.c func2.c -o libfunc.so
  30. $ ./main
  31. func1 return = 101
  32. func2 return = 202
  33. 可 以看出,动态库已经更新了。

六、结束语
    本文简单介绍了linux下如何使用gcc进行编译程序、以及简 单的静态、动态库的生成。静态库提供了一种打包管理方案,而动态库使程序局部更新成为了可能,更重要的是,当有多份实例存在时,动态库可减小内存的消耗 (只占用一份代码空间)。
    对本系列知识感兴趣者可继续跟踪阅读后续文章:库的版本管理、GCC的编译选项、Makefile与自动化编译

在Linux下如何使用GCC编译程序、简单生成 静态库及动态库的更多相关文章

  1. 详细讲解 关于Linux静态库和动态库的分析

    基本概念 库有动态与静态两种,动态通常用.so为后缀,静态用.a为后缀. 例如:libhello.so libhello.a 为了在同一系统中使用不同版本的库,可以在库文件名后加上版本号为后缀,例如: ...

  2. Linux中的静态库与动态库

    什么是库文件? 库文件是事先编译好的方法的合集.比如:我们提前写好一些数据公式的实现,将其打包成库文件,以后使用只需要库文件就可以,不需要重新编写. Linux系统中: 1.静态库的扩展名为.a:2. ...

  3. Linux下Gcc生成和使用静态库和动态库详解(转)

    一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同( ...

  4. Linux下Gcc生成和使用静态库和动态库详解

    参考文章:http://blog.chinaunix.net/uid-23592843-id-223539.html 一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库 ...

  5. 【转】Linux下gcc生成和使用静态库和动态库详解

    一.基本概念 1.1 什么是库 在Windows平台和Linux平台下都大量存在着库. 本质上来说,库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不 ...

  6. Linux下GCC生成和使用静态库和动态库【转】

    本文转载自:http://www.cppblog.com/deane/articles/165216.html 一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库. 本 ...

  7. [转]Linux下用gcc/g++生成静态库和动态库(Z)

    Linux下用gcc/g++生成静态库和动态库(Z) 2012-07-24 16:45:10|  分类: linux |  标签:链接库  linux  g++  gcc  |举报|字号 订阅     ...

  8. linux 下多版本gcc 共存问题

    linux 下多版本gcc 共存问题 http://blog.csdn.net/isfirst/article/details/42296583 参考 http://blog.csdn.net/chi ...

  9. linux下scsi共享磁盘的简单搭建

    linux下scsi共享磁盘的简单搭建 Scsi 共享磁盘需要我先有空余的分区,或者可以在虚拟机里面添加一块磁盘,安装所需的软件我在虚拟机里面添加了一块硬盘,分了一个主分区,sdb1 1G,将这个用s ...

随机推荐

  1. python 内建类型

    ''' 数值 numbers 字符串 strings 列表 lists 字典 dictionaries 元组 tuples 文件 files 集合 sets ''' 1.1 序列的操作 所有序列类型都 ...

  2. 55.Android之AsyncTask介绍 (转)

    AsyncTask和Handler对比 1 ) AsyncTask实现的原理,和适用的优缺点 AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操 ...

  3. ubuntu16.04+cuda7.5

    0 安装了ubuntu16.04 GT980的显卡,安装了nvidia340的驱动 1 下载cuda7.5的.run文件 2 进入tty1,service stop lightdm 3 sudo sh ...

  4. wpf中textbox与textblock有什么区别

    textbox是windows.form控件,textblock是WPF控件. 功能类似,但后者功能更强,也节省系统资源 wpf是基于directx技术的系统,向后兼容性更好. textblock只用 ...

  5. PHP扩展编写、PHP扩展调试、VLD源码分析、基于嵌入式Embed SAPI实现opcode查看

    catalogue . 编译PHP源码 . 扩展结构.优缺点 . 使用PHP原生扩展框架wizard ext_skel编写扩展 . 编译安装VLD . Debug调试VLD . VLD源码分析 . 嵌 ...

  6. Consuming a RESTful Web Service

    本篇文章将介绍使用Spring来建立RESTful的Web Service. 我们通过一个例子来说明这篇文章:这个例子将会使用Spring的RestTemplate来从Facebook的提供的API中 ...

  7. django 提示ImportError: cannot import name json_response

    from json_response import JsonResponse, json_response as json_resp 使用的语句如上,其实并不是没有安装,只是需要升级一下 pip in ...

  8. CSS3系列四(Media Queries移动设备样式)

    viewport设置适应移动设备屏幕大小 viewport:允许开发者创建一个虚拟窗口并自定义其窗口的大小或缩放功能 <meta name="viewport" conten ...

  9. BZOJ3393:[USACO LPHONE] 激光通讯

    分层图+堆优化的dijkstra 将原图分为4层,分别是只向上,向下,向左,向右建立边,然后层与层之间的转移很好处理.稠密图,应该用堆优化的dijkstra. //OJ 1845 //by Cydia ...

  10. UVA11624Fire!(BFS)

    题目链接 题意:帮助joe走出一个大火蔓延的迷宫,其中joe每分钟可往上下左右四个方向之一走,所有着火的格子都会蔓延(空格与着火格有公共边,下一分钟这个空格也会着火).迷宫中有一些障碍格,joe和火都 ...