Come posso aggiungere un linker o compilare un flag in un file CMake?


220

Sto usando il arm-linux-androideabi-g++compilatore. Quando provo a compilare un semplice "Ciao, mondo!" programma si compila bene. Quando lo collaudo aggiungendo una semplice gestione delle eccezioni in quel codice funziona anche (dopo aver aggiunto -fexceptions.. Immagino che sia disabilitato di default).

Questo è per un dispositivo Android e non voglio usare solo CMake ndk-build.

Per esempio - first.cpp

#include <iostream>

using namespace std;

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

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

Funziona senza problemi ...

Il problema ... Sto provando a compilare il file con un file CMake.

Voglio aggiungere il -fexceptionscome una bandiera. Ci ho provato

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

e

set ( CMAKE_C_FLAGS "fexceptions")

Visualizza ancora un errore.


in questo momento sto avendo lo stesso problema e sto provando cose diverse. Appendi un po 'e io posto una risposta. Per i flag di compilazione, esiste un modo impuro ma semplice: add_definitions ("- truc")
Offirmo

Per una discussione più aggiornata su questa domanda (specialmente se si utilizza CMake 3.xo versioni successive): qual è il metodo moderno per impostare flag di compilazione generali in CMake? .
ComicSansMS

Se i flag di collegamento che desideri mirano a configurare rpath, dai un'occhiata ai comandi specifici di CMake rpath gitlab.kitware.com/cmake/community/wikis/doc/cmake/…
Gabriel Devillers,

Risposte:


243

Supponiamo di voler aggiungere quei flag (meglio dichiararli in una costante):

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

Esistono diversi modi per aggiungerli:

  1. Il più semplice (non pulito, ma facile e conveniente, e funziona solo per i flag di compilazione, C e C ++ contemporaneamente):

    add_definitions(${GCC_COVERAGE_COMPILE_FLAGS})
  2. Aggiunta alle variabili CMake corrispondenti:

    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. Utilizzando le proprietà target, cfr. doc CMake compila la proprietà target flag e deve conoscere il nome target.

    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} )

In questo momento uso il metodo 2.


4
perché add_definitions () è sporco?
leinaD_natipaC

14
@leinaD_natipaC: La documentazione ufficiale dice: Questo comando può essere usato per aggiungere qualsiasi flag, ma è inteso per aggiungere definizioni del preprocessore . Penso che sia per questo.
Benoit Blanchon,

Mentre questa è la risposta accettata che mostra davvero CMAKE molto vecchio stile, fai riferimento alla risposta di @vitaut per come dovrebbe essere strutturato un nuovo codice CMAKE in relazione ai parametri del tempo di compilazione
Harald Scheirich

1
string(APPEND CMAKE_EXE_LINKER_FLAGS "new_value")è più corto e più pulito delset(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} new_value")
sanguinante

165

Nelle versioni più recenti di CMake è possibile impostare flag di compilatore e linker per un singolo target con target_compile_optionse target_link_librariesrispettivamente (sì, quest'ultimo imposta anche le opzioni di linker):

target_compile_options(first-test PRIVATE -fexceptions)

Il vantaggio di questo metodo è che puoi controllare la propagazione delle opzioni verso altri target che dipendono da questo tramite PUBLICe PRIVATE.

A partire da CMake 3.13 puoi anche usare target_link_optionsper aggiungere opzioni di linker che rendono più chiaro l'intento.


2
Ho provato ad usarlo: target_compile_options(main_static PRIVATE --static)ma non sembra funzionare, hai idea del perché?
Paweł Szczur,

2
-staticè probabilmente un linker, non un'opzione di compilazione. Prova a passarlo a target_link_libraries.
vitaut,

9
Oh, target_link_librariesho perso quella parte del documento: "Specifica le librerie o i flag da usare quando colleghi un determinato target.". Grazie.
Paweł Szczur,

3
Un'aggiunta recente: CMake 3.13 introduce target_link_optionscome un modo più pulito di specificare flag di linker. Dovresti evitare di utilizzare target_link_librariesper flag linker in futuro e utilizzare target_link_optionsinvece.
ComicSansMS,


46

Prova a impostare la variabile CMAKE_CXX_FLAGSanziché CMAKE_C_FLAGS:

set (CMAKE_CXX_FLAGS "-fexceptions")

La variabile ha CMAKE_C_FLAGSeffetto solo sul compilatore C, ma stai compilando il codice C ++.

L'aggiunta del flag a CMAKE_EXE_LINKER_FLAGSè ridondante.


l'ho provato ma mi dà ancora errore. È impostato (CMAKE_CXX_FLAGS "-fexceptions") l'unico modo per specificare il flag del compilatore.
solti

3
ho risolto il problema, ma non in senso positivo è una soluzione alternativa scadente. Ho fatto -DCMAKE_CXX_FLAGS = "-fexceptions" nella riga di comando. per qualche ragione cmake non legge i flag dal file .cmake. :( .. grazie sakra per la tua risposta ..
solti

8
-DCMAKE_CXX_FLAGS = "-fexceptions" NON dovrebbe esserci uno spazio tra il = e "
evandrix il

Per quanto riguarda quello che hai detto: "per qualche ragione cmake non legge i flag dal file .cmake." Assicurati di cancellare la cache esistente. Questo può essere fatto cancellando tutto dalla directory build prima di ricominciare da capo.
zaizen,

1

Puoi anche aggiungere flag di linker a una destinazione specifica usando la LINK_FLAGSproprietà:

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

Se si desidera propagare questa modifica ad altri target, è possibile creare un target fittizio al quale collegarsi.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.