在 Ubuntu 17.10 下与 rpath 的动态链接不起作用

Dynamic linking with rpath not working under Ubuntu 17.10

提问人:Kun Ren 提问时间:11/5/2017 最后编辑:Kun Ren 更新时间:12/12/2017 访问量:6081

问:

我构建了一个使用 Rcpp 并链接到第三方共享对象 () 的 R 包(该对象还链接到其他共享对象,例如在其自己的目录中)。为了确保它能够找到它所链接的那些共享对象,我将以下变量放入:libbarraopt.soliboptsrvr.so~/.Renviron

BARRA_OPS_HOME=${HOME}/bin/BarraOptimizer8.5

在包中,我创建了以下内容:src/Makevars

BARRA_LIB=$(BARRA_OPS_HOME)/lib/intel64
BARRA_INCLUDE=$(BARRA_OPS_HOME)/include
PKG_CXXFLAGS=-I$(BARRA_INCLUDE)
PKG_CFLAGS=-I$(BARRA_INCLUDE)
PKG_LIBS=-L$(BARRA_LIB) -Wl,-R,$(BARRA_LIB) -lbarraopt

在 Ubuntu 16.04 下,我可以成功构建、加载和使用该软件包,而不会出现任何问题。但是,当我在操作系统升级到 17.10 时测试完全相同的包时,可以构建该包,但无法加载,说:

g++ -std=gnu++11 -I/usr/share/R/include -DNDEBUG  -I"/home/renkun/R/x86_64-pc-linux-gnu-library/3.4/Rcpp/include"   -I/home/renkun/bin/BarraOptimizer8.5/include -fpic  -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c RcppExports.cpp -o RcppExports.o
** libs
g++ -std=gnu++11 -I/usr/share/R/include -DNDEBUG  -I"/home/renkun/R/x86_64-pc-linux-gnu-library/3.4/Rcpp/include"   -I/home/renkun/bin/BarraOptimizer8.5/include -fpic  -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c barraopt.cpp -o barraopt.o
g++ -std=gnu++11 -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o barraopt.so RcppExports.o barraopt.o -L/home/renkun/bin/BarraOptimizer8.5/lib/intel64 -Wl,-R,/home/renkun/bin/BarraOptimizer8.5/lib/intel64 -lbarraopt -L/usr/lib/R/lib -lR
installing to /tmp/Rtmpvbb6Io/devtools_install_42a342a07f84/barraopt/libs
* DONE (barraopt)
Error in dyn.load(dllfile) : 
  unable to load shared object '/home/renkun/Workspaces/barraopt/src/barraopt.so':
  liboptsrvr.so: cannot open shared object file: No such file or directory
Calls: suppressPackageStartupMessages ... <Anonymous> -> load_all -> load_dll -> library.dynam2 -> dyn.load
Execution halted

Exited with status 1.

似乎在这里没有效果。-Wl,-rpath

在装有 Ubuntu 16.04 的机器下,显示所有动态链接都已更正已解决。(ldd src/barraopt.soBARRA_OPS_HOME = /home/ken/bin/BarraOptimizer8.5)

linux-vdso.so.1 =>  (0x00007ffc89a16000)
libbarraopt.so => /home/ken/bin/BarraOptimizer8.5/lib/intel64/libbarraopt.so (0x00007f85dae49000)
libimf.so => /home/ken/bin/BarraOptimizer8.5/lib/intel64/libimf.so (0x00007f85da97f000)
libR.so => /usr/lib/libR.so (0x00007f85da346000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f85d9fc4000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f85d9dae000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f85d99e3000)
liboptsrvr.so => /home/ken/bin/BarraOptimizer8.5/lib/intel64/liboptsrvr.so (0x00007f85d7b10000)
libopsproto.so => /home/ken/bin/BarraOptimizer8.5/lib/intel64/libopsproto.so (0x00007f85d77a1000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f85d7497000)
libintlc.so.5 => /home/ken/bin/BarraOptimizer8.5/lib/intel64/libintlc.so.5 (0x00007f85d7249000)
libblas.so.3 => /usr/lib/libblas.so.3 (0x00007f85d6fe8000)
libreadline.so.6 => /lib/x86_64-linux-gnu/libreadline.so.6 (0x00007f85d6da1000)
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f85d6b31000)
liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f85d690f000)
libbz2.so.1.0 => /lib/x86_64-linux-gnu/libbz2.so.1.0 (0x00007f85d66fe000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f85d64e4000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f85d62dc000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f85d60d7000)
libgomp.so.1 => /usr/lib/x86_64-linux-gnu/libgomp.so.1 (0x00007f85d5eb5000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f85d5c98000)
/lib64/ld-linux-x86-64.so.2 (0x000055fb75088000)
libifcore.so.5 => /home/ken/bin/BarraOptimizer8.5/lib/intel64/libifcore.so.5 (0x00007f85d5961000)
libifport.so.5 => /home/ken/bin/BarraOptimizer8.5/lib/intel64/libifport.so.5 (0x00007f85d5732000)
libsvml.so => /home/ken/bin/BarraOptimizer8.5/lib/intel64/libsvml.so (0x00007f85d4e6d000)
libmosek64.so.7.0 => /home/ken/bin/BarraOptimizer8.5/lib/intel64/libmosek64.so.7.0 (0x00007f85d3c63000)
libiomp5.so => /home/ken/bin/BarraOptimizer8.5/lib/intel64/libiomp5.so (0x00007f85d396b000)
libprotobuf.so.6 => /home/ken/bin/BarraOptimizer8.5/lib/intel64/libprotobuf.so.6 (0x00007f85d3668000)
libbridge_common.so => /home/ken/bin/BarraOptimizer8.5/lib/intel64/libbridge_common.so (0x00007f85d3417000)
libsharc_xmlxproto.so => /home/ken/bin/BarraOptimizer8.5/lib/intel64/libsharc_xmlxproto.so (0x00007f85d31a4000)
libboost_thread.so.1.49.0 => /home/ken/bin/BarraOptimizer8.5/lib/intel64/libboost_thread.so.1.49.0 (0x00007f85d2f8a000)
libopenblas.so.0 => /usr/lib/libopenblas.so.0 (0x00007f85d0ef5000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007f85d0ccc000)
libxerces-c-3.1.so => /home/ken/bin/BarraOptimizer8.5/lib/intel64/libxerces-c-3.1.so (0x00007f85d07c4000)
libgfortran.so.3 => /usr/lib/x86_64-linux-gnu/libgfortran.so.3 (0x00007f85d0499000)
libnsl.so.1 => /lib/x86_64-linux-gnu/libnsl.so.1 (0x00007f85d027f000)
libquadmath.so.0 => /usr/lib/x86_64-linux-gnu/libquadmath.so.0 (0x00007f85d0040000)

