83

コンパイラが C++11 をサポートしているかどうかを CMake が自動的に検出できるようにする方法はありますか?

コンパイラが C++11 をサポートしていないため、CMake の実行中にコードがコンパイルされないことをユーザーに通知するとよいでしょう。現時点では、C++11 フラグを設定しています。ただし、コンパイラがサポートしていない場合、ユーザーは CMake の実行中にエラーではなくコンパイル エラーを受け取ります。

のように機能するものは完璧find_package()です。ただし、必要な機能を提供するモジュールまたは関数は見つかりませんでした。

std=c++0xさらに、コンパイラがフラグまたはフラグを必要とするかどうかを検出する機能があると便利ですstd=c++11

利用可能なものはありますか、それとも自分で開発する必要がありますか?

以下は、これまでに使用したコードの一部ですが、GNU'c GCC コンパイラでのみ機能します。より一般的な解決策があればいいのですが。

if(CMAKE_COMPILER_IS_GNUCXX)
   execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
   if (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)
        message(STATUS "C++11 activated.")
        add_definitions("-std=gnu++11")
   elseif(GCC_VERSION VERSION_GREATER 4.3 OR GCC_VERSION VERSION_EQUAL 4.3)
        message(WARNING "C++0x activated. If you get any errors update to a compiler which fully supports C++11")
        add_definitions("-std=gnu++0x")
   else ()
        message(FATAL_ERROR "C++11 needed. Therefore a gcc compiler with a version higher than 4.3 is needed.")   
   endif()
else(CMAKE_COMPILER_IS_GNUCXX)
   add_definitions("-std=c++0x") 
endif(CMAKE_COMPILER_IS_GNUCXX)
4

6 に答える 6

42

現時点では、CMake には C++11 をサポートするための便利な形式がありません。理想的には、次のように C++11 プロジェクトを指定します。

project(foo CXX11)

あなたの先頭にCMakeLists.txt。しかし、CXX11プロジェクト タイプは (まだ) 存在しません。それまでは、次の 2 段階の手法を使用できます。

  1. コンパイラの種類とバージョンを確認する
  2. それに応じてビルド フラグを調整します。

たとえば、これは Clang と GCC で C++11 をサポートするために使用するものです。

# Initialize CXXFLAGS.
set(CMAKE_CXX_FLAGS                "-Wall -std=c++11")
set(CMAKE_CXX_FLAGS_DEBUG          "-O0 -g")
set(CMAKE_CXX_FLAGS_MINSIZEREL     "-Os -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE        "-O4 -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")

# Compiler-specific C++11 activation.
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
    execute_process(
        COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
    if (NOT (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7))
        message(FATAL_ERROR "${PROJECT_NAME} requires g++ 4.7 or greater.")
    endif ()
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
else ()
    message(FATAL_ERROR "Your C++ compiler does not support C++11.")
endif ()
于 2012-06-12T20:50:12.460 に答える
9

この記事の執筆時点(GCC 4.8 より前)では、C++11 フラグを検出して追加することはお勧めできません。これは、標準 (少なくとも GCC の場合) を変更するとABI の互換性が失われ、リンク エラーが発生する可能性があるためです。

したがって、C++11 標準の使用は、プロジェクトの初期 CMake 構成時にコンパイラ設定で明示的に指定する必要があります。

CXX='g++ -std=c++11' cmake /path/to/source

つまり、 -std=c++11 の使用は、別のコンパイラのように扱われるべきであり、プロジェクト内で混合または変更されるべきではありません。

于 2013-02-02T16:28:22.160 に答える
8

使用する:

include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
    message(FATAL_ERROR "Compiler ${CMAKE_CXX_COMPILER} has no C++11 support.")
endif()

これは、マイナーな変更を加えて CMake で C++11 (C++0x) を有効にすることによるものです。

于 2014-09-14T07:17:24.313 に答える
6

CMake 3.8 以降を使用している場合は、C++11 以上cxx_std_11を要求する機能を使用できます。

target_compile_features(Hello PUBLIC cxx_std_11)

CMake 3.1* 以降では、これを行う適切で簡単な方法はCXX_STANDARD、特定のターゲットに対してプロパティを使用することです。たとえば、auto(named main.cpp) を使用した次の簡単な例を考えます。

#include <iostream>

int main() {
    auto num = 10;
    std::cout << num << std::endl;
    return 0;
}

以下CMakeLists.txtは、C++11 サポートを有効にします。

cmake_minimum_required(VERSION 3.3)
project(Hello CXX)

set(SOURCE_FILES main.cpp)
add_executable(Hello ${SOURCE_FILES})

set_property(TARGET Hello PROPERTY
    CXX_STANDARD 11
    CXX_STANDARD_REQUIRED ON
)

これにより、 などの必要なフラグが追加され-std=c++11ます。CXX_STANDARD_REQUIREDプロパティは、標準が以前のバージョンに減衰するのを防ぐことに注意してください。


CMAKE_CXX_KNOWN_FEATURES次のように、使用するを指定する別の適切な方法ですが、単純ではありませんcxx_auto_type

cmake_minimum_required(VERSION 3.3)
project(Hello CXX)

set(SOURCE_FILES main.cpp)
add_executable(Hello ${SOURCE_FILES})
target_compile_features(Hello PRIVATE cxx_auto_type)

* CMake 3.1 では試していませんが、CMake 3.3 では動作することを確認しています。3.1のドキュメントにはこれが記載されているため、動作するはずです。

于 2015-11-04T15:43:12.877 に答える