CMakeでC ++ 11をアクティブ化するにはどうすればよいですか?


356

CMakeで生成されたmakefileを実行してプログラムをコンパイルしようとすると、次のエラーが発生します。

範囲ベースのforループは、C ++ 98モードではサポートされていません。

にを追加add_definitions(-std=c++0x)してみましたがCMakeLists.txt、効果がありませんでした。

私もこれを試しました:

if(CMAKE_COMPILER_IS_GNUCXX)
    add_definitions(-std=gnu++0x)
endif()

私がするときg++ --version、私は得ます:

g ++(Ubuntu / Linaro 4.6.1-9ubuntu3)4.6.1

私も試しましたがSET(CMAKE_CXX_FLAGS "-std=c++0x")、これも機能しません。

CMakeを使用してC ++ 11の機能をアクティブ化する方法がわかりません。


11
SET(CMAKE_CXX_FLAGS "-std=c++0x")私のために罰金を動作しますので、CMakeListsファイル内のどこかに問題がある可能性があります。後で誤ってCMAKE_CXX_FLAGSの内容を上書きしないようにしてください。
ComicSansMS

7
add_definitions(-std = c ++ 11)は、CMake 2.8.8で動作します
kyku

@ComicSansMS:あなたは完全に正しいです!私はそれを上書きしましたが、それは私自身のミスでした。私はそれを修正しました、そして今、それはうまくいきます!C ++ 11のものはとてもクールです!構造のベクトルでループしたかったのですが、範囲ベースのforループがない場合、反復子と不必要なコーディングノイズが必要になります。私はBOOST_FOREACHを使用することもできると思いますが、まあ…
Subhamoy S.

32
CMake≥3.1の場合set(CMAKE_CXX_STANDARD 11)(ターゲットを定義する前)が最善の方法です。
emlai

@tuple_catターゲットベースで行うこともできます。ただし、CXX_STANDARDはMSVCでは機能しないので、target_compile_featuresクロスプラットフォームで機能するものが必要な場合は基本的にフォールバックする必要があることに注意してください。
Ela782 2016

回答:


395

CMake 3.1では、使用可能なCMAKE_CXX_STANDARD変数が導入されました。CMake 3.1を常に使用できることがわかっている場合は、これを最上位のCMakeLists.txtファイルに書き込むか、新しいターゲットが定義される直前に配置できます。

set (CMAKE_CXX_STANDARD 11)

古いバージョンのCMakeをサポートする必要がある場合は、次のマクロを使用して使用できます。

macro(use_cxx11)
  if (CMAKE_VERSION VERSION_LESS "3.1")
    if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
      set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
    endif ()
  else ()
    set (CMAKE_CXX_STANDARD 11)
  endif ()
endmacro(use_cxx11)

現在、マクロはGCCのみをサポートしていますが、他のコンパイラに拡張することは簡単です。

次にuse_cxx11()、C ++ 11を使用するターゲットを定義するCMakeLists.txtファイルの先頭に書き込むことができます。

macOSをターゲットとするclangユーザー向けのCMakeの問題#15943

CMakeとclangを使用してmacOSをターゲットにしている場合、機能が単純に機能しない(コンパイラフラグを追加しない)可能性のあるバグがありCMAKE_CXX_STANDARDます。次のいずれかを実行してください。

  • cmake_minimum_requiredを使用して、CMake 3.0以降を要求するか、
  • projectコマンドの前にCMakeLists.txtファイルの先頭にある次のコードを使用して、ポリシーCMP0025をNEWに設定します。

    # Fix behavior of CMAKE_CXX_STANDARD when targeting macOS.
    if (POLICY CMP0025)
      cmake_policy(SET CMP0025 NEW)
    endif ()

12
これは受け入れられる答えになるはずです。各ターゲットのプロパティを個別に操作する必要はなく、クロスプラットフォームで機能します。
DevSolar 2016年

