linux静态库和动态库
函数库是常用公共函数的集合,分为动态库和静态库。
静态库:程序编译时被链接到目标文件中,程序运行时就不需要此函数库的存在。(不推荐,会重复链接库)
动态库:程序编译时不链接到目标文件中,程序运行时才链接,所以需要函数库的存在。(推荐方式)
1:静态库
./test/libhello/hello1.c
#include <stdio.h> void print1() { printf("hello1****\n"); }
./test/libhello/hello2.c
#include <stdio.h>
void print2()
{
printf("hello2****\n");
}
./test/test.c
#include<stdio.h>
extern void print1();
extern void print2();//避免 warning: implicit declaration of function "function name"
int main(int argc,char **argv) { print1(); print2(); return 0; }
1.1 将库文件(hello1.c,hello2.c)编译为.o文件
./test/libhello:
gcc -c hello1.c hello2.c --> hello1.o hello2.o
-c : 只编译不链接
1.2 用.o文件创建静态库
静态库命名规则:lib+库名.a 比如要创建库hello,则静态库名字必须为libhello.a
使用命令:
./test/libhello:
ar -r libhello.a hello1.o hello2.o --> libhello.a
1.3 使用静态库
test.c文件需要此静态库,只需要在编译test.c时gcc链接此静态库,静态库中的函数就会在目标文件中声明。
./test:
gcc -o test test.c -L ./libhello -lhello --> test
-L:指定gcc在什么位置去链接hello库文件,不指定默认在/usr/lib中去找
-l(库名):库名hello就对应了静态库libhello.a
因为链接的是静态库,编译时库函数已经被链接进了目标文件test中,所以删除库文件libhello.a后test程序还是可以正常运行.
2:动态库
2.1 用.o文件生成动态库
动态库命名规则:lib+库名.so 比如要创建库hello,则静态库名字必须为libhello.so
使用命令:
./test/libhello:
gcc -shared -fPCI -o libhello.so hello1.o hello2.o --> libhello.so
cp libhello.so /usr/lib (因为动态库是运行时才链接的,链接的默认位置是‘/usr/lib’,所以将.so拷贝至/usr/lib)
2.2 使用动态库
./test:
gcc -o test test.c -L ./libhello -lhello
*:也可以在编译的时候指定链接的动态库的位置:gcc -o test test.c -L ./libhello/ -lhello -Wl,-rpath,./libhello/
这样就不用把库文件拷贝到/usr/lib目录下,目标程序会自动去./libhello文件下去链接
删除库文件libhello.so执行将出错:
error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory
3:总结
1:当静态库和动态库同名时(libhello.a和libhello.so),默认使用的是动态库
2:当一个库文件中有两个同名函数时,应用程序默认链接最前面哪个(比如hello1.o有print(),hello2.o有print(),在制作libhello.a时,ar -f libhello.a hello1.o hello2.o 这时会使用hello1.c中的print()函数)-->(在制作动态库时会提示命名冲突multiple definition of `print')