带有运行路径的C ++二级依赖项解析 [英] c++ secondary dependency resolution with runpath

查看:51
本文介绍了带有运行路径的C ++二级依赖项解析的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下问题:

我正在尝试使用默认的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