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

kes*_*ari 4 linker llvm ld julia

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

julia可执行文件使用的库 libjulia.so始终链接到 libLLVM*.so文件,即使我使用BUILD_SHARED_LIBS=OFF(默认配置)重建 LLVM也是如此。llvm-config --libs $LIB有和没有的输出BUILD_SHARED_LIBS=ON变化不大,似乎没有任何迹象llvm-config表明会发布链接选项,引导链接器链接 *.so 文件或 *.a 文件。

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

Mik*_*han 5

是的,为了实现该选项-lfoold默认情况下将libfoo.so优先链接到libfoo.a是否在同一搜索目录中找到两者,并且当它找到任何一个时,它将不再查找。

您只能通过传递-static给链接来强制静态库的链接,但在这种情况下,必须为所有库(包括默认系统库)找到静态版本,而不仅仅是您明确提到的库。

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

llvm-config-lfoo无论您构建静态库还是共享库,都会以这种形式发出库选项,因为这些选项对两者都可以正常工作,但是您需要了解在使用它们时链接器的行为方式。如果你不另外告诉它,它在面临选择时会链接共享而不是静态库。

之后

为什么 ld 更喜欢链接共享库而不是静态库?

AFAIK,开发人员ld很久以前做出这个决定的原因并没有记录在案,但原因很明显:如果动态链接是默认的,那么默认情况下,可执行文件将不会在物理上包含可以提供给所有可执行文件的额外代码副本通过单个共享副本,来自共享库。因此,默认情况下,可执行文件将节省它们的代码大小,并且构成您的系统或我的系统的可执行文件的总量将比不共享时要小得多。发明了共享库和动态链接,这样系统就不会因重复的代码而变得臃肿。

动态链接带来了复杂性,即与共享库链接的可执行文件在分发到构建它的系统之外的系统时,不会携带其动态依赖项。出于这个原因,在系统上安装新二进制文件的所有批准机制 - 包管理器 - 确保也安装了它们的所有动态依赖项。