¿Cómo hacer que CMake pase std=c++14 / c++1y o c++17/c++1z basado en la versión GCC?


CCG 4.x no acepta el interruptor --std=c++14 para el código de C++14 - toma --std=c++1y en su lugar. Las versiones posteriores toman --std=c++1z pero (probablemente) no --std=c++17 que aún no se ha establecido (escribiendo esto en 2016). Tal vez haya problemas similares con C++11.

¿CMake tiene alguna facilidad (tal vez como un módulo) para pasar el interruptor correcto de acuerdo con la versión de GCC?

Author: einpoklum, 2017-03-16

3 answers

Cuando se desea especificar una versión particular de C++, la forma recomendada de hacer esto con CMake 3.1 y posteriores es usar el CXX_STANDARD, CXX_STANDARD_REQUIRED y CXX_EXTENSIONS propiedades de destino, o sus equivalentes de variables para especificar los valores predeterminados de destino. Los detalles completos se pueden encontrar aquí , pero la versión corta es algo como esto:

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 debe entonces seleccionar el indicador de compilador apropiado para el estándar C++ solicitado basado en lo que el compilador soporta, o error si no soporta el estándar solicitado.

También debe tenerse en cuenta que CMake puede actualizar el destino para usar un estándar de lenguaje posterior al especificado por su propiedad destino CXX_STANDARD. El uso de compile feature requirements (como se menciona en la respuesta de @FlorianWolters) puede elevar el requisito estándar del lenguaje. De hecho, CMake siempre elegirá el requisito de idioma más fuerte especificado por la propiedad de destino CXX_STANDARD o los requisitos de característica de compilación establecidos en el destino. Note also que la documentación de CMake a partir de la versión 3.10.1 no refleja con precisión la forma en que CXX_EXTENSIONS interactúa con las características de compilación, ya que CXX_EXTENSIONS solo tiene efecto si CXX_STANDARD también se especifica para los compiladores más comunes (ya que se especifican junto con la bandera de un compilador).

 48
Author: Craig Scott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-17 12:33:08

El código CMake moderno debe usar target_compile_features comando para solicitar un estándar específico de C++. Esto se puede especificar como requisito de compilación solamente (PRIVATE), requisito de uso solamente (INTERFACE) o requisito de compilación y uso (PUBLIC).

Ejemplo:

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)

Consulte la sección Requiriendo Estándares de lenguajeen la documentación oficial de CMake para cmake-compile-features para obtener más información.

 11
Author: Florian Wolters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-18 11:57:04

Compruebe si el compilador soporta las banderas? Tal vez algo como

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()
 8
Author: Some programmer dude,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-16 13:04:17