gcc编译隐藏规则
前言
Linux下C++的编译、链接以及包管理一文中提到,Linux系统本身和GCC编译器在针对包的管理上存在一定的配合。
具体来说体现在,GCC在进行编译时会默认在特定的系统目录下去寻找头文件和库文件,而这些特定的系统目录恰恰是包安装的位置。
本文就展开说说这些默认规则。
基本规则
在介绍默认规则之前,先来回忆一下gcc命令行的基础规则有哪些:1
gcc main.c function/head.c -I../header -L. -lvector -o main
上面是一个非常典型的gcc使用场景,什么CMakelists.txt,makefile,catkin_make,bazel之类的编译管理工具无论搞得再花里胡哨,最后还是要落到这样的gcc调用上来。
先来翻译一下它的含义:以当前目录下的main.c和function目录下的head.c为源文件,将上一级目录下的header目录作为头文件搜索的补充路径,讲当前目录作为库搜索的补充路径,并寻找名为libvector.so或libvector.a的库文件参与编译,生成一个名为main的可执行文件。
要完成以上翻译,需要知道的规则有:
- -I(大写i) flag用于添加头文件的补充搜索路径;
- -L flag用于添加库文件的补充搜索路径;
- -l(小写L) flag用于添加库文件的模糊搜索名称。之所以说是模糊搜索名称,是因为libvector.so,libvector.a都算匹配成功。如果刚好有重名的动静态库,那么优先选择动态库。
- -o flag用于指定编译结果的名称;
这便是gcc最常用,最基础的规则。其中可以注意到,上面一直在强调补充二字,这是因为gcc有一些默认的头文件和库文件搜索路径,不管你有没有在调用gcc时显式地指定,它都是会按照一定的顺序去搜索这些默认路径。
隐藏规则
头文件搜索路径及顺序
- 先在当前目录下找
- 如果找不到,然后在-Iflag指定的目录找
- 还是找不到,再到CPLUS_INCLUDE_PATH和C_INCLUDE_PATH两个环境变量指定的路径下去找。前者是g++用的,后者是gcc用的
- 还是找不到,最后到/usr/include和/usr/local/include等系统目录中找,这里再找不到就编译失败了
库文件搜索路径及顺序——编译时
- 先到-L指定的目录下找
- 找不到去环境变量LD_LIBRARY_PATH指定的路径下去找
- 还找不到就是去/lib和/usr/local/lib等系统目录中找,还找不到就链接失败了
动态库搜索路径及顺序——运行时
- 先去环境变量LD_LIBRARY_PATH指定的路径下去找
- 找不到去/etc/ld.so.cache文件中指定的路径下去找
- 最后到/lib和/usr/local/lib等系统目录中找,还找不到就链接失败了
ld.so.cache工作的机制是:在/etc/ld.so.conf.d/目录下有一些.conf文件(比如mylib.conf),这些.conf文件的内容是该库的所在地址,比如mylib.conf的内容是/usr/local/me/mylib.so。运行
ldconfig
命令会读取所有这些.conf文件的内容,并将其写到ld.so.cache文件中。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!