我想创建动态链接到共享对象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
。
答案 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
和-l
,libbaz.so
就不会像libbar.so
一样依赖任何共享对象。
答案 1 :(得分:-2)
您正在编译一个奇怪的对象名称。创建可执行文件时将进行链接。 然后你必须提到你的各种对象和库。