4
同意されたとおり、これはCMake 3.1+の時点で受け入れられる答えになるはずです。Macでは動作しないようですが。Macのデフォルトである--stdlib = libc ++を使用して--std = c ++ 11を強制的に指定できます。代わりに、CMAKE_CXX_STANDARDは、サポートされている場合は常にgnu拡張を含み、結果は--stdlib = libc ++に対してビルドされないようです。代わりに、gnuの--stdlib = libstdc ++に切り替える必要があります。Macは特別なケースですが。Linuxの場合、libstdc ++でgnu ++ 11を選択するのが標準です。もちろん、フラグを追加するif(APPLE)add_compile_options()で簡単に修正できます。
Atifm 2016年

2
このアプローチの1つの問題はgnu++11、これらの変数が定義されている場合でも適用されることset(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION clang) set(CMAKE_ANDROID_STL_TYPE c++_static)です。私にとって唯一の実行可能な方法はクラシックだったset (CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
アントニオ

2
macOSでは動作しません(CMake 3.9.4、homebrew-clang)。他の人を絶望から救う。それが@EvanMoranで機能する理由はわかりませんが、私では機能しません。
Unapiedra 2017年

2
@Unapiedra:これはCMakeのバグですが、回避できます。gitlab.kitware.com/ cmake / cmake / issues / 15943を
David Grayson

186

CMakeコマンドtarget_compile_features()は、必要なC ++機能を指定するために使用されますcxx_range_for。CMakeはC ++標準を使用するように誘導します。

cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
project(foobar CXX)
add_executable(foobar main.cc)
target_compile_features(foobar PRIVATE cxx_range_for)

CMakeは、C ++コンパイラが適切なコマンドラインフラグで呼び出されることを確認するためadd_definitions(-std=c++11)、CMake変数を使用したり変更したりする必要はありませんCMAKE_CXX_FLAGS

たぶん、あなたのC ++プログラムは以外のC ++機能を使用していますcxx_range_for。CMakeグローバルプロパティCMAKE_CXX_KNOWN_FEATURESは、選択可能なC ++機能をリストします。

使用する代わりに target_compile_features()する、CMakeプロパティCXX_STANDARD を 設定CXX_STANDARD_REQUIREDしてCMakeターゲットにC ++標準を明示的に指定することもできます 。

こちらもご覧ください 私のより詳細な回答


4
今日の編集は誤解を招くようです。CMake 3.0.0にはtarget_compile_featuresは含まれていません。私が間違っていたら訂正してください。コマンドは、CMakeのナイトリービルドにのみ存在すると思います。
ErikSjölund、2014

4
私は、これが最も正確な答えだと思います
のMichałWalenciak

8
これが本来のやり方だと思います。他の答えは手動でフラグを追加するだけなので、非互換性が生じます。しかし、これはCMakeの3.1以上でのみ利用可能であるように思わ
ウリ・ケーラー

2
@UliKöhlerこれは実際にはまだ使用できず、3.2の一部のコンパイラで表示される可能性があります。この方法を短期的に使用しないでください。その完全にポータブルではありません。
Doug

2
CMake 2.6でこれを行う方法はありますか?
nuzzolilo

93

使っています

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(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()

あなたが一緒にプレイしたい場合はしかしC++11g++ 4.6.1かなり古いです。新しいg++バージョンを入手してください。


4
これは、私にとって、この質問に対する唯一の正解であり、g ++を使用する最新のLinuxでの現在の(ロールアウトされた)cmakeです。
Patrick B.

1
これをコピーして貼り付けたところ、問題なく動作しました。私はCMAKE 2.8.9を使用してCygwinを使用しています。CMAKEメーリングリストをフォローしており、WebKitをさまざまなコンパイラーに移植したので、ここで読んでいるほとんどのアプローチについて知っています。WebKitポート用に行ったことは、CMake 2.8.12をインストールすることでした。しかし、CygwinのCMAKEが古いことを知っているので、そのバージョンに適用できるものが欲しかった。(WebKitをCygwinに移植していない、申し訳ありません)
カーディフスペースマン

素晴らしい、これは古いCMakeとg ++ 4.6のドロップインです(そして将来も保証されています)。私は- CXX_STANDARDベースの回答にも賛成しましたが、これが私の状況で役立つ唯一の回答でした。
Tomasz Gandor 2015年

これはまさに私が探していたものですが、そのモジュールを使用するために必要な最小のcmakeバージョンが何であるかは明確ではありません。cmake --help-moduleはあまり役に立ちません。
Jan Segre 2015年

1
@JanSegreモジュールは2.4で最初に登場しました、cmake.org /…
KoKuToru

57

Cxx標準を設定する最も簡単な方法は次のとおりです。

 set_property(TARGET tgt PROPERTY CXX_STANDARD 11)

詳細については、CMakeのドキュメントを参照してください。


2
はい、これは間違いなく最新のCMake(3.1以降)でこれを行うための最良の方法の1つに見えます
Erburethは、モニカを

14
またはset(CMAKE_CXX_STANDARD 11)、その後に作成されるすべてのターゲットのデフォルトプロパティを定義することもできます。
emlai

1
これは、異なるターゲットに異なるC ++標準を設定する場合に必要なソリューションでもあります。これはset、@ emlaiによって提案されるコマンドはグローバルであり、後続のすべてのターゲットに影響するためです。
エリオットスローター

40

結局のところ、SET(CMAKE_CXX_FLAGS "-std=c++0x")アクティベート多くのC ++ 11個の機能はありません。うまくいかなかった理由は、ステートメントが次のようになったためです。

set(CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS} -g -ftest-coverage -fprofile-arcs")

このアプローチに従って、どういうわけか-std=c++0xフラグは上書きされ、機能しませんでした。フラグを1つずつ設定するか、listメソッドを使用して機能しています。

list( APPEND CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS} -g -ftest-coverage -fprofile-arcs")

36
私は常に使用するだけです:SET(CMAKE_CXX_FLAGS "$ {CMAKE_CXX_FLAGS} -std = c ++ 11")#gcc> = 4.7の場合、または4.6の場合はc ++ 0x
David Doria

私はかつてそのための小さなスクリプトを実行しました(ただし完全ではありません):github.com/Morwenn/POLDER/blob/master/cmake/set_cxx_norm.cmake
Morwenn

9
-1。コマンドラインからCMAKE_CXX_FLAGSを指定すると、2番目の方法でビルドコマンドにセミコロンが生成されます(元のCMAKE_CXX_FLAGSを2回繰り返します)。
ニコライ

:代わりに、手動で-gフラグを追加するのは、デバッグにCMAKE_BUILD_TYPE変数を設定する必要がありvoices.canonical.com/jussi.pakkanen/2013/03/26/...
bames53

1
CXX_STANDARDそれはコンパイラに依存しないでとプロパティが優れています。
jaskmar 2018


19

CMake 3.8以降では、使用できます

target_compile_features(target PUBLIC cxx_std_11)

1
これは、CMakeの最新バージョンの推奨される方法です
camino

PUBLICここの機能は何ですか?
Rotsiser Mho

2
@RotsiserMho PUBLICは、ターゲットに依存する他のターゲットでもC ++ 11を使用することを意味します。たとえば、ターゲットがライブラリの場合、ライブラリにリンクするすべてのターゲットtarget_link_librariesはC ++ 11サポートでコンパイルされます。
まつげ

17

これは、C ++ 11サポートを有効にするもう1つの方法です。

ADD_DEFINITIONS(
    -std=c++11 # Or -std=c++0x
    # Other flags
)

この方法のみが機能し、他の方法が失敗する場合があります。CMakeの最新バージョンと関係があるのか​​もしれません。


9
これは、C ++コンパイラのみを使用している場合にのみ機能します。CCコンパイラも使用している場合は失敗します。
Emmanuel

5
add_definitionsDEFINITIONS、つまり-D SOMETHINGを追加するためにのみ使用されることになっています。そして@Emmanuelが言ったように、それは多くの場合機能しません。
xuhdev 2014年

以前はそれを使用してadd_definitionsいましたが、フラグを設定するために作成されていないため、Cファイルをインクルードすると問題が発生しました。
Jan Segre 2015年

17

最新のCMake(> = 3.1)では、グローバル要件を設定する最良の方法は次のとおりです。

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

これは、「すべてのターゲットにC ++ 11が必要です。これはオプションではなく、GNUまたはMicrosoftの拡張機能を使用したくない」と解釈されます。C ++ 17の時点で、これはまだIMHOが最良の方法です。

ソース:CMakeでC ++ 11以降を有効にする


1
この方法は、最新のCMakeがない場合、C ++の最新バージョンには理想的ではありません。たとえば、CMake 3.12までこの方法でC ++ 2aを有効にすることはできません。
ルスラン

6

私にとってうまくいくのは、CMakeLists.txtに次の行を設定することです。

set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

このコマンドを設定すると、コンパイラーのC ++ 11機能がアクティブになり、cmake ..コマンドの実行後range based for loops、コードで使用してエラーなしでコンパイルできるようになります。


これは、フラグを使用するので-std=c++11、正確に必要な場合、最終的には最良の回答です。これは望ましくない場合があります。set (CMAKE_CXX_STANDARD 11)-std=gnu++11
アントニオ

1
@Antonioset (CMAKE_CXX_EXTENSIONS OFF)
mloskot

3

この2行で十分だと思います。

set(CMAKE_CXX_STANDARD 11)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

1
これは、プロジェクト内のすべてのターゲットが同じC ++標準を使用する場合に意味があります(たとえば、すべてのコンパイル済みライブラリと実行可能ファイルはC ++ 11を使用します)。それ以外の場合は、target_compile_features他の回答に示されているように、個々のターゲットに適用されるCmake 関数がより推奨されるアプローチです。
アラン

3

常に最新のC ++標準をアクティブ化したい場合は、最近の(CMake 3.8およびCMake 3.11)CMAKE_CXX_STANDARDの値17および20の追加に照らして、David Graysonの回答の私の拡張を以下に示します。

IF (CMAKE_VERSION VERSION_LESS "3.8")
    SET(CMAKE_CXX_STANDARD 14)
ELSEIF (CMAKE_VERSION VERSION_LESS "3.11")
    SET(CMAKE_CXX_STANDARD 17)
ELSE()
    SET(CMAKE_CXX_STANDARD 20)
ENDIF()

# Typically, you'll also want to turn off compiler-specific extensions:
SET(CMAKE_CXX_EXTENSIONS OFF)

set (CMAKE_CXX_STANDARD 11)リンクされた回答の代わりにそのコードを使用してください。)


1

最新のcmakeは、特定のバージョンのC ++を使用するようにコンパイラーを構成するより簡単な方法を提供します。誰でも必要なことは、関連するターゲットプロパティを設定することだけです。cmakeサポートされているプロパティのうち、特定のバージョンのC ++をサポートするようにコンパイラーを構成する方法を決定するために使用されるプロパティは次のとおりです。

  • CXX_STANDARDターゲットをビルドするために機能が要求されるC ++標準を設定します。11C ++ 11をターゲットにするには、これを設定します。

  • CXX_EXTENSIONS、コンパイラ固有の拡張機能が要求されるかどうかを指定するブール値。これをOffに設定すると、コンパイラ固有の拡張機能のサポートが無効になります。

実例として、これはの最小限の実用的な例ですCMakeLists.txt

cmake_minimum_required(VERSION 3.1)

project(testproject LANGUAGES CXX )

set(testproject_SOURCES
    main.c++
    )

add_executable(testproject ${testproject_SOURCES})

set_target_properties(testproject
    PROPERTIES
    CXX_STANDARD 11
    CXX_EXTENSIONS off
    )

-5

OS XおよびHomebrew LLVM関連:

その後にcmake_minimum_required(VERSION 3.3)とproject()を呼び出すことを忘れないでください!

または、CMakeがproject()行1の前に暗黙的に挿入され、Clangバージョンの検出で問題が発生し、その他の種類の問題が発生する可能性があります。これが関連する問題です。


2
特に、OSXやLVVMに関する問題ではありません。また、C ++ 11開発でCMake v3.xを必要とする理由はありません。clangのバージョン検出に関しては-それはOPが尋ねたことではありません。
アインポクルム2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.