【问题标题】:When statically linking a library, getting Linker error : cannot find -lgcc_s静态链接库时,出现链接器错误:找不到 -lgcc_s
【发布时间】:2023-03-29 07:06:01
【问题描述】:

我想静态链接一个库,比如 libcurl。由于静态库和共享库都在同一个文件夹中,我使用 -Wl,-Bstatic 让链接器知道使用静态库。

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

但是上面的命令报错:

/usr/bin/ld: cannot find -lgcc_s

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

出了什么问题?

【问题讨论】:

  • 你知道g++是C++编译器不是C编译器吗?
  • 是的,我知道这一点。但是你的意思是什么?我在 g++ 的手册页中检查了 -Bstatic 选项
  • 好吧,您现在删除了 C 标签,关键是您将此问题标记为 C,我指出要删除与问题无关的标签,这样您就不会得到不必要的反对票。

标签: c++ linux linker g++ static-linking


【解决方案1】:

当您使用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

-B静态

...

不要链接到共享库。这仅在支持共享库的平台上才有意义。 此选项的不同变体是为了与各种系统兼容。 您可以在命令行上多次使用此选项:它会影响库搜索后面的 -l 选项。 此选项还暗示 --unresolved-symbols=report-all。此选项可与 -shared 一起使用。 这样做意味着正在创建一个共享库,但该库的所有外部 引用必须通过从静态库中拉入条目来解决。

[我的重点]

因此,您的 -Bstatic 选项会指示链接器链接 static 版本的:

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

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

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

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

修复这个特定的链接错误。

【讨论】:

    猜你喜欢
    • 2018-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-23
    • 1970-01-01
    相关资源
    最近更新 更多