linux下库和头文件的搜索顺序与编译运行链接

程序的编译链接过程如上图, 从源文件生成了目标文件和静态库,目标文件和静态库生成可执行文件,可执行文件运行时通过LD_LIBRARY_PATH查找加载动态库运行

1.目标文件、静态库、动态库文件的生成

目标文件xxx.oc的生成,使用 -c 选项,指定只生成而不链接

gcc -c xxx.c -o xxx.o

静态库的生成,需先生成目标文件,使用ar rcs命令对其做转换

gcc -c xx1.c -o xx1.o
gcc -c xx2.c -o xx2.o
ar rsc libxxx.a xx1.o xx2.o

动态库的生成,使用-shared要求生成动态库,通常还加上-fpic要求生成的代码地址无关,就是要动态库内部的使用相对偏移寻址,防止安全攻击

gcc xxx.c -fPIC -shared -o libxxx.so

2. 头文件的查找顺序

头文件查找顺序:
1.先搜索当前目录
2 然后搜索-I指定的目录
3.环境变量CPLUS_INCLUDE_PATH(c使用的是C_INCLUDE_PATH
4.最后搜索gcc/g++的内定目录
/usr/include
/usr/local/include
/usr/lib/gcc/x86_64-redhat-linux/4.1.1/include

3.库的查找顺序

  • 运行时动态库的查找顺序:

1.环境变量LD_LIBRARY_PATH

2./etc/ld.so.conf下所包含的路径

其中,关于ld.so.conf中,参见此文:

Linux的动态链接库绝大多数都在`/lib`和`/usr/lib`下,操作系统也会默认去这两个路径下搜索动态链接库。另外,`/etc/ld.so.conf`文件里可以配置路径,`/etc/ld.so.conf`文件会告诉操作系统去哪些路径下搜索动态链接库。这些位置的动态链接库很多,如果链接器每次都去这些路径遍历一遍,非常耗时,Linux提供了`ldconfig`工具,这个工具会对这些路径的动态链接库按照SONAME规则创建软连接,同时也会生成一个缓存Cache到`/etc/ld.so.cache`文件里,链接器根据缓存可以更快地查找到各个`.so`文件。每次在`/lib`和`/usr/lib`这些路径下安装了新的库,或者更改了`/etc/ld.so.conf`文件,都需要调用`ldconfig`命令来做一次更新,重新生成软连接和Cache。但是`/etc/ld.so.conf`文件和`ldconfig`命令最好使用root账户操作。非root用户可以在某个路径下安装库文件,并将这个路径添加到`/etc/ld.so.conf`文件下,再由root用户调用一下`ldconfig`。

  • 编译链接时,库查找顺序:

1.-L或 -Wl, rpath指定的路径

2.查找环境变量LIBRARY_PATH下的路径

3.查找 /etc/ld.so.conf 下包含的路径

4 /lib 和 /usr/lib

其中,-L和-Wl, rpath都能够显示的指定库所在的目录,但它们存在区别,参见此文:

-L指定的库路径,在动态链接的时候,库的路径信息不会被存到到目标文件中,运行时目标文件只能通过LD_LIBRARY_PATH以及ld.so.conf提供的路径查找,如果使用-Wl, rpath则库的路径会存到目标文件中,运行时目标文件会先去这个路径查找,找不到了,再去LD_LIBRARY_PATH和ld.so.conf中找

4. 链接静态库和动态库的优先级

直接使用-l查找路径的时候,gcc/g++默认优先链接动态库,找不到动态库后,才去找静态库

gcc xxx.c -o xxx -lopenssl // 链接openssl.so

要链接静态库就需要使用或者 -static 进行显示指定全都使用静态库

gcc xxx.c -o xxx -static -lopenssl // 链接libopenssl.a

也可以使用 -Wl,-Bstatic, 这个选项使用后,后续的-l都是去找静态库,但可以通过Wl,-Bdynamic

再指定后面的都是动态库

//连接 libxx1.a libxx2.a libxx3.so
gcc xxx.c -o xxx -WL,-Bstatic -lxx1 -lxx2 -WL,-Bdynamic -lxx3
posted @ 2019-12-06 10:52  woder  阅读(2386)  评论(0编辑  收藏  举报