静态链接库.a
出于版权保护行为,将源文件编译但不链接生成.o文件,再用ar工具将多个.o文件归档成.a文件,该.a文件就被称为静态链接库。再发布.a和.h文件,h文件显示有.o中函数声明。用户即可知道库内有什么函数。用户使用的时候编译链接主函数时会来链接.a中相关功能函数,生成一个可执行文件。由于添加了库函数代码,最终用户可的执行程序较大。
动态链接库.so
动态链接库的后缀名是 .so(对应Windows中的.dll);编译时动态链接库的方式则不把库文件中的功能函数拷贝过来编译,而是在程序执行过程中再去操作系统指定路径去找该库文件。所以实际用户编译程序时比较小。特别是多个文件或应用程序去调用同一个库中函数,比较节约空间。
库函数的使用
GCC编译器模式使用的是动态链接库,如果要强制只用静态链接,用-static标识;
部分库函数链接时要使用-lxx来指定链接,如我们有一个libjpeg.a动态链接库,我们要链接时在makefile中添加时需要把lib省略,使用-ljpwg.a,-l后无空格。
如是动态链接库,还要使用-L来指定动态库的地址,-L后面有空格。
LDFLAGS := -ljpeg -L /opt/libdecode/lib
链接错误/警告:
xx.c :(.text + 0x123):xxxx;括号.text内容就说明是连接时出错,不是编译时出错。
使用标准库函数时,编译器只会默认在几个常用的函数库中查找,找不到则需要用户指定:
例如:gcc helloword.c -lm
lm:告诉连接器到libm中查找函数,
制作静态库
使用gcc -c 只编译不链接,生成.o文件,然后使用ar工具打包.a归档文件。
编写源文件 hello.c
gcc hello.c -o hello.o -c; // -o指定文件名,-c只编译不链接
ar -rc libhello.a hello.o; //ar:是linux工具链中的打包器;
-rc:创建静态链接库
libhello.a :库名不能随意起名,lib是固定格式开头,hello自定义名称,归档文件是执行后输出的文件;
使用静态库编译
gcc test.c -o test -lhello -L .
-o:重命名test
-lhello:是libhello库的缩写,因此静态库必须以lib开头;这是默认的规则。
-L.:大写的L 指定连接库路径; . 是说当前路径;
查看库文件中有哪些函数 nm:
nm libhello.a
动态库制作
编写库函数源码hello.c
只编译不连接,链接成动态库;
gcc hello.c -o hello -c -fPIC // -o指定.o文件名;-c只编译不链接;
-fPIC 编译成位置无关码,动态库只能是位置无关码,操作系统会随时调用。
gcc -o libhello.so hello.o -shared //-shared:链接成动态库
动态库编译
编写用户代码tset.c,包含动态库头文件;
gcc test.c -o test.o -lbhello -L . //编译时在指定目录找lbhello文件
动态库运行
相比静态库,动态库运行时有所不同,需要将动态库的路径告诉给操作系统。告诉操作系统可以有两种方法;
第1种:将动态库拷贝到系统默认库存放位置/usr/lib(避免混乱一般不使用)。
第2种:自定义存放位置,将路径导入到系统环境变量 LD_LIBRARY_PATH。操作系统在加载固定目录/usr/lib前会先在环境变量内指定的目录下去查找。
导出环境变量:export LD_LIBRARY_PATH = $LD_LIBRARY_PATH:需要新增的目录;
当前目录为 /home/hudaizhou/winshare/c_program/static_lible
查看环境变量:echo $LD_LIBRARY_PATH
分析文件引用的库
ldd test ;打印出来test都引用了哪些库。