When statically linking a library, getting Linker error : cannot find -lgcc_s

When statically linking a library, getting Linker error : cannot find -lgcc_s

我想静态 link 一个库说 libcurl。由于静态库和共享库都在同一个文件夹中,我使用 -Wl,-Bstatic 让 linker 知道使用静态库。

g++ -o prog prog.o -Wl,-Bstatic -lcurl. 

但是上面的命令给出了错误:

/usr/bin/ld: cannot find -lgcc_s

如果我排除 -Wl,-Bstatic,它工作正常,但它会使用我不想要的共享库。

出了什么问题?

当您使用 g++ 前端来执行您的 linkage 时,例如:

g++ -o prog prog.o -Wl,-Bstatic -lcurl

g++ 调用 linker 将您的 linkage 选项传递给它,并且还默默地 向 linker 命令行添加大量样板选项 对于 C++ linkage.

是不变的

例如,您的 C++ 程序很可能需要 link 标准 C++ 库, libstdc++,但是您的 g++ 命令没有提到它。它当然也需要标准的 C 库, 但也没有提到。 g++ 自动将 linkage 选项添加到 link 这些和 其他图书馆。

您可以看到 g++ 通过 运行 添加到您的 linkage 的所有样板 详细模式。你会看到类似:

$ g++ -v -o prog prog.o -Wl,-Bstatic -lcurl
...
...
COLLECT_GCC_OPTIONS='-v' '-o' 'prog' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-linux-gnu/7/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/7/liblto_plugin.so \
 -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper \
 -plugin-opt=-fresolution=/tmp/cckwrJp6.res -plugin-opt=-pass-through=-lgcc_s \
 -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc \
 -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc \
 --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu \
 --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro \
 -o prog /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o \
 /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crti.o \
 /usr/lib/gcc/x86_64-linux-gnu/7/crtbeginS.o \
 -L/usr/lib/gcc/x86_64-linux-gnu/7 -L/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu \
 -L/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib -L/lib/x86_64-linux-gnu \
 -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib \
 -L/usr/lib/gcc/x86_64-linux-gnu/7/../../.. prog.o \
 -Bstatic -lcurl -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc \     
 /usr/lib/gcc/x86_64-linux-gnu/7/crtendS.o \
 /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crtn.o
/usr/bin/x86_64-linux-gnu-ld: cannot find -lgcc_s
/usr/bin/x86_64-linux-gnu-ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status

请特别注意您的 -Bstatic 选项和以下 link 年龄选项:

 -Bstatic -lcurl -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc \     
 /usr/lib/gcc/x86_64-linux-gnu/7/crtendS.o \
 /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crtn.o

其中包括您的 -lcurl 以及默认系统库:

-lcurl -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc

然后看documentation of the -Bstatic linker option:

-Bstatic

...

Do not link against shared libraries. This is only meaningful on platforms for which shared libraries are supported. The different variants of this option are for compatibility with various systems. You may use this option multiple times on the command line: it affects library searching for -l options which follow it. This option also implies --unresolved-symbols=report-all. This option can be used with -shared. Doing so means that a shared library is being created but that all of the library’s external references must be resolved by pulling in entries from static libraries.

[我的重点]

因此,您的 -Bstatic 选项将 linker 引导至 link static 版本的:

-lcurl -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc

它会找到您已安装的静态 libcurl.a。它找不到一个 -lgcc_s 的静态库,因为没有安装任何 libgcc_s.a 你的系统。你只有这个和其他基本系统库的动态版本, 这很正常。

如果您希望linker link 静态库 -l 选项 指定,那么您必须在 -l 选项 之前打开 -Bstatic 并将其关闭 在他们 -Bdynamic 之后,即使这使 -Bdynamic 成为您命令行上的最后一件事。 因为 g++(或任何其他 GCC 前端,gccgfortran...)将添加 -l 幕后命令行的选项。 Link 喜欢:

g++ -o prog prog.o -Wl,-Bstatic -lcurl -Wl,-Bdynamic

修复这个特定的 link年龄错误。