但是,在 Ubuntu 17.10 下,使用相同的源显示共享对象链接即使已隔离,也无法解析:(lddlibbarraopt.so-Wl,-rpathBARRA_OPS_HOME = /home/renkun/bin/BarraOptimizer8.5)

linux-vdso.so.1 =>  (0x00007ffe067f5000)
libbarraopt.so => /home/renkun/bin/BarraOptimizer8.5/lib/intel64/libbarraopt.so (0x00007f3dc5f0c000)
libR.so => /usr/lib/libR.so (0x00007f3dc58e4000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f3dc555e000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f3dc5208000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f3dc4ff1000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3dc4c11000)
liboptsrvr.so => not found
libopsproto.so => not found
libblas.so.3 => /usr/lib/x86_64-linux-gnu/libblas.so.3 (0x00007f3dc49b6000)
libreadline.so.6 => /lib/x86_64-linux-gnu/libreadline.so.6 (0x00007f3dc4770000)
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f3dc44fe000)
liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f3dc42d8000)
libbz2.so.1.0 => /lib/x86_64-linux-gnu/libbz2.so.1.0 (0x00007f3dc40c8000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f3dc3eab000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f3dc3ca3000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f3dc3a9f000)
libgomp.so.1 => /usr/lib/x86_64-linux-gnu/libgomp.so.1 (0x00007f3dc3870000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f3dc3651000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3dc6526000)
libopenblas.so.0 => /usr/lib/x86_64-linux-gnu/libopenblas.so.0 (0x00007f3dc13ab000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007f3dc1182000)
libgfortran.so.4 => /usr/lib/x86_64-linux-gnu/libgfortran.so.4 (0x00007f3dc0da3000)
libquadmath.so.0 => /usr/lib/x86_64-linux-gnu/libquadmath.so.0 (0x00007f3dc0b63000)

看起来只有与正确的路径链接,但它链接的共享对象丢失了。libbarraopt.so

我想知道我的构建配置可能有什么问题,在 17.10 发布的工具链下被破坏。尽管使用全局配置可以解决此类问题,但我不喜欢,因为它所依赖的某些配置与操作系统附带的版本冲突。我宁愿使用本地配置的版本,而不影响全局配置。ldconfig.so

R Makefile G++ RCPP 动态链接

评论

0赞 Dirk is no longer here 11/5/2017
好吧,刚到家......但让我向你保证,就在本周,我设置了一个低于 17.04 的新项目,它按预期工作......一个更小的例子可能会减少在这里帮助你的障碍。-rpath

答:

13赞 Employed Russian 11/12/2017 #1

似乎 -Wl,-rpath 在这里无效。

可能发生的情况是,更新的链接器发出动态标记,旧链接器发出 。(也有可能你的旧链接器是GNU-ld,而新的链接器是Gold。DT_RUNPATHDT_RPATH

首选为更正确的路径,并且会影响二进制文件本身的搜索路径,但不会影响任何依赖库的搜索路径。DT_RUNPATH

具有全局效果,类似于将目录添加到环境变量中。DT_RPATHLD_LIBRARY_PATH

您可以通过以下方式进行验证。readelf -d a.out | grep 'R.*PATH'

如果您确实看到 vs. 区别,实际上正在使用 Gold,您可以强制使用“旧”行为(最近也添加了它,因此它应该适用于任何一个链接器)。RPATHRUNPATH-Wl,--disable-new-dtagsGNU ld--disable-new-dtags

评论

0赞 Kun Ren 11/12/2017
是的,而不是出现在 ELF 中。就我而言,这就是我需要的。RUNPATHRPATHRPATH
0赞 Kun Ren 11/12/2017
看起来 Ubuntu 16.04 附带的默认行为与 Ubuntu 17.10 的默认行为不同。我查看了指向的两个位置,它们都指向但版本不同。是一个和另一个还是只是版本中断?ld/usr/bin/ldx86_64-linux-gnu-ldGNU-ldGold
1赞 Steve Lorimer 12/12/2017
@EmployedRussian这篇博文底部的评论提到DT_RPATH被认为是 ELF 规范中的缺陷。如何将传递依赖项传播到传递依赖项?“修复”是在依赖项本身上设置的吗?有没有更好的方法?TIA。RUNPATHRUNPATH
1赞 Employed Russian 12/12/2017
@SteveLorimer 是的:这个想法是,每个 ELF 映像都应该被构建为正确描述它自己所需的运行时路径和它自己的依赖关系,而不是依赖于它被加载到哪个“主”应用程序中。设置每个传递依赖项是实现此目的的一种方法。RUNPATH
1赞 Employed Russian 8/23/2018
@YitzikC 使用标志。-Wl,--disable-new-dtags