sentencias para libro instrucciones for español dummies dev curso completo comandos codigos básico avanzado c++ c++11 cmake

para - libro de c++ completo



Cómo detectar el soporte de c++ 11 de un compilador con cmake (7)

En CMake 3.1 *, la forma correcta de hacerlo es usar la propiedad CXX_STANDARD para un objetivo determinado. Por ejemplo, dado este sencillo ejemplo usando auto (llamado main.cpp ):

#include <iostream> #include <memory> int main() { auto num = 10; std::cout << num << std::endl; return 0; }

El siguiente CMakeLists.txt habilitará la CMakeLists.txt con C ++ 11:

cmake_minimum_required(VERSION 3.3) project(Hello CXX) set(SOURCE_FILES main.cpp) add_executable(Hello ${SOURCE_FILES}) set_property(TARGET Hello PROPERTY CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON )

Esto agregará todos los indicadores necesarios como -std=c++11 . Tenga en cuenta que la propiedad CXX_STANDARD_REQUIRED evitará que el estándar se descomponga en una versión anterior.

* No he probado esto en CMake 3.1, pero he verificado que funciona en CMake 3.3. La documentación para 3.1 documenta esto, así que debería funcionar.

¿Hay alguna manera de dejar que cmake detecte automáticamente si un compilador admite C ++ 11 o no?

Como sería bueno informar a los usuarios durante la ejecución de cmake que el código no se compilará ya que el compilador no es compatible con C ++ 11. Por el momento establezco las banderas de C ++ 11; sin embargo, si un compilador no lo admite, el usuario obtiene errores de compilación en lugar de un error durante la ejecución de cmake.

Perfecto sería algo que funcione como find_package() pero no he encontrado ningún módulo de función que proporcione la funcionalidad necesaria.

Adicional, sería bueno tener la función para detectar si el compilador necesita las banderas std=c++0x o std=c++11 .

¿Hay algo disponible o tuve que desarrollar esto por mi cuenta?

Aquí, algún código que uso hasta ahora, sin embargo, solo funciona con compiladores GNU gcc. Sería bueno si hubiera una solución más general.

if(CMAKE_COMPILER_IS_GNUCXX) execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) if (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7) message(STATUS "C++11 activated.") add_definitions("-std=gnu++11") elseif(GCC_VERSION VERSION_GREATER 4.3 OR GCC_VERSION VERSION_EQUAL 4.3) message(WARNING "C++0x activated. If you get any errors update to a compiler which fully supports C++11") add_definitions("-std=gnu++0x") else () message(FATAL_ERROR "C++11 needed. Therefore a gcc compiler with a version higher than 4.3 is needed.") endif() else(CMAKE_COMPILER_IS_GNUCXX) add_definitions("-std=c++0x") endif(CMAKE_COMPILER_IS_GNUCXX)


En el momento de escribir este documento (antes de GCC 4.8) , puede que no sea una buena idea detectar indicadores de C ++ 11 y agregarlos. Esto se debe a que al cambiar el estándar (al menos para GCC) se rompe la compatibilidad ABI , lo que puede provocar errores de enlace.

Por lo tanto, el uso del estándar C ++ 11 debe especificarse explícitamente con la configuración del compilador durante la configuración inicial de CMake del proyecto , por ej.

CXX=''g++ -std=c++11'' cmake /path/to/source

Es decir, el uso de -std = c ++ 11 se debe tratar como un compilador separado, que no se debe mezclar o cambiar en un proyecto.


En este punto, CMake no tiene una forma conveniente para admitir C ++ 11. Idealmente, debería especificar un proyecto de C ++ 11 como este:

project(foo CXX11)

al comienzo de su CMakeLists.txt . Pero el tipo de proyecto CXX11 no existe (todavía). Hasta entonces, puedes usar una técnica de dos etapas:

  1. Determine el tipo y la versión del compilador
  2. Ajuste los indicadores de compilación en consecuencia.

Por ejemplo, esto es lo que uso para soportar C ++ 11 con Clang y GCC:

# Initialize CXXFLAGS. set(CMAKE_CXX_FLAGS "-Wall -std=c++11") set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG") set(CMAKE_CXX_FLAGS_RELEASE "-O4 -DNDEBUG") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g") # Compiler-specific C++11 activation. if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") execute_process( COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) if (NOT (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)) message(FATAL_ERROR "${PROJECT_NAME} requires g++ 4.7 or greater.") endif () elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") else () message(FATAL_ERROR "Your C++ compiler does not support C++11.") endif ()


