四时宝库

程序员的知识宝库

C++“准标准库”boost的源码编译RPATH设置方法

作为C++的“准标准库”——boost,相信作为C++研发人员应该大都有所耳闻。如果在这之前都没有了解或者听说过,建议花点时间了解一下,对于C++的研发效率应该大有帮助。

一、背景

作为boost库的多年老友,前一段时间偶然发现基于源码编译的boost库有个问题,那就是使用ldd libboost_regex.so命令查看链接库情况时,竟然出现了多个icu4c库的not found信息,具体如下:

linux-vdso.so.1 => (0x00007ffc079f8000)

librt.so.1 => /lib64/librt.so.1 (0x00007f6111156000)

libicudata.so.74 => not found

libicui18n.so.74 => not found

libicuuc.so.74 => not found

libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f6110e4e000)

libm.so.6 => /lib64/libm.so.6 (0x00007f6110b4c000)

libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f6110936000)

libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f611071a000)

libc.so.6 => /lib64/libc.so.6 (0x00007f611034c000)

/lib64/ld-linux-x86-64.so.2 (0x00007f611135e000)

二、想要达到的目的

我们知道在使用CMake进行代码编译时,可以通过LINK_DIRECTORIES关键字来设置待链接库文件的路径,同时使用SET(
CMAKE_INSTALL_RPATH_USE_LINK_PATH ON)
选项把共享库的编译搜索路径也加入到运行搜索路径中。这样一来,实际程序在运行时不需要配置LD_LIBRARY_PATH、profile.d等系统环境,实现对环境的透明。同时也可以避免存在相同链接库的多个版本时,程序依然可以正确链接特定位置的目标版本,因为RPATH的优先级高于其它环境变量,可以强制共享库的搜索路径。

之前使用boost库没有链接库问题,是因为实际使用前重新设置了环境变量,让boost库可以快速找到所需的icu4c库所在位置。那么问题来了,如何让源码编译出来的boost库搜索相关共享库(如前述的icu4c库)也采用类似CMake的RPATH方式,避免实际运行时需要修改环境变量?让我们接下来继续进行目标的达成。

三、具体操作

前期采用了下列多种方式依然无法达成目标:

1. 修改
tools/build/example/user-config.jam
文件,添加下列内容强制指明icu4u的库路径,具体如下:

using icu4c : 74.1 : /myapp/icu4c : /myapp/icu4c/include : /myapp/icu4c/lib ;

2. 执行bootstrap.sh命令时附加参数--with-icu=/myapp/icu4c设置icu4c位置。

这个命令有个地方需要注意,/myapp/icu4c目录下的include子目录必须与安装icu4c的原始目录层级一致,否则boost会找不到icu4c的头文件而出现has_icu : no字样而不会使用icu4c。

3. 执行b2命令时增加libray_path=/myapp/icu4c/lib参数,

最终,通过执行b2命令时增加linkflags="-Wl,-rpath -Wl,/myapp/icu4c/lib -Wl,--disable-new-dtags"参数得以解决问题,相关参数说明如下:

1. -Wl,-rpath

传递RPATH给链接器。

2. -Wl,/myapp/icu4c/lib

指定运行时库搜索路径。

3. -Wl,--disable-new-dtags

强制使用 RPATH(高优先级)。

此时再使用ldd liboost_regex.so命令查看链接库情况时,一切正常,具体如下:

linux-vdso.so.1 => (0x00007ffe3695f000)

librt.so.1 => /lib64/librt.so.1 (0x00007fd49af8e000)

libicudata.so.74 => /myapp/icu4c/lib/libicudata.so.74 (0x00007fd499230000)

libicui18n.so.74 => /myapp/icu4c/lib/libicui18n.so.74 (0x00007fd498edb000)

libicuuc.so.74 => /myapp/icu4c/lib/libicuuc.so.74 (0x00007fd498cc1000)

libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007fd4989b9000)

libm.so.6 => /lib64/libm.so.6 (0x00007fd4986b7000)

libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fd4984a1000)

libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fd498285000)

libc.so.6 => /lib64/libc.so.6 (0x00007fd497eb7000)

libdl.so.2 => /lib64/libdl.so.2 (0x00007fd497cb3000)

/lib64/ld-linux-x86-64.so.2 (0x00007fd49b196000)

我们再通过readelf命令进行查看确认,可以看到RPATH信息,如下:

readelf -d libboost_regex.so | grep RPATH

0x000000000000000f (RPATH) Library rpath: [/myapp/icu4c/lib]

至此,我们达到了本文的目的,实现了boost库的源码编译设置RPATH。

当然,从v1.85.0版本的boost新增了cmake编译方式,可能就不需要这么麻烦了,使用前述简单的cmake机制就可以实现目标,但是因为个人还没有用过v1.85.0及其以上的新版本,具体细节就不再说明。但是有一点需要提醒一下,支持cmake编译的boost库源码包与不支持cmake编译的源码包不是同一个源码包,避免下载错误导致无法达成所愿。

四、联系

如果您在操作中遇到疑问或有其他想法,欢迎联系我,我会尽快回复并提供帮助!

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接