2

C++ 的链接问题

 3 years ago
source link: https://zhiqiang.org/coding/link-in-cpp.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

C++的链接分为两部分,一个是编译时,一个是运行时。但运行时的行为也收到编译参数的影响。

1. 编译时链接

基本就两个参数,-l-L

  • -l 编译时要链接的库(包括动态链接库.so和静态链接库.a),注意库的顺序,被依赖的放在后面。
  • -L查询链接库的位置,编译器将依次查找。(/usr/lib之类的系统位置不用写)。

一个例子:

g++ ... -l folly -l boost_system -L /opt/lib

2. 运行时链接

编译时,静态链接库.a文件将直接被合并,因此运行时链接只涉及动态链接库.so文件。

执行ldd your_file可以查看指定文件运行时所需要链接的文件以及是否链接到指定位置。如果出现Not found或者链接到不正确位置,需要考察以下两个设置对象。

2.1. 系统环境变量LD_LIBRARY_PATH

链接程序首先考虑系统的环境变量LD_LIBRARY_PATH,从这里面设置的目录列表依次查找所需要的库文件。

下面命令可以查看当前设置的(用:隔开的)目录列表:

echo $LD_LIBRARY_PATH

下面命令可以设置该列表:

export LD_LIBRARY_PATH=~/lib:$LD_LIBRARY_PATH

注意将自己的目录放在最前面,多个目录用:隔开,并且包含原有的$LD_LIBRARY_PATH,以免破坏其它程序的设置。

该命令设置只会对当前窗口有效,新开窗口需要重新设置。如果需要总是有效,可考虑下面方法:

  • 如果想对所有用户生效,可放在/etc/environment文件里(需 ROOT 权限)。
  • 如果想对当前用户生效,可放在~/.bashrc或者~/.zshrc等启动配置文件。

2.2. 程序内置参数RUNPATH

如果链接程序在系统环境变量LD_LIBRARY_PATH找不到指令的库,此时会参考程序内置参数RUNPATH。下面命令可以查看该设置:

readelf -d your_file | grep RUNPATH

这个参数的设置在编译环节,即常见的-Wl,rpath

g++ ... -Wl,rpath=dir1 -Wl,rpath=dir2

2.3. 程序内置参数DT_RPATH

内置参数DT_RPATH是很老的-Wl,rpath行为,现在已经改成了RUNPATHDT_RPATH的区别在于它的优先级还在系统设置LD_LIBRARY_PATH之前。下面命令可查看该设置

readelf -d your_file | grep DT_RPATH

设置方法为-Wl,rpath配上-Wl,disable-new-dtags选项:

g++ ... -Wl,rpath=dir1 -Wl,rpath=dir2 -Wl,disable-new-tags

2.4. 还是找不到库?

有时候,通过上面方法设置了合适的路径和参数,查看路径和参数也都正常,但还是提示找不到,比如报「libboost_thread.so.xxx.xxx.xxx: cannot open shared object file: No such file or directory」错误。

我碰到的一次,解决方法是执行:

sudo ldconfig /opt/lib/ 

其中/opt/lib换成你的 boost 的安装路径。本质是通过ldconfig刷新缓存。

Q. E. D.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK