c - Ubuntu 和 CentOS 之间链接行为的差异
问题描述
我正在构建两个共享库,一个库 (B) 依赖于另一个 (A) 并且都使用rpath
of构建$ORIGIN/.
,然后将可执行文件链接到库 B。因此依赖关系如下:
可执行 C -> 库 B -> 库 A
在 Ubuntu 上,B 对 A 的依赖是使用它的 解决的rpath
,而在 CentOS 上,链接器警告说找不到 A,我应该在编译可执行文件期间使用“尝试使用-rpath
或”。-rpath-link
这是重现该问题的最小示例:
mkdir testdir
echo 'void a() {}' > testdir/a.c
echo 'int a(); void b() { a(); }' > testdir/b.c
echo 'int b(); int main() { b(); }' > testdir/c.c
gcc testdir/a.c -shared -o testdir/liba.so -Wl,-rpath,'$ORIGIN/.' -fPIC
gcc testdir/b.c -Ltestdir -la -shared -o testdir/libb.so -Wl,-rpath,'$ORIGIN/.' -fPIC
gcc testdir/c.c -Ltestdir -lb -o testdir/a.out
导致此问题的 Ubuntu 和 CentOS 上的链接行为有什么区别?有没有办法可以“解决”这个问题,这样 A 就可以得到解决,而不必依赖诸如LD_LIBRARY_PATH
?
更新:如果我使用库目录的绝对路径而不是$ORIGIN
,这似乎可行。当然我不知道它们将被部署到哪里的绝对路径,所以这并不能解决这个问题,但它表明$ORIGIN
CentOS 7(或其加载程序)不支持。
解决方案
我认为这里的问题可能是这个错误,针对 binutils 2.26 报告,但可能也存在于早期版本中。问题是链接器ld
与动态加载器不同ld.so
,它没有解释$ORIGIN
rpath 中的特殊替换字符串,因此只能使用绝对路径。
该错误在 binutils 2.28 中被标记为已修复,但 Centos 7 具有 binutils 2.27。另一方面,Ubuntu 18.4 使用 binutils 2.30。
推荐阅读
- reactjs - 是否可以通过 useCallback 避免自定义 React Hook 上的“eslint(react-hooks/exhaustive-deps)”错误?
- java - 使用命令行运行 Java 类
- spring - Spring MVC:Bean 名称“标记”的 BindingResult 和普通目标对象都不能用作请求属性。尝试了所有解决方案
- excel - 如何将数据范围复制到另一个工作表的最后一行?
- html - 如何定位父级内的所有标签
- activemq-artemis - # 通过 MQTT 订阅会导致连接丢失时出现巨大的队列
- c# - 创建文件有效,但是在下载该文件时,C# 中没有任何反应
- python-3.x - 仅存储“失败”芹菜任务的结果(芹菜结果后端)
- angular - Angular Material TypeError:无法读取未定义的属性“id”
- php - Laravel 6,MYSQL - 如何使用 Laravel Querybuilder 或 Model Eloquent 将子查询与 GroupBY 左连接?