我想静态链接一个库,说libcurl。由于静态库和共享库都在同一文件夹中,因此我在使用-Wl,-Bstatic来使链接程序知道使用静态库。
g++ -o prog prog.o -Wl,-Bstatic -lcurl.
但是上面的命令给出了错误:
/usr/bin/ld: cannot find -lgcc_s
如果我排除-Wl,-Bstatic,它可以正常工作,但是它将使用我不想要的共享库。
怎么了?
最佳答案
当您使用g++
前端执行链接时,例如:
g++ -o prog prog.o -Wl,-Bstatic -lcurl
g++
调用链接器,将其传递给您的链接选项,并且也进行静默向链接器命令行添加了大量样板选项,这些选项
对于C++链接是不变的。
例如,您的C++程序很可能需要链接标准C++库,
libstdc++
,但是您的g++
命令未提及它。当然也需要标准的C库,但也没有提及。
g++
自动添加链接选项以链接这些链接和其他图书馆。
您可以通过运行以下命令查看
g++
添加到链接的所有样板详细模式。您将看到以下内容:
$ 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
选项和以下链接选项: -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
选项将指示链接程序链接以下静态版本:-lcurl -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc
它会找到您已安装的静态
libcurl.a
。找不到-lgcc_s
的静态库,因为没有安装任何libgcc_s.a
你的系统。您只有该版本和其他基本系统库的动态版本,这很正常。
如果您希望链接器仅链接静态库,则仅针对您所使用的
-l
选项指定,那么您必须在
-Bstatic
选项之前打开-l
并将其关闭在它们之后是
-Bdynamic
,即使这使-Bdynamic
在命令行中成为最后一件事。因为
g++
(或任何其他GCC前端gcc
,gfortran
...)将添加-l
后台命令行选项。链接类似:g++ -o prog prog.o -Wl,-Bstatic -lcurl -Wl,-Bdynamic
解决此特定的链接错误。