最近在编写的一个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. static关键字总结

      static,即静态声明.它在 作用域.存储方式.生命周期 等各方面影响一个变量或函数.文章将从 局部变量.全局变量.普通函数.类的static成员(包括数据成员与成员函数)来总结static. ...

  2. Jenkins+CCNET的另类部署图

    最近公司的CI系统升级,从CCNET换成Jenkins进行搭建,原因是Jenkins支持所有语言,不再是单一的dotnet语言支持,并且以节点的形式能做分布式自动构建,非常节省配置成功. 而且从MSB ...

  3. FUSE 简介

    编译别人改过的一个 OpenWRT ,发现用到了一个叫 FUSE 的包.感兴趣了解一下. FUSE 是 Filesystem in USErspace 的简称.对于文件系统,经常安装系统.格式化 U ...

  4. MACOS 答题器,界面跳转

    国内OSX开发的资料实在少,甚至连一本开发的书都找不到… 更无语的是,苹果自家的开发文档Sample Code不仅还停留在OC版本,还是MRC的… 在这样的情况下,OSX开发还真得靠“想象力”… 网上 ...

  5. iOS 即时通讯SDK的集成,快速搭建自己的聊天系统

    现在的外包项目需求变态的各种各样,今天要做社交,明天要加电商,后天又要加直播了,这些系统如果要自己开发,除非大公司技术和人力都够,不然短时间是几乎实现不了的.所以学会灵活利用市面上的各种SDK是灰常重 ...

  6. HDU 1007 Quoit Design

    传送门 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem Des ...

  7. java连接数据源-读取tomcat数据源配置

    读取数据源配置,获取连接 1.配置数据源 D:\apache-tomcat-7.0.70\conf\context.xml <Resource name="jdbc/news" ...

  8. Python基本数据类型之set

    一.定义 set是一个无序且不重复的元素集合. 集合对象是一组无序排列的可哈希的值,集合成员可以做字典中的键.集合支持用in和not in操作符检查成员,由len()内建函数得到集合的基数(大小), ...

  9. 利用jar命令打包和解压

    常常在网上看到有人询问:如何把 java 程序编译成 .exe 文件.通常回答只有两种,一种是制作一个可执行的 JAR 文件包,然后就可以像.chm 文档一样双击运行了:而另一种是使用 JET 来进行 ...

  10. JS-Date对象

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>D ...