c - 将一个 .so 与另一个 .so 链接时 undefined symbol

标签 c linux gcc shared-libraries

a.so定义函数A()b.so定义函数B()并调用A()a.so 中定义。 b.so 链接到 a.so 如下

gcc -fPIC -shared B.c -o libb.so -la

现在我创建了一个二进制文件,它调用在 b.so 中定义的 B()

gcc mybin.c -o mybin -lb

gcc 正在检查 b.so 中的每个符号并抛出错误,指出 A() 未定义。

gcc mybin.c -o mybin -lb -la

上面的方法有效,但我必须将 mybin 与 a.so 链接,即使它与 a.so 没有直接关系。我的要求是,如果 b.soa.so 正确链接,则仅将 mybinb.so 链接> 应该可以。

这可能吗?

最佳答案

链接可执行文件时,链接器想知道 libb.so 所需的库存在,以便它可以检查它们解析 libb.so 中任何 undefined reference

链接器在通常的位置查找所需的库,因此如果找不到 liba.so那么你可以使用 LD_LIBRARY_PATH 告诉链接器去哪里查找如另一个答案所示,或者通过使用专门为此目的而存在的链接器选项, -rpath-link

gcc mybin.c -o mybin -lb -Wl,-rpath-link=.

(-Wl, 前缀是告诉 GCC 将选项传递给链接器的方式,这是 GCC 不直接了解的链接器选项所需要的。)

或者,您可以告诉链接器允许libb.so中 undefined symbol 。在这种情况下,它不会尝试查找 liba.so解析对 A() 的引用,并相信您将正确链接并确保该库在运行时可用。这是通过 --allow-shlib-undefined 完成的选项:

gcc mybin.c -o mybin -lb -Wl,--allow-shlib-undefined

但是,通常最好让链接器检查所有符号是否已定义,并告诉它如何查找所需的库,因为它可以更快地发现真正的问题。

-rpath-link选项only告诉链接器在哪里寻找额外的共享库,它对链接的可执行文件没有明显的影响(即它不会在任何地方记录可执行文件中库的路径)。另一种选择是创建 libb.so这样它就包含了如何查找liba.so的知识嵌入其中。这是通过 -rpath 完成的链接器选项,例如如果liba.so位于/some/path你可以这样做:

gcc -fPIC -shared B.c -o libb.so -la -Wl,-rpath=/some/path

这会产生 DT_RPATH标签 libb.so链接器将使用它来查找其依赖项:

readelf -d libb.so  | fgrep RPATH
 0x000000000000000f (RPATH)              Library rpath: [/some/path]

现在您可以链接可执行文件,而无需了解 liba.so ,链接器将看到 libb.so需求liba.so并将使用 RPATH 来查找它:

gcc mybin.c -o mybin -lb

如果路径 /some/path/liba.so 则效果很好已修复,但在开发期间和部署可执行文件后在同一位置找到该库可能并不正确。在这种情况下,您仍然可以使用-rpath-link让可执行文件告诉链接器在链接期间在哪里查找它,并依靠 RPATH 在运行时查找它。或者您可以使用特殊字符串 $ORIGIN在 RPATH 中,动态链接器将其扩展为包含 RPATH 的对象的位置,例如如果liba.solibb.so始终在同一目录中,您可以链接 libb.so像这样(注意引号以防止 shell 扩展 $ORIGIN ):

gcc -fPIC -shared B.c -o libb.so -la '-Wl,-rpath=$ORIGIN'

readelf -d libb.so  | fgrep RPATH
 0x000000000000000f (RPATH)              Library rpath: [$ORIGIN]

关于c - 将一个 .so 与另一个 .so 链接时 undefined symbol ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27422303/

相关文章:

python - Python 和 C/C++ 中的可变/不可变对象(immutable对象)

c++ - 有没有办法强制一个程序只使用一个线程?

linux - 使用 Bash 用 IFS 分割字符串?

linux - 如何编写 awk 脚本来列出当前使用系统的用户以及他们登录的次数?

gcc - 如果编译失败,则执行命令

c++ - Vulkan 异步模型加载

c - 在 C 中传递字符串

c++ - 指针)是否有可能已经占据(ptr + 1)?

c - 如何在两个应用程序之间共享一个共享库(*.so)实例

c++ - clang 错误 : c++/4. 8/bits/STL_iterator_base_types.h:227:29: 错误: 'iterator_category' 中没有名为 'std::iterator_traits<unsigned long>' 的类型