在C ++

时间:2016-02-04 22:03:17

标签: linker g++

我想创建动态链接到共享对象A的共享对象B.我使用以下命令编译共享对象B:

g++ -fPIC -shared -L/path/to/directory -lA -o libB.so B.cpp

据我了解,-lA告诉链接器libB.so应该动态链接到/path/to/directory/libA.so。但是,当我对最终产品执行ldd时,未列出依赖项(并且因为缺少依赖项而加载libB.so失败)。

ldd libB.so

linux-vdso.so.1 =>  (0x00007ffd4233e000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f35072fe000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f35070e7000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f3506de1000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3506a1c000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3507807000)

我对-l应该做什么感到错误?我假设上面是C ++的最小动态依赖集。

有没有找到的陷阱?例如,当链接器无法找到文件或其他内容时,链接器是否会忽略-l个请求(我必须调试我的路径比我已经拥有的更多)?

我是否必须在C ++代码中添加一些内容来表示依赖(例如" extern"函数或其他内容)?

更新

我已确定ld报告 的动态依赖关系集取决于我的C ++代码而似乎依赖于任何{{1}我提供的{}或-L标志。链接器会自动猜测我的-l应该依赖哪些共享对象,并且它没有足够的假设。

例如,我知道我需要B加载A,因为我调用了一些最终调用libB.so中的代码的代码。如何向链接器提供此信息?

澄清:

我呼唤的是#34;共享对象A"是一个复杂的事情,可能会动态加载一些代码。我希望包含足够的依赖关系,这样它就不会失败"缺少符号"当它试图动态加载此代码时。这就是我想在B中强制依赖的原因,因为链接器可能不会在依赖树中静态地找到它们。

另外,我使用的是g ++ 4.8.4(Ubuntu 14.04)。这是相关的,因为从版本4.6开始,g ++开始隐式应用libA.so

2 个答案:

答案 0 :(得分:2)

ldd的输出中可能没有列出依赖关系,因为在B.cpp中找不到libA.so中使用的符号。这可能是因为C ++符号名称错误导致:如果{C编译器已编译libA.so,它可能将函数void foo()的符号存储在漂亮的名称foo下,而C ++编译器将会破坏它变成_Z3foov之类的东西。您可以使用以下命令进行检查:

$ # Replace "SomeSharedObject" with the actual name of symbol exported by libA.so.
$ strings libA.so | grep SomeSharedObject
$ strings libB.so | grep SomeSharedObject

为避免这种情况,可以将符号foo的声明放入extern "C" {}子句中。然后编译器不会破坏这个名称,链接器可能会在libA.so中找到这个名称。

-l选项在实验室环境中的效果如您所愿:

$ cat bar.cpp 
extern void foo();

void bar()
{
    foo();
}
$ cat baz.cpp 
extern void bar();

void baz()
{
    bar();
}
$ # Link against libssl.so (OpenSSL).
$ # Obviously libssl.so is unnecessary in libbar.so.
$ g++ -fPIC -shared bar.cpp -o libbar.so -lssl 
$ ldd libbar.so 
    statically linked
$ # Link against libbar.so in the current directory
$ g++ -fPIC -shared baz.cpp -o libbaz.so -L`pwd` -lbar
$ ldd libbaz.so 
    linux-vdso.so.1 =>  (0x00007fff7cfe2000)
    libbar.so => not found

此处libbar.so取决于函数foo。但是在任何图书馆中都找不到它,包括libssl.so。因此ldd将共享对象libbar.so报告为“静态链接”。生成libbar.so时未找到的所有符号将在创建取决于libbar.so的最终可执行文件时进行搜索。

反过来,libbaz.so取决于libbar.so,因为在我们通过void bar()选项指定的上述共享对象中找到了函数-l。如果我们省略-L选项,链接器将报告错误-lbar: not found。如果我们省略-L-llibbaz.so就不会像libbar.so一样依赖任何共享对象。

答案 1 :(得分:-2)

您正在编译一个奇怪的对象名称。创建可执行文件时将进行链接。 然后你必须提到你的各种对象和库。