Linux下c/c++头文件和库文件的查找路径

简介

这是个相当基础的话题,平时也觉得知道一点。如头文件会先在当前目录查找,如果未找到会查找系统目录。

但当问题出现时,还是有点不知所措,对所谓的“系统目录”一知半解,很难把它们的清楚完整地梳理出来。

借此时机,梳理一下。

头文件

一般有两种形式的写法:双引号和尖括号,如下:

#include <iostream>
#include "demo.h"

当然也可以直接写绝对路径,那就不会有查找路径的问题了。

它们查找路径的顺序是有区别的,双引号形式会查找当前目录,而尖括号形式不会,具体查找顺序为:

  1. 当前目录(仅双引号形式)
  2. 编译时指定的头文件目录(由gcc -I参数指定)
  3. 系统环境变量 CPLUS_INCLUDE_PATH(c++头文件)或 C_INCLUDE_PATH(c头文件)指定的目录
  4. gcc默认目录:/usr/include;/usr/local/include;/usr/lib/gcc/x86_64-linux-gnu/5/include(注:最后一个路径是gcc程序的库文件地址,各个用户的系统上可能不一样)

如果各目录下存在相同的文件,则先找到哪个就使用哪个,这时顺序很重要。特别注意,尖括号形式不查找当前目录。

gcc的默认目录与安装gcc时指定的–prefix有关,该值可通过 gcc -v查看,具体的目录可通过 echo | g++ -v -x c++ -E -查看,如下:

#include "..." search starts here:
#include <...> search starts here:
 /usr/include/c++/5
 /usr/include/x86_64-linux-gnu/c++/5
 /usr/include/c++/5/backward
 /usr/lib/gcc/x86_64-linux-gnu/5/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/5/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include

知道了头文件的查找规则,查找问题也就得心应手了。

添加路径到头文件默认搜索路径

注意,除非必要,一般不建议这样做。比较好的方式是写入到CMakeLists或者Makefile中。

  • 一次性生效,命令行输入即可,只对当前shell生效,重新登录消失:

c++: export CPLUS_INCLUDE_PATH=xxx:$CPLUS_INCLUDE_PATH
c: export C_INCLUDE_PATH=XXXX:$C_INCLUDE_PATH

  • 用户级生效:

修改用户的 ~/.bashrc,在文件最后添加上述命令。执行source ~/.bashrc 或者重新登录生效。

  • 全局级生效:

修改/etc/profile 文件,在文件最后添加上述命令,运行 source /etc/profile 后生效。对所有用户生效。

库文件

头文件用于编译,库文件用于链接,编译通过了,还要链接通过。链接时库文件的查找顺序如下:

  1. 编译时指定的库文件目录(由gcc -L参数指定)
  2. 环境变量LIBRARY_PATH指定的目录
  3. 系统默认目录:/lib; /usr/lib; /usr/local/lib

一般用户安装的库会安装在/usr/local/lib,系统自带的库位于/lib; /usr/lib,用户自己编译的库可能就要使用-L参数指定了。

编译时通过了,还会有一个问题,就是运行动态库的使用。因为动态库是运行时加载的,所以还会有一个查找的顺序:

  1. 编译时指定的动态库搜索路径(通过gcc 的参数"-Wl,-rpath,"指定。当指定多个动态库搜索路径时,路径之间用冒号:分隔)
  2. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径(路径之间用冒号:分隔)
  3. 配置文件/etc/ld.so.conf中指定的动态库搜索路径
  4. 默认的动态库搜索路径/lib:/usr/lib

特别注意,库文件的查找默认是不查找当前目录的,也就是说,即使使用的库位于同一个目录内,也需要指定才能指定。

所以,当下次遇到下面这个错误时,就容易找到原因了:

./a.out: error while loading shared libraries: demo.so: cannot open shared object file: No such file or directory

添加路径到库文件默认搜索路径

注意,除非必要,一般不建议这样做。比较好的方式是写入到CMakeLists或者Makefile中。

与头文件默认路径的添加方法类似,添加的命令如下:

#动态链接库搜索路径:
export LD_LIBRARY_PATH=XXX:$LD_LIBRARY_PATH
#静态链接库搜索路径:
export LIBRARY_PATH=XXX:$LIBRARY_PATH

三个维度的生效范围同头文件。

总结

一知半解能应付照猫画虎式写代码,但是一旦写错,出现问题,就无所适从。

解决问题的根本还是要彻底弄明白事情的来龙去脉,这样才能抽丝剥茧,处理问题游刃有余。

一个再简单不过的问题依然如此,对于复杂的问题,更需要静下心来,琢磨透彻了。

  • 43
    点赞
  • 114
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值