何时需要使用标志-stdlib=libstdc++?

89

在使用gcc编译时,何时需要使用标志-stdlib=libstdc++来指定链接器?

编译器是否会自动使用libstdc++?

我正在Ubuntu 13.10上使用gcc4.8.2,并希望使用C++11标准。我已经向编译器传递了-std=c++11参数。


8
这是一个老问题了,但 -stdlib=libstdc++ 不是有效的 gcc 标志。在 macOS 上可以使用它,因为在 macOS 上的 g++ 实际上是 clang++。请注意,此翻译仅供参考,不得用于正式场合。 - davmac
3个回答

112

在Linux上:通常情况下,所有常见的Linux发行版都会默认使用libstdc++,而所有现代版本的GCC都带有支持C++11的libstdc++。如果你想在这里编译C++11代码,请使用以下其中之一:

  • g++ -std=c++11 input.cxx -o a.out(通常是GNU编译器)
  • g++ -std=gnu++11 input.cxx -o a.out

在Mavericks之前的OS X上:实际上,g++clang++ 的别名,而苹果旧版本的libstdc++是默认的。你可以通过传递 -stdlib=libc++ 来使用libc++(它包含C++11库支持)。如果你想在这里编译C++11代码,请使用以下其中之一:

  • g++ -std=c++11 -stdlib=libc++ input.cxx -o a.out(不是GNU编译器,而是clang!)
  • g++ -std=gnu++11 -stdlib=libc++ input.cxx -o a.out(不是GNU编译器,而是clang!)
  • clang++ -std=c++11 -stdlib=libc++ input.cxx -o a.out
  • clang++ -std=gnu++11 -stdlib=libc++ input.cxx -o a.out

从Mavericks以后的OS X上:libc++是默认选项,你不需要传递任何 -stdlib=<...> 标志。自Xcode 10以来,不再支持使用libstdc++进行构建。已经使用libstdc++构建的现有代码将继续工作,因为仍然提供 libstdc++.6.dylib ,但不再支持对新代码使用libstdc++进行编译。

  • clang++ -std=c++11 input.cxx -o a.out
  • clang++ -std=gnu++11 input.cxx -o a.out
  • 这两行命令是用于编译C++代码的。其中,-std=c++11-std=gnu++11指定了C++标准的版本,input.cxx是输入文件名,-o a.out则指定了输出文件名为a.out

2
@raymondvaldes:没错。苹果拒绝分发包含C++11支持的更新版本的libstdc++。 - Bill Lynch
1
我能否在clang(而非clang++)中使用libstdc++? - hithwen
6
@hithwen: 我认为你的问题与这个答案无关。我建议你创建一个新的问题来询问。 - Bill Lynch
2
libc++libstdc++有什么区别?它们都是C++标准运行库吗? - nn0p
10
是的。它们是 C++ 标准库的两个不同实现。一个是由 GCC 团队开发,另一个是由 LLVM 团队开发。 - Bill Lynch
显示剩余7条评论

38
什么时候在使用gcc编译时需要使用标志“-stdlib=libstdc++”来指定编译器和链接器?
简短回答:永远不需要。
更详细的回答:"-stdlib"是Clang的标志,不会与任何版本的GCC兼容。在macOS上,有时候"gcc"和"g++"命令实际上是Clang的别名,而不是GCC,而Apple提供的libstdc++版本非常古老(大约2008年),因此当然不支持C++11。这意味着在macOS上,当使用Clang伪装成GCC时,您可以使用"-stdlib=libc++"选择Clang的新的C++11兼容库,或者您可以使用"-stdlib=libstdc++"选择属于博物馆的C++11之前的古董版本的libstdc++。但是在GNU/Linux上,"gcc"和"g++"确实是GCC,而不是Clang,因此"-stdlib"选项根本不起作用。

编辑:自从我写这个答案以来,GCC已经被更改为有条件地支持-stdlib标志,但对于大多数支持的平台,默认情况下该支持是禁用的。即使启用了它,默认值仍然是-stdlib=libstdc++,所以你永远不需要明确地指定它。GCC仍然会自动使用libstdc++。

编译器是否自动使用libstdc++?

是的,GCC始终使用libstdc++,除非你告诉它完全不使用任何标准库,可以使用-nostdlib-nostdlib++选项(在这种情况下,你需要避免使用任何标准库功能,或者使用-I-L-l标志来指定替代的头文件和库文件集)。

我正在使用Ubuntu 13.10上的gcc4.8.2,我想使用c++11标准。我已经将-std=c++11传递给编译器。

你不需要做任何其他事情。GCC自带了自己的C++标准库实现(libstdc++),它与GCC本身一起开发和测试,所以GCC的版本和libstdc++的版本是100%兼容的。如果你使用-std=c++11编译,那么会启用g++编译器中的C++11特性,同时也会启用libstdc++头文件中的C++11特性。

我在我的项目中使用了clang,但是对于CI来说,默认情况下编译器设置为gcc。所以这正是发生的问题。gcc不支持“-stdlib”,因此CI总是失败。 - tjysdsg
@JonathanWakely “或使用 -I 和 -L 和 -l 标志将其指向另一组头文件和库文件” -- 按照您的建议,我使用 -l:libstdc++.so.6.0.21 来覆盖 .19 版本,ldd 找到了它,但是除非 /usr/lib64/libstdc++.so.6 符号链接指向 .21 版本,.21 的符号会被忽略。如何绕过符号链接呢? - Jeff Brower
@JeffBrower 这是一个完全不同的问题,不应该在这里留评论。简短回答:你为什么要那样做?不要那样做,因为这不是使用 GCC 或 libstdc++ 的有效方式。较长回答:你不能这样做,你需要让动态加载器(ld.so)在另一个目录中找到一个不同的 libstdc++.so.6,在该目录中它是指向其他版本的符号链接,参见 https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dynamic_or_shared.html#manual.intro.using.linkage.dynamic -- 但你为什么要那样做?不要那样做,因为这不是使用 GCC 或 libstdc++ 的有效方式。 - Jonathan Wakely
@JonathanWakely,那我误解了你的建议,抱歉。 - Jeff Brower
1
@IceFire,那个答案说你需要在clang中使用-stdlib=libc++,这个问题是在问你何时需要在gcc中使用-stdlib=libstdc++。完全不一样的东西。 - undefined
显示剩余3条评论

7
如果您使用g++前端而不是gcc前端,编译器将自动使用libstdc++。请注意,HTML标签已被保留。

2
确实。只是要澄清一下:OP问的是“使用gcc编译时?”如果在一堆.o文件上运行gcc,那么我认为它会假设它们只是C程序,并且不会链接任何*C ++*内容。但是如果您使用g ++(或者在gcc命令行中有任何cpp文件),那么我认为它会意识到应该包括stdc ++。但我不太确定。这是你想说的吗? - Aaron McDaid
1
为了澄清我的问题,当我说gcc时,我指的是GNU编译器集合(作为整体)。由于我正在谈论C++代码,因此我将使用g++前端。 - Raymond Valdes
哇,这个不是很明显。 - garyF
1
@RaymondValdes 当提到整个GCC时,通常说的是GCC,以区别于“gcc”驱动程序。 - Jonathan Wakely
1
@Torsten,你所指的是如果使用g++而不是gcc,则会自动链接到libstdc++。如果使用gcc编译C++文件(扩展名为.cc.C.cpp),则它将使用C++前端编译代码,并自动通过#include使libstdc++头文件可用,与使用g++编译时完全相同。只有链接步骤根据您使用的是gcc还是g++来处理libstdc++。 - Jonathan Wakely

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接