¿Cómo agrego un enlazador o una marca de compilación en un archivo CMake?

220

Estoy usando el arm-linux-androideabi-g++compilador. Cuando trato de compilar un simple "¡Hola, mundo!" programa se compila bien. Cuando lo pruebo agregando un manejo de excepciones simple en ese código, también funciona (después de agregar -fexceptions... Supongo que está deshabilitado por defecto).

Esto es para un dispositivo Android, y solo quiero usar CMake, no ndk-build.

Por ejemplo - first.cpp

#include <iostream>

using namespace std;

int main()
{
   try
   {
   }
   catch (...)
   {
   }
   return 0;
}

./arm-linux-androideadi-g++ -o first-test first.cpp -fexceptions

Funciona sin problema ...

El problema ... Estoy tratando de compilar el archivo con un archivo CMake.

Quiero agregar el -fexceptionscomo una bandera. Lo intenté con

set (CMAKE_EXE_LINKER_FLAGS -fexceptions ) or set (CMAKE_EXE_LINKER_FLAGS "fexceptions" )

y

set ( CMAKE_C_FLAGS "fexceptions")

Todavía muestra un error.

solti
fuente
ahora mismo estoy teniendo el mismo problema y estoy intentando cosas diferentes. Cuelga un poco y publico una respuesta. Para compilar banderas, hay una manera sucia pero fácil: add_definitions ("- truc")
Offirmo
Para una discusión más actualizada sobre esta pregunta (especialmente si está utilizando CMake 3.xo más reciente): ¿Cuál es el método moderno para establecer marcas generales de compilación en CMake? .
ComicSansMS
Si los indicadores de enlace que desea tienen como objetivo configurar rpath , eche un vistazo a los comandos específicos de CMake rpath gitlab.kitware.com/cmake/community/wikis/doc/cmake/…
Gabriel Devillers

Respuestas:

243

Supongamos que desea agregar esas banderas (mejor declararlas en una constante):

SET(GCC_COVERAGE_COMPILE_FLAGS "-fprofile-arcs -ftest-coverage")
SET(GCC_COVERAGE_LINK_FLAGS    "-lgcov")

Hay varias formas de agregarlos:

  1. El más fácil (no limpio, pero fácil y conveniente, y funciona solo para compilar banderas, C & C ++ a la vez):

    add_definitions(${GCC_COVERAGE_COMPILE_FLAGS})
  2. Anexar a las variables CMake correspondientes:

    SET(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}")
    SET(CMAKE_EXE_LINKER_FLAGS  "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}")
  3. Usando las propiedades de destino, cf. doc CMake compila la propiedad de destino del indicador y necesita saber el nombre del objetivo.

    get_target_property(TEMP ${THE_TARGET} COMPILE_FLAGS)
    if(TEMP STREQUAL "TEMP-NOTFOUND")
      SET(TEMP "") # Set to empty string
    else()
      SET(TEMP "${TEMP} ") # A space to cleanly separate from existing content
    endif()
    # Append our values
    SET(TEMP "${TEMP}${GCC_COVERAGE_COMPILE_FLAGS}" )
    set_target_properties(${THE_TARGET} PROPERTIES COMPILE_FLAGS ${TEMP} )

En este momento uso el método 2.

Offirmo
fuente
44
¿Por qué es add_definitions () impuro?
leinaD_natipaC
14
@leinaD_natipaC: La documentación oficial dice: Este comando se puede usar para agregar cualquier indicador, pero está destinado a agregar definiciones de preprocesador . Creo que es por eso.
Benoit Blanchon
Si bien esta es la respuesta aceptada, esto realmente muestra CMAKE de estilo muy antiguo, consulte la respuesta de @vitaut para saber cómo se debe estructurar cualquier código CMAKE nuevo con respecto a los parámetros de tiempo de compilación
Harald Scheirich
1
string(APPEND CMAKE_EXE_LINKER_FLAGS "new_value")es más corto y más limpio queset(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} new_value")
sangriento
165

En las versiones más recientes de CMake, puede establecer marcas de compilador y vinculador para un solo objetivo con target_compile_optionsy target_link_librariesrespectivamente (sí, este último también establece opciones de vinculador):

target_compile_options(first-test PRIVATE -fexceptions)

La ventaja de este método es que puede controlar la propagación de opciones a otros objetivos que dependen de este mediante PUBLICyPRIVATE .

A partir de CMake 3.13, también puede usarlo target_link_optionspara agregar opciones de enlazador, lo que aclara la intención.

vitaut
fuente
2
He intentado usarlo: target_compile_options(main_static PRIVATE --static)pero no parece funcionar, ¿alguna idea de por qué?
Paweł Szczur
2
-statices probablemente una opción de vinculador, no compilador. Intenta pasárselo a target_link_libraries.
Vitaut
99
Ah, target_link_librariesme perdí esa parte del documento: "Especificar bibliotecas o banderas para usar al vincular un objetivo determinado". Gracias.
Paweł Szczur
3
Una adición reciente: CMake 3.13 presenta target_link_optionscomo una forma más limpia de especificar banderas de enlace. Debe evitar el uso target_link_librariesde indicadores de vinculador en el futuro y utilizarlo target_link_optionsen su lugar.
ComicSansMS
1
También hay add_compile_options : consulte stackoverflow.com/questions/39501481/… y, más recientemente, add_link_options
Bruce Adams, el
46

Intente configurar la variable en CMAKE_CXX_FLAGSlugar de CMAKE_C_FLAGS:

set (CMAKE_CXX_FLAGS "-fexceptions")

La variable CMAKE_C_FLAGSsolo afecta al compilador de C, pero está compilando código de C ++.

Agregar la bandera a CMAKE_EXE_LINKER_FLAGSes redundante.

sakra
fuente
Lo intenté pero todavía da error. Se establece (CMAKE_CXX_FLAGS "-fexceptions") la única forma de especificar el indicador del compilador.
solti
3
resolví el problema, pero no en el buen sentido, es una solución alternativa pobre. Hice -DCMAKE_CXX_FLAGS = "-fexceptions" en la línea de comando. por alguna razón, cmake no está leyendo indicadores del archivo .cmake. :( .. gracias sakra por tu respuesta ..
solti
8
-DCMAKE_CXX_FLAGS = "-fexceptions" NO debe haber un espacio entre = y "
evandrix
Con respecto a lo que dijo: "por alguna razón, cmake no está leyendo indicadores del archivo .cmake". Asegúrese de limpiar el caché existente. Esto se puede hacer eliminando todo del directorio de compilación antes de volver a hacer cmake.
zaizen
1

También puede agregar indicadores de vinculador a un objetivo específico utilizando la LINK_FLAGSpropiedad:

set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " ${flag}")

Si desea propagar este cambio a otros objetivos, puede crear un objetivo ficticio para vincularlo.

kaveish
fuente