Linux之静态库、共享库
一、静态库和共享库的区别
- 静态库在编译的时候被加载,而共享库在执行之后才被加载
- 加载静态库编译所生成的可执行文件比使用共享库的方式要大
- 静态库以.a为后缀,共享库以.so为后缀
二、静态库的制作
- gcc -c add.c sub.c(编写源文件,gcc -c命令生成对应的目标文件add.o和sub.o)
- ar crs -o libmath.a add.o sub.o(ar命令归档目标文件,生成静态库libmath.a)
- gcc mian.c -L. -lmath(链接静态库libmath.a,编译生成可执行文件a.out)
三、动态库的制作
- gcc -c add.c sub.c(编写源文件,gcc -c命令生成对应的目标文件add.o和sub.o)
- gcc -fPIC-shared -o libmath.so add.o sub.o(-fPIC方式生成共享库文件libmath.so)
- gcc main.c -L. -lmath(链接共享库libmath.so,编译生成可执行文件a.out)
(1)在gcc编译生成可执行文件的时候,默认链接系统的共享库,但如果添加了-static选项则链接了系统的静态库,可执行文件会大很多;
(2)共享库.so可以通过callback调用应用程序中的函数app,因为动态链接器会将可执行文件和链接器本身的符号表合并到全局符号表中,当一个新的共享库.so被装载进来的时候,它的符号表也会被合并到全局符号表中,所以共享库.so是从全局符号表中找到应用程序的函数地址并调用的。但是加载共享库.so的时候却提示找不到函数app,因为ld链接的时候默认只导出共享库.so的符号,而不会导出应用程序的符号app;因此在编译可执行文件的时候需要用gcc -Wl,-E选项来将可执行文件中的全局符号导出到动态符号表中,那么其他调用主程序的符号时才可以找到;
应用程序找共享库的方式有四种:
- 环境变量LD_LIBRARY_PATH指定的共享库搜索路径
- 配置文件/etc/ld.so.conf中指定的共享库搜索路径(include /etc/ld.so.conf.d/*.conf)
- 默认的共享库搜索路径/lib
- 默认的共享库搜索路径/usr/lib
四、gcc命令常用选项
- -c(只生成可重定位目标文件.o)
- -o filename(指定输出文件的名字为filename)
- -g(生成调试信息,供gdb使用)
- -static(对于支持动态链接的系统,使用静态链接而不是动态链接)
- -I path(头文件包含目录,即在path目录下寻找相关的include文件)
- -L path(库文件包含目录,即在path目录下寻找相关的库文件)
- -lxx(链接库libxx.a或者libxx.so,比如若链接libm.so库则写成-lm)
- -std=xx(指定编译的语言标准,比如-std=c99或-std=c11)
- -Wall(输出错误和警告)
- -Werror(将警告视为错误输出)
- -Wl,option(将参数option作为后续链接器ld的参数)
- -Wl,rpath=path(指定非默认的共享库搜索路径,运行该程序时会在-rpath指定的目录下寻找共享库.so文件)
头文件来源:-I路径--->环境变量(C_INCLUDE_PATH、CPLUS_INCLUDE_PATH、OBJC_INCLUDE_PATH)--->内定目录(/usr/include、/usr/local/include等)
库文件来源:-L路径--->环境变量(LIBRARY_PATH)--->内定目录(/lib、/lib64、/usr/lib、/usr/lib64、/usr/local/lib、/usr/local/lib64)
五、未完待续~