带有运行路径的C ++二级依赖项解析 [英] c++ secondary dependency resolution with runpath
问题描述
我有以下问题:
我正在尝试使用默认的gnu编译器(gcc-7)和可用的链接器版本在Ubuntu18上构建软件.
I am trying to build software on an Ubuntu18 by using the default gnu compiler (gcc-7) and linker versions available.
现在我们有了一个例子,一个可执行文件可以链接一个共享库,而该库又可以链接另一个共享库.因此,可执行文件具有次要依赖性.但是仅从rpath而不是runpath中获取辅助依赖项.因此,即使将辅助依赖关系放在可执行文件的runpath文件夹中,也不会找到它.
Now we have the case, that an executable may link a shared library, which again links another shared libraries. Thus the executable has a secondary dependency. But secondary dependencies are only picked up from rpath and not from runpath. So even if the secondary dependency is placed in the runpath folder of the executable it will not be found.
结合使用googletest和cmake时发现了问题.由于找不到次要依赖项,因此无法编译测试.因此,设置 LD_LIBRARY_PATH
可能不是一个选择,或者至少会使一切变得复杂.
The problem was identified when using googletest in combination with cmake. There the tests cannot be compiled, because of not found secondary dependencies. So setting LD_LIBRARY_PATH
might not be an option or at least complicates everything a lot.
以下是在Ubuntu18系统上gcc-7出问题的示例(但在Ubuntu16上gcc-5可以正常工作):
secondary.hpp
#include <string>
class World{
public:
std::string world();
};
secondary.cpp
#include "secondary.hpp"
std::string World::world(){
return "world";
}
primary.hpp
#include <string>
class Hello{
public:
std::string helloWorld();
};
primary.cpp
#include "primary.hpp"
#include "secondary.hpp"
#include <sstream>
std::string Hello::helloWorld(){
std::stringstream strm;
World world;
strm << "hello ";
strm << world.world();
strm << "!";
return strm.str();
}
并像这样编译两个库
mkdir build
cd build
gcc -shared -o libsecondary.so -fPIC ../secondary.cpp
gcc -shared -o libprimary.so -fPIC ../primary.cpp -lsecondary -L$(pwd)
如果我现在从以下文件构建可执行文件
If I now build an executable from the following files
main.cpp
#include "primary.hpp"
#include <iostream>
int main(int argc, char** argv){
Hello hello;
std::cout << hello.helloWorld() << std::endl;
}
通过在新的构建目录中执行以下操作(与上一个目录平行)
by doing the following in a new build directory (parallel to the previous one)
cd ..
mkdir build_app
cd build_app
gcc -o app ../main.cpp -L../build -lstdc++ -lsecondary -lprimary -Wl,-rpath=$(pwd)/../build
如果我现在使用 ldd应用
,我发现找不到 libsecondary.so
If I now do ldd app
I see, that libsecondary.so
is not found
linux-vdso.so.1 (0x00007fff0cf8c000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f9e86fe7000)
libprimary.so => <some_path>/libprimary.so (0x00007f9e86de5000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f9e86bcd000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9e867dc000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f9e8643e000)
/lib64/ld-linux-x86-64.so.2 (0x00007f9e87573000)
libsecondary.so => not found
并且应用程序的运行路径为(通过运行 readelf -d应用程序
)
and the runpath of app is (by running readelf -d app
)
Dynamic section at offset 0x1d40 contains 31 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6]
0x0000000000000001 (NEEDED) Shared library: [libprimary.so]
0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000001d (RUNPATH) Library runpath:[<some_path>/build]
问题是,为什么 ld
不从 app
的运行路径中获取 libsecondary.so
? libprimary.so
和 libsecondary.so
都放置在同一文件夹中,但是仅找到 libprimary.so
.
The question is, why ld
is not taking libsecondary.so
from the runpath of app
? Both libprimary.so
and libsecondary.so
are placed in the same folder, but only libprimary.so
is found.
解决该问题的一种方法是使用-disable-new-dtags
进行编译,该代码将使用rpath而不是runpath,并且是Ubuntu16上gcc-5的默认设置.但是,ld似乎不赞成使用rpath.
One solution to the problem is to compile with --disable-new-dtags
which will use rpath instead of runpath and is the default for gcc-5 on Ubuntu16. However, the usage of rpath seems to be deprecated from ld.
那么将runpath与辅助依赖项一起使用的正确方法是什么?
So what is a proper way to use runpath together with secondary dependencies?
推荐答案
libprimary
负责加载 libsecondary
,而不是 app
.这意味着 app
的DT_RUNPATH条目不适用.
libprimary
is responsible for loading libsecondary
, not app
. That means that the DT_RUNPATH entry for app
does not apply.
由于您可以控制所有库,因此可以将 -Wl,-rpath = ...
添加到 libprimary
和 libsecondary
.
Since you have control over all libraries, you could add a -Wl,-rpath=...
to the compile statements for libprimary
and libsecondary
as well.
这篇关于带有运行路径的C ++二级依赖项解析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!