writing and using libraries
几乎所有的程序都链接一个或多个库。当你运行gcc的时候,系统会默认添加libc库,运行g++的时候会加入stdc++库。库的出现大大增强了程序的可复用性,便于管理。库分为静态库和动态库。使用静态库,程序会变大(加入整个静态库的代码),也很难升级(重新编译连接),但是部署很方便(不需要额外的库),使用动态库,程序会小一点,也很容易升级,但是部署却不方便。
Archive(static library)
其实静态库就是简单的把目标文件打包到一个单独的文件中, 生成的方式比较简单
$ ar cr libxxx.a lib1.o lib2.o
Shared Library
动态库也是由一组目标文件打包而成,类似于静态库。但是这里还是有很大的差别。当动态库链接到程序中,程序并不包含动态库中的代码,而仅仅是引用这个动态库,那么这样的话所有的程序都可以共享同一个动态库,这是和静态库最大的区别。
第二个最大的区别是当编译动态库的时候会使用-fPIC
如 gcc -c -fPIC test.c
加入PIC(Position-Independent Code) 的目的是为了让编译器知道test.o是作为动态库的目标文件。为什么需要这个?首先静态库在编译时就已经把库中的所有符号都添加到程序中,那么这个符号的地址已经固定在程序中,而动态库中所有符号的地址因为每次载入内存而不同,可以把它看作是相对地址,所以加入fPIC就是为了处理这种情况。
动态库静态库的选择
系统默认情况下会先搜索动态库,如果没有找到,再搜索静态库。如果只想使用静态库,加入-static选项。
动态库搜索路径
在动态库的存放问题上,Linux提供了这么几个位置
a)-wl,-rpath,./path1:/path2
在生成动态库的时候加入这个参数。
b)LD_LIBRARY_PATH环境变量
c)ld.so.conf
在ld.so.conf中配置路径,也可以在/etc/ld.so.conf.d/添加自己的路径。修改完成系统并没有生效,需要运行ldconfig来把ld.so.conf的修改更新到ld.so.cache中,这样系统才能识别。
e) /lib, /usr/lib
那么程序在加载动态库的时候,它的搜索顺序就是按上面的顺序来搜索的。
动态库版本
动态库的版本是用来处理兼容系问题的,当库有更新,原来的程序还可以使用低版本的库,而新程序可以使用新的库,不会由于库版本更新而出现兼容性问题。
格式为:lib + name + .so + ( .major .version .number)
$ g++ -shared -Wl,-soname,libhello.so.2 -o libhello.so.2.0 hello.o
$ ldconfig -v -n .
$ ln -sf libhello.so.2.0 libhello.so
动态库的依赖关系
一个库往往会依赖于其他库,库和库之间就构成了一种依赖关系。
一个程序引用了哪些动态库通过ldd工具查看。
几乎所有的程序都链接一个或多个库。当你运行gcc的时候,系统会默认添加libc库,运行g++的时候会加入stdc++库。库的出现大大增强了程序的可复用性,便于管理。库分为静态库和动态库。使用静态库,程序会变大(加入整个静态库的代码),也很难升级(重新编译连接),但是部署很方便(不需要额外的库),使用动态库,程序会小一点,也很容易升级,但是部署却不方便。
Archive(static library)
其实静态库就是简单的把目标文件打包到一个单独的文件中, 生成的方式比较简单
$ ar cr libxxx.a lib1.o lib2.o
Shared Library
动态库也是由一组目标文件打包而成,类似于静态库。但是这里还是有很大的差别。当动态库链接到程序中,程序并不包含动态库中的代码,而仅仅是引用这个动态库,那么这样的话所有的程序都可以共享同一个动态库,这是和静态库最大的区别。
第二个最大的区别是当编译动态库的时候会使用-fPIC
如 gcc -c -fPIC test.c
加入PIC(Position-Independent Code) 的目的是为了让编译器知道test.o是作为动态库的目标文件。为什么需要这个?首先静态库在编译时就已经把库中的所有符号都添加到程序中,那么这个符号的地址已经固定在程序中,而动态库中所有符号的地址因为每次载入内存而不同,可以把它看作是相对地址,所以加入fPIC就是为了处理这种情况。
动态库静态库的选择
系统默认情况下会先搜索动态库,如果没有找到,再搜索静态库。如果只想使用静态库,加入-static选项。
动态库搜索路径
在动态库的存放问题上,Linux提供了这么几个位置
a)-wl,-rpath,./path1:/path2
在生成动态库的时候加入这个参数。
b)LD_LIBRARY_PATH环境变量
c)ld.so.conf
在ld.so.conf中配置路径,也可以在/etc/ld.so.conf.d/添加自己的路径。修改完成系统并没有生效,需要运行ldconfig来把ld.so.conf的修改更新到ld.so.cache中,这样系统才能识别。
e) /lib, /usr/lib
那么程序在加载动态库的时候,它的搜索顺序就是按上面的顺序来搜索的。
动态库版本
动态库的版本是用来处理兼容系问题的,当库有更新,原来的程序还可以使用低版本的库,而新程序可以使用新的库,不会由于库版本更新而出现兼容性问题。
格式为:lib + name + .so + ( .major .version .number)
$ g++ -shared -Wl,-soname,libhello.so.2 -o libhello.so.2.0 hello.o
$ ldconfig -v -n .
$ ln -sf libhello.so.2.0 libhello.so
动态库的依赖关系
一个库往往会依赖于其他库,库和库之间就构成了一种依赖关系。
一个程序引用了哪些动态库通过ldd工具查看。
ldd显示当前程序引用动态库的情况,这可以清楚显示程序在当前系统中库的完整情况,以及当前所使用动态库的版本。