Как мне активировать C++ 11 в CMake?

Когда я пытаюсь запустить созданный CMake make файл для компиляции моей программы, я получаю сообщение об ошибке, что

диапазон, основанный на циклах, не поддерживается в режиме 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"), который также не работает.

Я не понимаю, как я могу активировать функции C++ 11 с помощью CMake.

Ответ 1

Как оказалось, SET(CMAKE_CXX_FLAGS "-std=c++0x") активирует многие возможности С++ 11. Причина, по которой это не сработало, заключалась в том, что утверждение выглядело так:

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

После этого подхода, как-то флаг -std=c++0x был перезаписан, и он не работал. Установка флагов один за другим или использование метода списка работает.

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

Ответ 2

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() в верхней части любого файла CMakeLists.txt, который определяет цель, которая использует С++ 11.

CMake выпуск № 15943 для пользователей clang, ориентированных на macOS

Если вы используете CMake и clang для нацеливания на macOS, существует ошибка bug, которая может привести к тому, что функция CMAKE_CXX_STANDARD просто не будет работать (не добавлять какие-либо флаги компилятора). Убедитесь, что вы делаете одно из следующих действий:

  • Используйте cmake_minimum_required, чтобы потребовать CMake 3.0 или новее, или
  • Установите для политики CMP0025 значение NEW с помощью следующего кода в верхней части файла CMakeLists.txt перед командой project:

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

Ответ 3

Команда CMake target_compile_features() используется для указания требуемой функции С++ cxx_range_for. Затем CMake побуждает использовать стандарт С++.

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)

Нет необходимости использовать add_definitions(-std=c++11) или изменить переменную CMake CMAKE_CXX_FLAGS, потому что CMake убедится, что компилятор С++ вызывается с помощью соответствующей команды флаги линии.

Возможно, ваша программа на С++ использует другие функции С++, чем cxx_range_for. Глобальное свойство CMake CMAKE_CXX_KNOWN_FEATURES перечисляет возможности С++, которые вы можете выбрать.

Вместо использования target_compile_features() вы также можете явно указать стандарт С++, установив свойства CMake CXX_STANDARD  а также CXX_STANDARD_REQUIRED для вашей цели CMake.

См. также мой более подробный ответ.

Ответ 4

Я использую

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++.

Ответ 5

Самый простой способ установить стандарт Cxx:

 set_property(TARGET tgt PROPERTY CXX_STANDARD 11)

Смотрите документацию CMake для более подробной информации.

Ответ 6

Самый простой способ:

add_compile_options(-std=c++11)

Ответ 7

Это еще один способ включить поддержку С++ 11,

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

Я встречал экземпляры, где работает только этот метод, а другие методы терпят неудачу. Может быть, это имеет какое-то отношение к последней версии CMake.

Ответ 8

Для CMake 3.8 и новее вы можете использовать

target_compile_features(target PUBLIC cxx_std_11)

Ответ 9

На современном CMake (> = 3.1) лучший способ установить глобальные требования:

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

Это переводится как "Я хочу С++ 11 для всех целей, это не обязательно, я не хочу использовать какие-либо расширения GNU или Microsoft". Начиная с С++ 17, это ИМХО лучший способ.

Источник: Включение С++ 11 и более поздних версий в CMake

Ответ 10

Что для меня работает, так это установить следующую строку в вашем CMakeLists.txt:

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

Установка этой команды активирует функции С++ 11 для компилятора и после выполнения команды cmake .. вы можете использовать range based for loops в своем коде и скомпилировать ее без каких-либо ошибок.

Ответ 11

Я думаю, что этих двух строк достаточно.

set(CMAKE_CXX_STANDARD 11)

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

Ответ 12

Если вы хотите всегда активировать последний стандарт C++, здесь мое расширение ответа Дэвида Грейсона, в свете недавних (CMake 3.8 и CMake 3.11) добавлений значений 17 и 20 для CMAKE_CXX_STANDARD) :

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() # CMake 3.11 or higher:
    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) в связанном ответе.)

Ответ 13

OS X и Homebrew LLVM:

Не забудьте вызвать cmake_minimum_required (ВЕРСИЯ 3.3) и project() после него!

Или CMake будет вставлять project() неявно перед строкой 1, вызывая проблемы с обнаружением версии Clang и, возможно, другими видами проблем. Вот связанная с этим проблема.