Как получить CMake для передачи либо std = С++ 14/С++ 1y, либо С++ 17/С++ 1z на основе версии GCC?

GCC 4.x не принимает --std=c++14 для кода С++ 14 - вместо этого он принимает --std=c++1y. Более поздние версии принимают --std=c++1z но (возможно) не --std=c++17 который еще не установлен (написав это в 2016 году). Возможно, есть и подобные проблемы с С++ 11.

Имеет ли CMake какое-либо средство (возможно, как модуль) для передачи правильного переключателя в соответствии с версией GCC?

Ответ 1

Если вы хотите указать конкретную версию C++, рекомендуемый способ сделать это с помощью CMake 3.1 и более CXX_STANDARD CXX_STANDARD_REQUIRED CXX_EXTENSIONS целевые свойства CXX_STANDARD, CXX_STANDARD_REQUIRED и CXX_EXTENSIONS или их эквиваленты переменных для указания целевых значений по умолчанию. Подробную информацию можно найти здесь, но короткая версия выглядит примерно так:

cmake_minimum_required(VERSION 3.1)
project(Example)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# ... Define targets, etc. as usual

Затем CMake должен выбрать соответствующий флаг компилятора для запрошенного стандарта C++ на основе того, что поддерживает компилятор, или ошибки, если он не поддерживает запрошенный стандарт.

Следует также отметить, что CMake может обновить цель, чтобы использовать более поздний языковой стандарт, чем тот, который указан его целевым свойством CXX_STANDARD. Использование требований к компиляции (как упоминалось в ответе @FlorianWolters) может повысить требования к языковым стандартам. Фактически, CMake всегда будет выбирать более сильное языковое требование, указанное либо целевым свойством CXX_STANDARD либо требованиями к компиляции, установленными на целевом объекте. Также обратите внимание, что документация CMake по 3.10.1 не точно отражает то, как CXX_EXTENSIONS взаимодействует с функциями компиляции, поскольку CXX_EXTENSIONS вступает в силу, если CXX_STANDARD также указан для большинства распространенных компиляторов (поскольку они указаны вместе с одним флагом компилятора).

Ответ 2

Современный код CMake должен использовать команду target_compile_features для запроса определенного стандарта C++. Это может быть указано только как требование к сборке (PRIVATE), только требование к потреблению (INTERFACE) или требование сборки и использования (PUBLIC).

Пример:

cmake_minimum_required(VERSION 3.9.4)

project(cpp-snippets)
add_executable(cpp-snippets "main.cpp")
target_compile_features(cpp-snippets PRIVATE cxx_std_17)

Для получения дополнительной информации см. Раздел "Требуемые стандарты языка" в официальной документации CMake для компонентов cmake-compile.

Ответ 3

Проверьте, поддерживает ли компилятор флаги? Возможно, что-то вроде

include(CheckCXXCompilerFlag)

# Check for standard to use
check_cxx_compiler_flag(-std=c++17 HAVE_FLAG_STD_CXX17)
if(HAVE_FLAG_STD_CXX17)
    # Have -std=c++17, use it
else()
    check_cxx_compiler_flag(-std=c++1z HAVE_FLAG_STD_CXX1Z)
    if(HAVE_FLAG_STD_CXX1Z)
        # Have -std=c++1z, use it
    else()
        # And so on and on...
    endif()
endif()