链接器是否更喜欢 .so 文件而不是 .a 文件?

Does the linker prefer .so files over .a files?

我正在使用包含 libLLVM*.so 文件和相应的 libLLVM*.a 文件的本地 LLVM 构建构建 Julia。这是首先使用 BUILD_SHARED_LIBS=ON 构建的,它负责 libLLVM*.so 文件的存在。

libjulia.so,julia 可执行文件使用的库,总是link编辑到 libLLVM*.so 文件,即使我用 BUILD_SHARED_LIBS=OFF(默认配置)重建了 LLVM。 llvm-config --libs $LIB 使用和不使用 BUILD_SHARED_LIBS=ON 的输出变化不大,似乎没有任何迹象表明 llvm-config 发出 linking 选项来指导 link er to link *.so 文件或 *.a 文件。

为什么会这样?即使存在同名的 .a 文件,linker 的默认行为是使用 .so 文件吗?或者,是否有 Julia 重用的构建配置缓存?

是的,为了满足选项 -lfoold 将默认 link libfoo.so 优先于 libfoo.a 如果两者 在同一个搜索目录中找到,当它找到其中一个时 不会再看了。

您只能通过将 -static 传递给 linkage 来强制执行静态库的 linkage, 但在那种情况下,必须为 all 库找到静态版本 - 包括 默认系统库 - 不仅仅是您明确提到的那些。

选择性地link一个静态库libfoo.a,而不指定-static, 您可以使用 -l 选项的显式形式:-l:libfoo.a 而不是 -lfoo.

llvm-config 将以 -lfoo 形式发出库选项,无论您是否构建 静态或共享库,因为这些选项可以正常工作 两者都可以,但是您在使用它们时需要了解 linker 表现。如果您不另行告诉它,它将 link 共享而不是 比静态库面临选择的时候。

以后

Why does ld prefer to link shared libraries over static ones?

AFAIK,ld 的开发者做出这个决定的原因并没有记录在案 以前,但原因很明显:如果动态 linkage 是默认值,那么 默认情况下,可执行文件不会包含额外的代码副本 可以通过共享库中的单个共享副本提供给所有可执行文件。因此 默认情况下,可执行文件将节省它们的代码大小和 构成你的系统或我的系统的可执行文件将比 它必须没有共享。共享库和动态 linkage 被发明出来是为了让系统不会因重复的代码而变得臃肿。

动态 linkage 带来了可执行文件的复杂性 link使用共享库编辑,当分发到除 构建它的一个,不带有它的动态依赖性。它是 出于这个原因,所有批准的安装新二进制文件的机制 在系统上 - 包管理器 - 确保他们所有的动态依赖 也安装了。