g++ -static 标志替换动态库加载器

g++ -static flag replaces the dynamic library loader

首先我想提供一些背景信息以避免XY Problem

我正在尝试使用 makefile 和 g++ 编译一个 c++ 程序。我还必须在程序中静态构建任何依赖项,但不是 'system libraries'(libz.solibdl.solibstdc++.solibm.solibpthread.so , libc.solibgcc.so).

为了实现这一点,我将 -static 指定为 linker 标志,然后所有必须静态 linked 的依赖项,然后我使用 -Wl, -Bdynamic 选项,这应该告诉 linker link 每个库,在这个选项之后,动态地 linked in 包括 'system libraries' 因为他们最后得到 linked .(如有错误请指正。)

LDFLAGS += -Lpath/to/dependencies

# These libs should be linked statically
LDFLAGS += -static
LDFLAGS += -llib1
LDFLAGS += -llib2
LDFLAGS += -llib3

# Libs after this should be linked dynamically.
LDFLAGS += -Wl, -Bdynamic
LDFLAGS += -lz         # If i dont specify these three libraries (z, pthread, dl) 
LDFLAGS += -lpthread   # I get undefined reference errors 
LDFLAGS += -ldl

当我调用 make 时,程序编译并且 link 很好,但是当我尝试执行它时我得到错误:bash: ./program: No such file or directory。 但是文件确实存在。

当我从 linker 中删除 -static 标志时,程序可以正常执行,但是依赖项是动态 linked,这不是我想要的:(.

所以当我在程序上调用 file 时,它是用 -static 标志制作的,我得到这个:

program: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), dynamically linked, interpreter /usr/lib/libc.so.1, for GNU/Linux 4.9.0, not stripped

问题似乎是解释器设置为 /usr/lib/libc.so.1 而不是通常应设置的 /lib/ld-linux.so.2。至少,当我在没有 -static 选项的情况下进行编译时是这样。

我发现 'interpreter' 实际上是共享库加载程序,从我读到的内容来看,我现在假设 bash 告诉我它找不到程序,因为库加载器是错误的(尽管我不太了解其中的细节)。

所以基本上我的问题是:当我为 link er 指定 -static 选项时,为什么库加载器设置为 libc.so 以及我如何告诉 linker 在指定 -static 时使用正确的库加载程序?

您的错误是混合使用 -static-Bdynamic 作为编译器和 linker 标志。不要那样做。如果你使用 -Wl,gcc 只是盲目地将这些标志传递给 linker,但如果你不使用,它会重新排列整个 link 行。 (检查它对 gcc -v 的作用)。

混合创建了不一致且错误的 link 命令。我不知道为什么 gcc 至少没有对此发出警告,但它确实没有,并且默默地将动态加载程序设置为一个不存在的文件。

您想始终使用 -Wl,-Bstatic-Wl,-Bdynamic。不是 -Bstatic-Bdynamic,因为 gcc 逻辑与 ld.

不同

这将创建一个正确的动态 linked 可执行文件,其中包含一些 linked 的静态库。