g++ -static 标志取代了动态库加载器

mar*_*o.b 4 linux linker makefile g++ ld

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

我正在尝试使用 makefile 和 g++ 编译 C++ 程序。我还必须将任何依赖项静态构建到程序中,但不是“系统库”(libz.solibdl.solibstdc++.solibm.solibpthread.solibc.solibgcc.so

为了实现这一点,我指定-static为链接器标志,然后所有必须静态链接的依赖项,然后我使用该-Wl, -Bdynamic选项,该选项应该告诉链接器链接每个库,在此选项之后,动态链接,包括“系统库”因为它们是最后链接的。(如果我错了,请纠正我。)

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
Run Code Online (Sandbox Code Playgroud)

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

当我从链接器中删除-static标志时,程序可以很好地执行,但是依赖项是动态链接的,这不是我想要的:(。

因此,当我调用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选项的情况下编译时是这样。

我发现“解释器”实际上是共享库加载器,从我读到的内容来看,我现在假设 bash 告诉我它找不到该程序,因为库加载器是错误的(尽管我不知道)不太明白这个细节)。

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

n. *_* m. 7

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

这种混合会产生不一致且错误的链接命令。我不知道为什么 gcc 至少不会对此发出警告,但它不会,并且默默地将动态加载器设置为不存在的文件。

您希望始终如一地使用-Wl,-Bstatic和。-Wl,-Bdynamic不是-Bstatic-Bdynamic,因为 gcc 逻辑与 ld 不同。

这将创建一个正确的动态链接可执行文件,其中链接了一些静态库。