CMake에서 C ++ 11을 어떻게 활성화합니까?


356

CMake 생성 makefile을 실행하여 프로그램을 컴파일하려고하면 오류가 발생합니다.

C ++ 98 모드에서는 루프 기반 범위가 지원되지 않습니다.

나는 추가하는 시도 add_definitions(-std=c++0x)내에 CMakeLists.txt, 그러나 그것은 도움이되지 않았다.

나는 이것을 시도했다.

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

내가 할 때 g++ --version, 나는 얻는다 :

g ++ (우분투 / 리나로 4.6.1-9 우분투 3) 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 2016 년

7
add_definitions (-std = c ++ 11)는 CMake 2.8.8에서 작동합니다
kyku

@ComicSansMS : 당신은 완전히 옳습니다! 나는 그것을 덮어 썼는데, 그것은 내 자신의 실수였습니다. 나는 그것을 고쳤으며 이제는 잘 작동하고 있습니다! C ++ 11 물건은 매우 시원합니다! 루프를 기반으로 범위를 가지지 않으면 반복자와 불필요한 코딩 노이즈가 필요한 구조 벡터를 반복하고 싶었습니다. BOOST_FOREACH를 사용할 수는 있지만, 오 잘 ...
Subhamoy S.

32
CMake ≥3.1의 경우 set(CMAKE_CXX_STANDARD 11)(대상을 정의하기 전에) 가장 좋은 방법입니다.
emlai

@tuple_cat 타겟 기반으로도 할 수 있습니다. 그러나 MSVC에서는 작동 CXX_STANDARD하지 않으므로 기본적으로 target_compile_features크로스 플랫폼에서 작동하는 것을 원한다면 다시 넘어야 합니다.
Ela782

답변:


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 3.0 이상을 요구 하려면 cmake_minimum_required 를 사용하십시오 . 또는
  • 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

4
동의합니다. CMake 3.1 이상에서 허용되는 답변이어야합니다. 그래도 Mac에서는 작동하지 않는 것 같습니다. Mac의 기본값 인 --stdlib = libc ++를 사용하여 --std = c ++ 11을 제공 할 수 있습니다. 대신 CMAKE_CXX_STANDARD는 gnu 확장자가 지원되는 경우 항상 gnu 확장자를 포함하며 결과는 --stdlib = libc ++에 대해 빌드되지 않습니다. 대신 gnu의 --stdlib = libstdc ++로 전환해야합니다. Mac은 특별한 경우입니다. Linux의 경우 libstdc ++와 함께 gnu ++ 11을 선택하는 것이 일반적입니다. 물론 이는 플래그를 고정하기 위해 if (APPLE) add_compile_options ()로 쉽게 수정됩니다.
Atifm

2
이 접근 방식의 한 가지 문제점은 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}")
Antonio

2
macOS (CMake 3.9.4, homebrew-clang)에서는 작동하지 않습니다. 절망을 다른 사람을 구하십시오. 왜 @EvanMoran에서 작동하지만 확실하지 않습니다.
Unapiedra

2
@Unapiedra : 그것은 CMake의 버그하지만 당신은 그것을 해결할 수 있습니다 참조 gitlab.kitware.com/cmake/cmake/issues/15943
데이비드 그레이

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 ++ 컴파일러가 적절한 명령 행 플래그로 호출되는지 확인하므로 CMake add_definitions(-std=c++11)변수 를 사용 하거나 수정할 필요가 없습니다 CMAKE_CXX_FLAGS.

아마도 C ++ 프로그램이 이외의 다른 C ++ 기능을 사용하고있을 것 cxx_range_for입니다. CMake 전역 속성 CMAKE_CXX_KNOWN_FEATURES에는 선택할 수있는 C ++ 기능이 나열됩니다.

대신 사용 target_compile_features()도 CMake 속성을 설정하여 명시 적으로 C ++ 표준을 지정할 수 있습니다 당신 CXX_STANDARDCXX_STANDARD_REQUIRED당신의 CMake 목표를 위해.

더 자세한 답변을 참조하십시오 .


4
오늘의 수정 사항이 잘못된 것 같습니다. CMake 3.0.0에는 target_compile_features가 포함되어 있지 않습니다. 틀 렸으면 말해줘. CMake의 야간 빌드에만 명령이 있다고 생각합니다.
Erik Sjölund

