参考我使用的是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
?
答案 0 :(得分:7)
-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++
坚持静态版本。
libstdc++
g++
的自动链接意味着: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
。
答案 1 :(得分:0)
从技术上讲,这不是答案,而是针对损坏的构建系统的解决方法。
我正在使用一个出于某些很奇怪的原因的构建系统,即使是C ++对象,也使用gcc而不是g ++来驱动构建过程。而且我需要有一个二进制文件,除了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