Quiero escribir un archivo cmake que establezca diferentes opciones de comstackción para clang ++, g ++ y MSVC en comstackciones de depuración y liberación. Lo que estoy haciendo actualmente se ve así:
if(MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++latest /W4") # Default debug flags are OK set(CMAKE_CXX_FLAGS_RELEASE "{CMAKE_CXX_FLAGS_RELEASE} /O2") else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1z -Wall -Wextra -Werror") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} some other flags") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3") if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") else() # nothing special for gcc at the moment endif() endif()
Pero tengo un par de problemas con esto:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} Foo")
con append(CMAKE_CXX_FLAGS "Foo")
? CMAKE_CXX_FLAGS
y variables similares en primer lugar, pero no estoy seguro de qué otro mecanismo usar. make foo_debug_clang
. Entonces mis preguntas son
La mayoría de las referencias que pude encontrar en Internet están desactualizadas o muestran solo ejemplos triviales. Actualmente uso cmake3.8, pero si eso marca alguna diferencia, estoy aún más interesado en la respuesta para las versiones más recientes.
Su enfoque sería, como @Tsyvarev ha comentado, absolutamente correcto, ya que ha pedido el “nuevo” enfoque en CMake, aquí es a lo que se traduciría su código:
cmake_minimum_required(VERSION 3.8) project(HelloWorld) string( APPEND _opts "$," "/W4;$<$:/O2>," "-Wall;-Wextra;-Werror;" "$<$ :-O3>" "$<$:-stdlib=libc++>" ">" ) add_compile_options("${_opts}") add_executable(HelloWorld "main.cpp") target_compile_features(HelloWorld PUBLIC cxx_lambda_init_captures)
Toma add_compile_options()
y – como @ Al.G. ha comentado – “use las expresiones del generador sucio”.
Hay algunas desventajas de las expresiones del generador:
$
solo está disponible en CMake versión> = 3.8 string(APPEND ...)
, que también puede usar para “optimizar” su set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ...
llamadas. Así que es mejor utilizar un enfoque más legible y compatible con versiones anteriores con add_compile_options()
:
if(MSVC) add_compile_options("/W4" "$<$:/O2>") else() add_compile_options("-Wall" "-Wextra" "-Werror" "$<$ :-O3>") if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") add_compile_options("-stdlib=libc++") else() # nothing special for gcc at the moment endif() endif()
Y sí, ya no especifica explícitamente el estándar C ++, simplemente llama a la función C ++ que su código / destino depende de las llamadas target_compile_features()
.
Para este ejemplo, he elegido cxx_lambda_init_captures
que, por ejemplo, para un comstackdor GCC anterior, da el siguiente error (como un ejemplo de lo que sucede si un comstackdor no admite esta característica):
The compiler feature "cxx_lambda_init_captures" is not known to CXX compiler "GNU" version 4.8.4.
Y necesita escribir un script de contenedor para crear múltiples configuraciones con un generador de archivos make “de configuración única” o usar un IDE de “configuración múltiple” como Visual Studio.
Aquí están las referencias a ejemplos:
Así que probé lo siguiente con el soporte de Open Folder
Visual Studio 2017 CMake para combinar en este ejemplo los comstackdores cl , clang y mingw :
CMakeSettings.json
{ // See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file. "configurations": [ { "name": "x86-Debug", "generator": "Visual Studio 15 2017", "configurationType": "Debug", "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}", "buildCommandArgs": "-m -v:minimal", }, { "name": "x86-Release", "generator": "Visual Studio 15 2017", "configurationType": "Release", "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}", "buildCommandArgs": "-m -v:minimal", }, { "name": "Clang-Debug", "generator": "Visual Studio 15 2017", "configurationType": "Debug", "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}", "cmakeCommandArgs": "-T\"LLVM-vs2014\"", "buildCommandArgs": "-m -v:minimal", }, { "name": "Clang-Release", "generator": "Visual Studio 15 2017", "configurationType": "Release", "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}", "cmakeCommandArgs": "-T\"LLVM-vs2014\"", "buildCommandArgs": "-m -v:minimal", }, { "name": "GNU-Debug", "generator": "MinGW Makefiles", "configurationType": "Debug", "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}", "variables": [ { "name": "CMAKE_MAKE_PROGRAM", "value": "${projectDir}\\mingw32-make.cmd" } ] }, { "name": "GNU-Release", "generator": "Unix Makefiles", "configurationType": "Release", "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}", "variables": [ { "name": "CMAKE_MAKE_PROGRAM", "value": "${projectDir}\\mingw32-make.cmd" } ] } ] }
mingw32-make.cmd
@echo off mingw32-make.exe %~1 %~2 %~3 %~4
De modo que puede usar cualquier generador de CMake desde Visual Studio 2017, hay algunas citas insalubres en curso (en septiembre de 2017, tal vez corregidas más adelante) que requieren el intermediario mingw32-make.cmd
(eliminando las comillas).
Otra forma es usar archivos .rsp.
set(rsp_file "${CMAKE_CURRENT_BINARY_DIR}/my.rsp") configure_file(my.rsp.in ${rsp_file} @ONLY) target_compile_options(mytarget PUBLIC "@${rsp_file}")
lo que podría facilitar la administración de la inclusión de opciones múltiples y esotéricas.
Puede usar target_compile_options () para “agregar” opciones de comstackción.
Abordar los dos primeros puntos, pero no el tercero:
- He leído varias veces, que uno no debe establecer manualmente CMAKE_CXX_FLAGS y variables similares en primer lugar, pero no estoy seguro de qué otro mecanismo usar.
El comando que desea es set_property
. CMake admite un conjunto de propiedades, no todo, pero muchas, de forma que le ahorra la molestia de realizar un trabajo específico del comstackdor. Por ejemplo:
set_property(TARGET foo PROPERTY CXX_STANDARD 17)
que para algunos comstackdores dará como resultado --std=c++17
pero para los anteriores con --std=c++1z
(antes de que finalizara C ++ 17). o:
set_property(TARGET foo APPEND PROPERTY COMPILE_DEFINITIONS HELLO WORLD)
resultará en -DHELLO
-DWORLD
para gcc, clang y MSVC, pero para los comstackdores extraños podrían usar otros switches.
¿Realmente no hay un comando como append que me permita reemplazar el
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} Foo")
conappend(CMAKE_CXX_FLAGS "Foo")?
set_property
se puede usar en el modo de configuración o en el modo de adición (ver ejemplos anteriores).
target_compile_features
embargo, no puedo decir si esto es preferible a add_compile_options
o target_compile_features
.