-static-libstdc ++适用于g ++但不适用于纯gcc?

时间:2017-06-11 21:30:43

标签: c++ gcc mingw mingw32

参考我使用的是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

2 个答案:

答案 0 :(得分:7)

GCC manual, Link Options说:

  

-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