如何防止基于 g++ 编译器版本的不同编译

How do I prevent different compilation based on the version of my g++ compiler?

本文关键字:编译 版本 编译器 何防止 g++      更新时间:2023-10-16

>场景:
我正在两台不同的机器上构建软件。
其中一台机器具有完全兼容的 C++11 版本的 g++
另一个没有。

机器 1 (Linux(:

$ g++ --version
g++ (Ubuntu 5.1.0-0ubuntu11~14.04.1) 5.1.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  

机器 2(带有 Cygwin 的窗口(:

$ g++ --version
g++ (GCC) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  

我在这两台机器上构建的C++软件一直支持C++98。

但是,如果C++的新功能可用,则将使用它们。
(有问题的软件是C++ Catch进行单元测试(。

问题:
我有一个通用的makefile来构建这个软件。 在Cygwin它成功构建软件。 在Linux,使用较新的编译器,它无法构建,因为我假设它检测到编译器的版本并尝试使用更现代的C++功能。

这是用于浏览目的的错误转储。 大多只是nullptr_t相关。 也许与模板推理的新规则有关(不完全确定(:

catch.hpp:833:17: error: ‘nullptr_t’ in namespace ‘std’ does not name a type
     inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
                 ^
catch.hpp:954:58: error: ‘template<Catch::Internal::Operator Op, class T> bool Catch::Internal::compare’ conflicts with a previous declaration
     template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
                                                          ^
catch.hpp:948:44: note: previous declaration ‘namespace Catch::Internal { }::compare’
     template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
                                            ^
catch.hpp:954:53: error: ‘nullptr_t’ is not a member of ‘std’
     template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
                                                     ^
catch.hpp:954:70: error: expected primary-expression before ‘*’ token
     template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
                                                                      ^
catch.hpp:954:72: error: ‘rhs’ was not declared in this scope
     template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
                                                                        ^
catch.hpp:954:76: error: expression list treated as compound expression in initializer [-fpermissive]
     template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
                                                                            ^
catch.hpp:954:44: warning: variable templates only available with -std=c++14 or -std=gnu++14
     template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
                                            ^
catch.hpp:954:78: error: expected ‘;’ before ‘{’ token
     template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
                                                                              ^
catch.hpp:957:66: error: ‘std::nullptr_t’ has not been declared
     template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
                                                                  ^
catch.hpp:957:44: error: redefinition of ‘template<Catch::Internal::Operator Op, class T> bool Catch::Internal::compare(T*, int)’
     template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
                                            ^
catch.hpp:948:44: note: ‘template<Catch::Internal::Operator Op, class T> bool Catch::Internal::compare(T*, int)’ previously declared here
     template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
                                            ^
In file included from main.cpp:2:0:
catch.hpp:1088:38: error: ‘std::string Catch::toString’ redeclared as different kind of symbol
 std::string toString( std::nullptr_t );
                                      ^
catch.hpp:1085:13: note: previous declaration ‘std::string Catch::toString(unsigned char)’
 std::string toString( unsigned char value );
             ^
catch.hpp:1088:23: error: ‘nullptr_t’ is not a member of ‘std’
 std::string toString( std::nullptr_t );
                       ^
In file included from main.cpp:2:0:
catch.hpp:7336:38: error: ‘std::string Catch::toString’ redeclared as different kind of symbol
 std::string toString( std::nullptr_t ) {
                                      ^
In file included from main.cpp:2:0:
catch.hpp:1232:13: note: previous declaration ‘template<class T, class Allocator> std::string Catch::toString(const std::vector<_Tp, _Alloc>&)’
 std::string toString( std::vector<T,Allocator> const& v ) {
             ^
In file included from main.cpp:2:0:
catch.hpp:7336:23: error: ‘nullptr_t’ is not a member of ‘std’
 std::string toString( std::nullptr_t ) {

通过确保使用 --std=c++11 标志编译g++,可以在Linux计算机上轻松解决此问题。 但是,我不希望在两台计算机上使用两个单独的生成文件。 我无法将 --std=c++11 标志添加到两个构建中,因为版本 4.9 还没有该标志。

问题:
如何在不同版本的g++上使用相同的命令启用交叉编译?代码根据g++的版本以不同的方式构建 - 在这种情况下,有时需要传递std标志。

附加:
我尝试为g++两个版本提供标志--std=c++98,但它在Linux版本中仍然失败。 此处的目标是在两台计算机上使用相同的命令。

在Windows平台上,我建议使用Stephan Lavavej的Nuwen Distro。唯一的障碍是你不能使用std::thread设施,但boost::thread提供了一个几乎无缝的替代方案。

在Windows上,我建议切换到MSYS2,特别是如果你需要c ++ 11支持。最新版本有mingw64 g++4.9.2。我能够成功地使用 c++11/boost/python 构建我的 Ubuntu 项目,而我无法在 Cygwin 或 MSVC2015 RC 上做到这一点。MSYS2 有一个名为 pacman 的包管理器,它有点等效apt-get/yum

您可以

在此处查看大量预构建的内容。

这里介绍非常紧凑

相关文章: