当我使用的库使用的库发生更改时,我的可执行文件是不是需要重新链接?

Posted

技术标签:

【中文标题】当我使用的库使用的库发生更改时,我的可执行文件是不是需要重新链接?【英文标题】:Does my executable need relinking when a library used by a library that I use changes?当我使用的库使用的库发生更改时,我的可执行文件是否需要重新链接? 【发布时间】:2017-06-21 13:49:21 【问题描述】:

假设我们有一个可执行的exe,它依赖于共享库foo,而共享库又依赖于共享库barexe 需要 libfoo.sofoo 需要 libbar.so。 然后,bar 以源兼容的方式更改(即 API 未更改),但不以二进制兼容的方式更改(即 ABI 更改)。因此,我们必须重新链接(或面临分段错误)。

问题是:究竟应该重新编译/重新链接什么?


让我说得更具体一点。要链接 exe,我们不需要添加编译器选项“-lbar”,而我们确实需要该选项来链接 foo

gcc -fPIC -shared -I. -Ibar -lbar -o libfoo.so foo.o
gcc -fPIC -I. -Ifoo -Ibar -lfoo -o exe exe.o

    因此,重新链接 foo 并保持 exe 不变就足够了吗?

    fooexe 是否也需要重新编译(如果 bar 改变了,但它的 API 没有改变)?

最后,我尝试让 foo 保持不变,但使用添加的“-lbar”编译器选项重新链接 exe

gcc -fPIC -I. -Ifoo -Ibar -lfoo -lbar -o exe exe.o

这确实消除了分段错误,这可能意味着所有内容都正确链接...内存问题)。

    是否允许这样做,即保持 foo 不变,但将 exebar 显式链接?

有些相关的读数:[1][2][3][4][5]

【问题讨论】:

这种繁重的工作应该始终留给机器来解决。不是因为它很难做,而是因为它很乏味,如果你不注意,你会失去一个小时的生命。那里有很多构建系统,选择一个。 @HansPassant 我正在使用构建系统 wmake,它是开源计算流体动力学软件 OpenFoam 的自定义。询问的原因是 OpenFoam 由许多不同的可执行文件(“求解器”)组成,它们依赖于许多动态库来完成工作。我为我的目的改编了一个这样的库(bar),我认为只需覆盖现有的动态库,所有求解器都可以正常工作:但它们给了我段错误。这就是为什么我要问究竟是什么应该重新链接。 【参考方案1】:

在专家回答之前,这些都是我自己的假设:

    鉴于链接器不需要 exe 的“-lbar”,我倾向于得出结论 exe 不需要重新链接,因为链接器显然不需要 bar。但是,我对此非常不确定,因为这假设链接器没有通过 foo 找到 bar。 (毕竟ldd libfoo.so 会告诉我bar,所以我想说链接器可能知道它需要bar。)

    李>

    不,他们没有。源是兼容的,因此编译(对象)文件中的符号应该仍然是正确/兼容的。但是,可执行文件确实需要重新链接,因为这些符号在目标文件中的位置已更改。

    看来这是允许的……但我不确定。另外:除了 exe 之外,任何依赖于 foo 的可执行文件/库仍然会面临分段错误,所以这是不好的做法,不是吗?

【讨论】:

以上是关于当我使用的库使用的库发生更改时,我的可执行文件是不是需要重新链接?的主要内容,如果未能解决你的问题,请参考以下文章

将 clang 构建的可执行文件与 g++-v6 构建的 boost 库链接的错误

如果我在 Linux 上更改 C++ 动态共享库而我的可执行程序在它上面使用会发生啥

Makefile 在运行时无法链接库

g++ 版本兼容性

如何检查 C# 中的库 (dll) 是不是可用?

x86的库和arm的.o文件能链接吗