Как активировать 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.
17 ответов
Как выясняется, 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( APPEND CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS} -g -ftest-coverage -fprofile-arcs")
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, который определяет цель, которая использует C++ 11.
CMake выпуск № 15943 для пользователей clang, ориентированных на macOS
Если вы используете CMake и clang для MacOS, существует ошибка, которая может привести к 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 ()
Команда 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)
Там нет необходимости использовать add_definitions(-std=c++11)
или изменить переменную CMake CMAKE_CXX_FLAGS
потому что CMake убедится, что компилятор C++ вызывается с соответствующими флагами командной строки.
Может быть, ваша программа C++ использует другие функции C++, чем cxx_range_for
, Глобальное свойство CMake CMAKE_CXX_KNOWN_FEATURES
перечисляет функции C++, которые вы можете выбрать.
Вместо того, чтобы использовать target_compile_features()
Вы также можете явно указать стандарт C++, установив свойства CMake CXX_STANDARD
а также CXX_STANDARD_REQUIRED
для вашей цели CMake.
Смотрите также мой более подробный ответ.
Я использую
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++
версия.
Самый простой способ установить стандарт Cxx:
set_property(TARGET tgt PROPERTY CXX_STANDARD 11)
Смотрите документацию CMake для более подробной информации.
На современном CMake (>= 3.1) лучший способ установить глобальные требования:
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
Это означает: "Я хочу C++11 для всех целей, это не обязательно, я не хочу использовать какие-либо расширения GNU или MS". Начиная с C++17, это ИМХО лучший способ.
Источник: https://crascit.com/2015/03/28/enabling-cxx11-in-cmake/
Для CMake 3.8 и новее вы можете использовать
target_compile_features(target PUBLIC cxx_std_11)
Это еще один способ включения поддержки C++11,
ADD_DEFINITIONS(
-std=c++11 # Or -std=c++0x
# Other flags
)
Я встречал случаи, когда только этот метод работает, а другие методы не работают. Может быть, это как-то связано с последней версией CMake.
Современный cmake предлагает более простые способы настройки компиляторов для использования определенной версии C++. Единственное, что нужно сделать, это установить соответствующие целевые свойства. Среди свойств, поддерживаемых cmake, те, которые используются для определения того, как настроить компиляторы для поддержки конкретной версии C++, следующие:
CXX_STANDARD
устанавливает стандарт C++, функции которого требуются для построения цели. Установите это как11
для таргетинга на C++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
)
Если вы хотите всегда активировать последний стандарт 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)
в связанном ответе).
Что работает для меня, это установить следующую строку в вашем CMakeLists.txt:
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
Установка этой команды активирует функции C++11 для компилятора и после выполнения cmake ..
команда, вы должны быть в состоянии использовать range based for loops
в вашем коде и скомпилируйте его без ошибок.
Я думаю, что только этих двух строк достаточно.
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
Если вы столкнетесь с той же ошибкой, используя cmake, что и я. Вам нужно установить
set (CMAKE_CXX_STANDARD 11)
активировать многопоточность, потому что она поддерживается только с С++ 11 ++
надеюсь, это поможет
Современный способ - указать минимально необходимый стандарт для С++ 11 с помощью:
target_compile_features(foo PUBLIC cxx_std_11)
Сюда:
- CMake может соблюдать стандарт C++ по умолчанию для компилятора, если он больше, чем C++11.
- Вы можете четко указать, требуется ли стандарт C++ во время сборки, во время использования или в обоих случаях. Это удобно для библиотек.
- Общедоступные функции компиляции распространяются на нижестоящие цели, поэтому они предоставляются бесплатно в этих целях, даже если они не используют эту функцию напрямую.
- Пользователи могут внешне установить другой стандарт C++ (в основном более новый) с помощью , либо из командной строки, либо из предустановок CMake. Если вы жестко кодируете
CMAKE_CXX_STANDARD
в CMakeLists никто не может переопределить стандарт C++ без редактирования ваших CMakeLists, что не очень приятно.
Требуется CMake >= 3.8
Вы можете использовать следующее. Это автоматически изменяет функцию в зависимости от вашей среды.
target_compile_features(your_target INTERFACE cxx_std_20)
Например,
- в Gnu / Linux следующее добавляет
-std=gnu++20
- в Windows с Clang / Ninja это становится
-std=c++20
- в Windows с MSVC становится
/std=c++20
Таким образом, вы поддерживаете как можно больше сред.
OS X и Homebrew LLVM связаны с:
Не забудьте вызвать cmake_minimum_required(VERSION 3.3) и project() после него!
Или CMake вставит project()
неявно перед строкой 1, вызывая проблемы с обнаружением версии Clang и, возможно, другие виды проблем. Вот связанная проблема.