-static-libstdc++ 适用于 g++ 但不适用于纯 gcc?
-static-libstdc++ works on g++ but not on pure gcc?
作为参考,我使用的是MinGW(GCC 5.3)。编译文件时
g++ file.cc -static-libstdc++
它静态链接C++标准库(libstdc++
)并生成一个1.9MB的可执行文件。
然而运行
gcc -lstdc++ -static-libstdc++ file.cc
它仍然动态链接到libstdc++-6.dll
并生成 34KB 可执行文件。
为什么-static-libstdc++
只适用于g++
而不适用于纯gcc
?
GCC 手册,链接选项说:
-static-libstdc++
当g++程序用于链接C++程序时,它通常会自动链接 反对libstdc++。如果 libstdc++ 可用作共享库,并且 -static 选项未使用,则此链接对应于 libstdc++ 的共享版本。 这通常没问题。但是,有时冻结 程序使用的libstdc++,而无需一直到完全静态的链接。 -static-libstdc++ 选项指示 g++ 驱动程序静态链接 libstdc++, 不必静态链接其他库。
这清楚地表明,选项-static-libstdc++
仅对g++
编译器驱动程序,而不是gcc
或任何其他驱动程序。
另一方面,选项-l<name>
有意义,意思相同 到所有 GCC 编译器驱动程序。在此基础上,毫不奇怪:
gcc file.cc -lstdc++ -static-libstdc++
具有与以下相同的含义:
gcc file.cc -lstdc++
然而,这一观察并没有真正阐明为什么第一个 命令行动态链接libstdc++
:-
-static-libstdc++
仅对g++
有意义,因为只有g++
链接 自动libstdc++
。所以问题只是为了g++
自动链接的libstdc++
是否为动态版本 或静态版本。动态版本为默认值:-static-libstdc++
坚持静态版本。
通过g++
自动链接libstdc++
意味着:静默地g++
将-lstdc++
附加到您指定的任何链接选项(以及 相当多的其他样板用于C++链接)。您可以显示所有内容 通过请求详细链接(g++ ... -Wl,-v ...
)的样板文件。
追加的-lstdc++
本身将导致链接器链接动态版本libstdc++
,根据其默认行为。唯一的区别是-static-libstdc++
是在-lstdc++
本来会的地方 以静默方式传递给链接器,选项如下:
-Bstatic -lstdc++ -Bdynamic
而是默默地传递给它。这些告诉链接器:
-Bstatic
: 请勿链接动态库,直至另行通知-lstdc++
: 链接libstdc++
-Bdynamic
: 链接动态库,直至另行通知。
您会看到如何在没有的情况下保护libstdc++
的静态链接 排除对任何其他库链接的副作用。
但你也可以看到,libstdc++
的自动联动,是否 动态或静态,对联动没有追溯效力 您自己指定的任何库。
因此,如果您的链接已经包含-lstdc++
在任何样板之前 选项由编译器驱动程序以静默方式附加,然后libstdc++
将被链接 与连杆中该位置的任何-l<name>
相同 序列。如果以静默方式附加样板选项会导致-lstdc++
稍后在链接序列中重新出现,无论是单独出现还是与 周边环境:
-Bstatic -lstdc++ -Bdynamic
那么后面的外观就只是多余的,因为库有 已经链接。
因此,gcc
并没有什么特别
gcc file.cc -lstdc++ -static-libstdc++
生成动态链接libstdc++
的程序。也是如此
g++ file.cc -lstdc++ -static-libstdc++
或者确实:
g++ file.cc -static-libstdc++ -lstdc++
因为生成的链接器命令行的格式为:
... file.o -lstdc++ ... -Bstatic -lstdc++ -Bdynamic ...
-Bstatic -lstdc++ -Bdynamic
为时已晚,无法做出任何改变。
看看吧:
file.cc
#include <iostream>
int main()
{
std::cout << "Hello World" << std::endl;
return 0;
}
正常编译和链接,并检查动态依赖ldd
:
$ g++ -o prog file.cc
$ ldd prog
linux-vdso.so.1 => (0x00007ffede76a000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f42fa74c000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f42fa385000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f42fa07c000)
/lib64/ld-linux-x86-64.so.2 (0x0000558ab42bc000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f42f9e65000)
libstdc++.so
存在。
现在只有-static-libstdc++
:
$ g++ -o prog file.cc -static-libstdc++
$ ldd prog
linux-vdso.so.1 => (0x00007fff448d7000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fe5f7c71000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe5f78aa000)
/lib64/ld-linux-x86-64.so.2 (0x0000556ebf272000)
libstdc++.so
缺席。
最后是-static-libstdc++ -lstdc++
:
$ g++ -o prog file.cc -static-libstdc++ -lstdc++
$ ldd prog
linux-vdso.so.1 => (0x00007ffd12de9000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fd5a1823000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd5a145c000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd5a1153000)
/lib64/ld-linux-x86-64.so.2 (0x000055bbe31c3000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fd5a0f3c000)
libstdc++.so
回来了。
(当然,这是Linux,但你会在Windows上找到同样的东西)。
所以无论你是驱动你的联动g++
还是gcc
,原因
{gcc|g++} file.cc -lstdc++ ...
将导致libstdc++
动态链接
{gcc|g++} file.cc -lfoo ...
将导致libfoo
动态链接(如果可以),无论...
是什么,前提是...
不包含选项-static
.
从技术上讲,这不是一个答案,而是针对损坏的构建系统的解决方法。
我正在使用一个构建系统,出于某种非常奇怪的原因,它使用 gcc 而不是 g++ 来驱动构建过程,即使是对于C++对象也是如此。我需要有一个二进制文件,除了glibc库之外不依赖于任何其他东西。所以,我最终这样做了:
$ cat <<EOF > gcc
#!/bin/bash
if [[ $@ == *"-lstdc++"* ]]; then
/full/path/to/g++ -static-libgcc -static-libstdc++ $(echo $@ | sed 's,-lstdc++,,g')
else
/full/path/to/gcc -static-libgcc $@
fi
EOF
$ chmod +x gcc
$ export PATH=$PWD:$PATH
- 为什么我的 SFINAE 表达式不再适用于 GCC 8.2?
- 适用于 gcc 4.8 的任何正则表达式库
- 流输入运算符导致分段错误与 clang 但适用于 gcc
- -static-libstdc++ 适用于 g++ 但不适用于纯 gcc?
- enable_if的模板专用化在 Clang 中失败,适用于 GCC
- 函数指针数组的类模板参数推导适用于 clang,但不适用于 gcc
- 可变参数模板作为模板参数:演绎适用于 GCC,但不适用于 Clang
- -m32 选项不适用于 gcc,但适用于 g++
- 在哪里可以下载适用于 Windows 的 GCC 4.3.2 二进制文件
- gcc-fdiagnostics颜色是否适用于Windows
- 将 C++11 正则表达式与 gcc 4.8.2 一起使用时会出现奇怪的结果(但适用于 Boost 正则表达式)
- Netbeans 8.1(适用于 C/C++)找不到我的编译器(gcc-6.0.0 开发版本)
- 宏调用中的 #ifdef 适用于 GCC,但不适用于 MSVC
- 静态表生成适用于 GCC,但不适用于 clang;被叮当窃听
- 模板专用化适用于 gcc,但不适用于 Visual Studio 10
- c ++ 11 参数包在 Apple LLVM 7.0.0 中存在错误行为,但适用于 GCC-5.1
- 此代码有效吗?适用于 gcc,不要与 clang 合作
- 两层嵌套的c++类适用于GCC,但不适用于Clang
- 如何包装对"std::thread"构造函数的调用?(适用于gcc、VS和icpc)
- 可变参数模板转换为 std::function<R(ARGS...)>适用于 GCC 而不是 MSVC2013,为什么?