Encontré este script CMake que dice hacer exactamente lo que necesita. También puede verificar características individuales de C ++ 11. No creo que pueda decidir entre std=C++0x y std=C++11 .


Hemos escrito un módulo CMake para detectar y habilitar el soporte de C ++ 11 que puede encontrar aquí:
https://github.com/NitroShare/CXX11-CMake-Macros

Todavía es un trabajo en progreso, pero lo estamos utilizando para una serie de proyectos Qt que se dirigen a Windows / Linux / Mac. Actualmente solo son compatibles MSVC ++, GCC y Clang.

Ejemplo:

include(CXX11) check_for_cxx11_compiler(CXX11_COMPILER) # If a C++11 compiler is available, then set the appropriate flags if(CXX11_COMPILER) enable_cxx11() endif()


Si tiene CMake versión 3.1.0 o posterior, puede detectar qué características C ++ admite su compilador C ++

cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) project(foobar CXX) message("Your C++ compiler supports these C++ features:") foreach(i ${CMAKE_CXX_COMPILE_FEATURES}) message("${i}") endforeach()

Pero normalmente no es necesario utilizar la variable CMake CMAKE_CXX_COMPILE_FEATURES en sus secuencias de comandos de CMake. En su lugar, hay dos maneras de decirle a CMake bajo qué estándar de C ++ deben compilarse sus archivos C ++, ya sea especificando explícitamente el estándar C ++ o especificando las características C ++ requeridas y dejando que CMake induzca el estándar C ++. CMake se asegurará de que el compilador de C ++ se invoque con los indicadores de línea de comando correctos (por ejemplo, -std = c ++ 11).

1. Especificar el estándar de C ++ explícitamente

Puede especificar el estándar C ++ explícitamente, configurando las propiedades CMake CXX_STANDARD y CXX_STANDARD_REQUIRED para su destino CMake.

$ cat /tmp/src/CMakeLists.txt project(foobar CXX) cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) add_executable(prog main.cc) set_property(TARGET prog PROPERTY CXX_STANDARD 11) set_property(TARGET prog PROPERTY CXX_STANDARD_REQUIRED ON) $ cat /tmp/src/main.cc int main() { return 0; } $ mkdir /tmp/build $ cd /tmp/build $ cmake /tmp/src -- The CXX compiler identification is GNU 4.8.2 -- Check for working CXX compiler: /usr/bin/c++ -- Check for working CXX compiler: /usr/bin/c++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done -- Generating done -- Build files have been written to: /tmp/build $ make VERBOSE=1 | grep main.cc | grep -- "-c" /usr/bin/c++ -std=gnu++11 -o CMakeFiles/prog.dir/main.cc.o -c /tmp/src/main.cc $

2. Especificar las características requeridas de C ++ y dejar que CMake induzca el estándar de C ++

Puede usar el comando CMake target_compile_features para especificar las características C ++ que se utilizan en su destino CMake. De esta lista, CMake inducirá el uso del estándar C ++. La propiedad global de CMake CMAKE_CXX_KNOWN_FEATURES enumera las características de C ++ que puede elegir.

cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) message("Your CMake version supports these C++ features:") get_property(known_features GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES) foreach(i ${known_features}) message("${i}") endforeach()

Por ejemplo, este programa C ++ con el nombre de archivo main.cc hace uso de las características de C ++ 11: cxx_strong_enums , cxx_constexpr , cxx_auto_type

#include <cstdlib> int main(int argc, char *argv[]) { enum class Color { Red, Orange, Yellow, Green, Blue, Violet }; constexpr float a = 3.1415f; auto b = a; return EXIT_SUCCESS; }

Este archivo CMakeLists.txt lo construiría

cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) project(foobar CXX) add_executable(foobar main.cc) set(needed_features cxx_strong_enums cxx_constexpr cxx_auto_type) target_compile_features(foobar PRIVATE ${needed_features})


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(FATAL_ERROR "Compiler ${CMAKE_CXX_COMPILER} has no C++11 support.") endif()

de http://www.guyrutenberg.com/2014/01/05/enabling-c11-c0x-in-cmake/ con cambios menores