linux下制作静态库与动态库
我们在编写程序的过程过有可能会调用到不是我们自己写的函数,这里我称其为外部的函数,比如在写C语言程序的时候,你会调用到printf函数用于调试输出等,还有可能是这个情况,你自己写的一些通用用途的函数,你在软件项目中有多处地方要调用这些函数,这样的话做成库函数会比较合适,其他进程只需包含这个库和头文件就可以使用这些函数了。库函数分两种,一种是静态库,另一种则是动态库,在程序执行过程中对于静态库,它是直接包含到可执行程序中的,通俗的说就是不管要不要调用都先包含编译进来,而对于动态库,它是在程序执行的时候动态地包含要使用的库,同样通俗的说就是要调用的时候再临时的去动态库里取。
1. 链接方式:
1.1 静态链接:编译时以-static选项指明静态编译方式
优点:生成的可执行程序对环境的依赖性小,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。
缺点:因为所有函数都被编译进可执行程序,所以目标文件比较偏大,占用空间,还有一点就是当静态函数库改变了,那么你的程序必须重新编译。
例:以世界上最经典的例子hello.c来说明静态链接方式:gcc hello.c -static -o hello_static,这个编译例子的意思是将hello.c程序以静态链接方式编译生成hello_static可执行程序。
1.2 动态链接:当不特别指明是-static静态编译时,系统默认是以动态链接方式编译目标
优点:因为是动态编译,所以函数并没有实际编进可执行文件中,程序执行到相关函数时才调用该函数库里的相应函数,所以动态链接方式生成的可执行程序体积比较小,而且动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。
缺点:对环境的依赖比较大,由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。
例:gcc hello.c -o hello_share,这个编译例子的意思是将hello.c程序默认以动态链接方式编译生成hello_share可执行程序。
2. 制作静态链接库
在linux中,静态库的命名规则是:lib[库名].a。假设对于一个现有写好的程序mylib.c,现在把这个源文件编译成testlib库文件,即libtestlib.a。只需如下两个步骤OK。
gcc -c mylib.c -o mylib.o (-c编译但不链接)
ar rc libtestlib.a mylib.o (ar rc 创建一个归档文件,通常用于创建静态库)
3. 动态库的使用
假设现在hello.c文件要用到上面这个库libtestlib.a的函数,详见在以下三种情况中的使用:
3.1 库与头文件(假设该库有对应的"*.h"文件,下同)均在当前源文件的同一目录下
gcc -o hello_exe hello.c libtestlib.a (./hello_exe 可直接运行)
3.2 库与头文件在指定目录/opt下
gcc -o hello_exe hello.c -L/opt -ltestlib -I/opt (前一个"-l"是小写的"-L",后一个"-l"是大写的"-i",具体含义可见我 的另一篇博文"Linux之gcc的使用")
3.3 库与头文件分别在系统默认搜索路径下
在linux中,系统有一些库和头文件的默认搜索目录,比如标准输入输出头文件"stdio.h",当然你也完全可以把自己编译的静态和动态库及相应的头文件加入到那些目录中,这样就可以直接像如下方式使用库了。
linux下系统默认搜索的库文件*.a、*.so搜索路径:/lib /usr/lib /usr/local/lib
linux下系统默认搜索的头文件*.h搜索路径:/usr/include
mv libtestlib.a /lib (把库加入到系统默认搜索目录)
gcc -o hello_exe hello.c -ltestlib
4. 制作动态链接库
在linux中,动态库的命名规则是:lib[库名].so。假设对于一个现有写好的程序mylib.c,现在把这个源文件编译成testlib库文件,即libtestlib.so。只需如下一步OK。
gcc -shared mylib.c -o libtestlib.so
5. 静态库的使用(分以下三种情况)
假设现在hello.c文件要用到上面这个库libtestlib.so的函数,详见在以下三种情况中的使用:
5.1 库与头文件均在当前源文件的同一目录下
gcc -o hello_exe hello.c libtestlib.so (./hello_exe
可直接运行)
5.2 库与头文件在指定目录/opt下
gcc -o hello_exe hello.c -L/opt -ltestlib -I/opt
注:5.1和5.2能编译通过生成可执行文件hello_exe,但是运行时会出错:编译时找到了库函数,但链接时找不到库。解决方法可通过环境变量LD_LIBRARY_PATH指定动态库搜索路径(当通过该环境变量指定多个动态库搜索路径时,路径之间用冒号":"分隔),比如这里需要执行操作:#export
LD_LIBRARY_PATH=./:/opt:$LD_LIBRARY_PATH,把当前目录加入搜索路径。
5.3 库与头文件分别在系统默认搜索路径下(同3.3)
gcc -o hello_exe hello.c -ltestlib (编译运行都不会报错)
问题:有个问题出现了?我们前面的静态库也是放在/lib下,那么连接的到底是动态库还是静态库呢?
答:当静态库与动态库重名时,系统会优先连接动态库,或者我们可以加入-static指定使用静态库。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。