4
나는 이것이 가장 정확한 대답이다라고 말하고 싶지만
마이클 Walenciak

8
나는 이것이해야한다고 생각합니다. 다른 답변은 수동으로 플래그를 추가하므로 비 호환성을 유발합니다. 그러나 이것은 CMake 3.1 이상에서만 사용할 수있는 것 같습니다
Uli Köhler

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++11, g++ 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

이것은 내가 찾던 것이지만 해당 모듈을 사용하는 데 필요한 최소 cmake 버전이 무엇인지는 확실하지 않습니다. cmake --help-module은 그것에 대해별로 도움이되지 않습니다.
Jan Segre

1
@JanSegre 모듈은 2.4, cmake.org/
KoKuToru

57

Cxx 표준을 설정하는 가장 쉬운 방법은 다음과 같습니다.

 set_property(TARGET tgt PROPERTY CXX_STANDARD 11)

자세한 내용 은 CMake 설명서 를 참조하십시오.


2
네, 이것은 현대 CMake (
3.1+

14
또는 set(CMAKE_CXX_STANDARD 11)그 후에 생성 된 모든 대상에 대한 기본 속성을 정의 할 수 있습니다 .
emlai

1
set@emlai가 제안한 명령이 전역 적이며 모든 후속 대상에 영향을주기 때문에 다른 대상에 대해 다른 C ++ 표준을 설정하려는 경우에도 필요한 솔루션 입니다.
Elliott Slaughter

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플래그를 덮어 쓰고 작동하지 않았습니다. 플래그를 하나씩 설정하거나 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, c ++ 0x for 4.6
David Doria

: 나는 한 번 그 (완료되지하지만)에 대한 약간의 스크립트했다 github.com/Morwenn/POLDER/blob/master/cmake/set_cxx_norm.cmake
Morwenn

9
-1. 명령 행에서 CMAKE_CXX_FLAGS를 지정하면 두 번째 메소드는 빌드 명령에서 세미콜론을 생성하고 원래 CMAKE_CXX_FLAGS를 두 번 반복합니다.
Nikolai

-g 플래그를 수동으로 추가하는 대신 CMAKE_BUILD_TYPE 변수를 디버그로 설정해야합니다. voices.canonical.com/jussi.pakkanen/2013/03/26/…
bames53

1
CXX_STANDARD는 컴파일러 불가지론으로 속성은 더 좋다.
jaskmar


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_librariesC ++ 11 지원으로 컴파일됩니다.
속눈썹

17

이것이 C ++ 11 지원을 가능하게하는 또 다른 방법입니다.

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

이 방법 만 작동하고 다른 방법이 실패하는 인스턴스가 발생했습니다. 아마도 최신 버전의 CMake와 관련이있을 수 있습니다.


9
C ++ 컴파일러 만 사용하는 경우에만 작동합니다. CC 컴파일러도 사용하면 실패합니다.
Emmanuel

5
add_definitionsDEFINITIONS, 즉 -D SOMETHING을 추가 할 때만 사용해야합니다. 그리고 @ Emmanuel이 말했듯이 많은 경우에 작동하지 않습니다.
xuhdev

나는 전에 그것을 사용했지만 add_definitions플래그 설정을 위해 만들어지지 않았기 때문에 C 파일을 포함시킬 때 문제가있었습니다 .
Jan Segre

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를 이런 식으로 활성화 할 수 없습니다.
Ruslan

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

이 두 줄만으로 충분하다고 생각합니다.

set(CMAKE_CXX_STANDARD 11)

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

1
이는 프로젝트의 모든 대상이 동일한 C ++ 표준을 사용하는 경우에 적합합니다 (예 : 모든 컴파일 된 라이브러리 및 실행 파일은 C ++ 11을 사용함). 그렇지 않으면 target_compile_features다른 답변에 표시된 것처럼 각 개별 대상에 적용되는 Cmake 기능이 더 권장되는 방법입니다.
Allan

3

항상 최신 C ++ 표준을 활성화하려는 경우 CMAKE_CXX_STANDARD에 대한 17 및 20 값의 최근 (CMake 3.8 및 CMake 3.11) 추가에 비추어 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가 요구 한 것이 아닙니다.
einpoklum 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.