首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有运行路径的c++二级依赖关系解析

具有运行路径的c++二级依赖关系解析
EN

Stack Overflow用户
提问于 2019-12-09 11:55:47
回答 1查看 1.1K关注 0票数 1

我有以下问题:

我试图通过使用默认的gnu编译器(gcc-7)和链接器版本在Ubuntu18上构建软件。

现在我们有了这样的情况,一个可执行文件可以链接一个共享库,这再次链接了另一个共享库。因此,可执行文件具有次要的依赖性。但是次要依赖项只能从rpath中获取,而不是从runpath中获取。因此,即使次要依赖项被放置在可执行文件的runpath文件夹中,它也不会被找到。

当使用googletest与cmake相结合时,发现了这个问题。在那里,由于找不到次要依赖项,无法编译测试。因此,设置LD_LIBRARY_PATH可能不是一种选择,或者至少会使一切变得复杂。

这里是gcc-7在Ubuntu18系统上出现问题的一个例子(但在Ubuntu16上运行得很好):

secondary.hpp

代码语言:javascript
复制
#include <string>

class World{
    public:
        std::string world();
};

secondary.cpp

代码语言:javascript
复制
#include "secondary.hpp"

std::string World::world(){
    return "world";
}

primary.hpp

代码语言:javascript
复制
#include <string>

class Hello{
  public:
    std::string helloWorld();
};

primary.cpp

代码语言:javascript
复制
#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();
}

并像这样编译这两个库

代码语言:javascript
复制
mkdir build
cd build
gcc -shared -o libsecondary.so -fPIC ../secondary.cpp
gcc -shared -o libprimary.so -fPIC ../primary.cpp  -lsecondary -L$(pwd)

如果我现在从以下文件构建一个可执行文件

main.cpp

代码语言:javascript
复制
#include "primary.hpp"
#include <iostream>

int main(int argc, char** argv){
    Hello hello;
    std::cout << hello.helloWorld() << std::endl;
}

在新的构建目录中执行以下操作(与前一个目录并行)

代码语言:javascript
复制
cd ..
mkdir build_app
cd build_app
gcc -o app ../main.cpp -L../build -lstdc++ -lsecondary -lprimary  -Wl,-rpath=$(pwd)/../build

如果我现在做ldd app,我看到,libsecondary.so是找不到的

代码语言:javascript
复制
    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 app)

代码语言:javascript
复制
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.solibprimary.solibsecondary.so都放在同一个文件夹中,但只有libprimary.so

解决这个问题的一个解决方案是使用--disable-new-dtags编译,它将使用rpath而不是runpath,并且是Ubuntu16上gcc-5的默认设置。然而,rpath的使用似乎与ld不同。

那么,将runpath与辅助依赖一起使用的正确方法是什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-12-09 12:03:15

libprimary负责加载libsecondary,而不是app。这意味着DT_RUNPATH条目不适用于app

因为您控制了所有库,所以您也可以将一个-Wl,-rpath=...添加到libprimarylibsecondary的编译语句中。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59248421

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档