Ignora i flag di compilazione per i singoli file


109

Vorrei utilizzare un set globale di flag per la compilazione di un progetto, il che significa che nel mio file CMakeLists.txt di primo livello ho specificato:

ADD_DEFINITIONS ( -Wall -Weffc++ -pedantic -std=c++0x )

Tuttavia, per un file specifico (diciamo "foo.cpp") in una sottodirectory, voglio cambiare i flag di compilazione per non applicare -Weffc ++ (libreria commerciale inclusa che non posso cambiare). Per semplificare la situazione da utilizzare solo -Wall, ho provato:

 SET_SOURCE_FILES_PROPERTIES( foo.cpp PROPERTIES COMPILE_FLAGS -Wall )
 ADD_EXECUTABLE( foo foo.cpp )

, che non ha funzionato. Ho anche provato

SET_PROPERTY( SOURCE foo.cpp PROPERTY COMPILE_FLAGS -Wall )
ADD_EXECUTABLE( foo foo.cpp )

e

ADD_EXECUTABLE( foo foo.cpp )
SET_TARGET_PROPERTIES( foo PROPERTIES COMPILE_FLAGS -Wall )

, in cui nessuno dei due ha funzionato.

Infine, ho provato a rimuovere questa definizione:

REMOVE_DEFINITIONS( -Weffc++ )
ADD_EXECUTABLE( foo foo.cpp )
ADD_DEFINITIONS( -Weffc++ )

, che inoltre non ha funzionato (il che significa che ricevo molti avvisi di stile sulla libreria commerciale). (** Nota: gli avvisi SONO soppressi se NON includo nuovamente la direttiva -Weffc ++ dopo che l'eseguibile è stato creato.)

Ho anche provato a rimuovere temporaneamente i flag di compilazione: http://www.cmake.org/pipermail/cmake/2007-June/014614.html , ma ciò non ha aiutato.

Non c'è una soluzione elegante a questo?


1
Aspetta, se il tuo ultimo tentativo funziona, ma solo dopo che è stato creato, potrebbe non essere un problema di memorizzazione nella cache? Prova a eliminare CMakeCache dopo aver apportato le modifiche.
Cameron

Correlato, vedi Come modificare un flag del compilatore per un solo eseguibile in CMake? La risposta di Andre mostra quello che sembra essere un modo per sostituire le opzioni esistenti con nuove opzioni.
jww

Risposte:


126

I tuoi tentativi precedenti stanno aggiungendo ulteriori flag al tuo file / destinazione invece di sovrascriverli come ti aspetti. Ad esempio, dalla documentazione relativa alle proprietà sui file di origine - COMPILE_FLAGS :

Questi flag verranno aggiunti all'elenco dei flag di compilazione quando questo file sorgente viene compilato.

Dovresti essere in grado di -Weffc++annullare il flag per foo.cpp facendo

set_source_files_properties(foo.cpp PROPERTIES COMPILE_FLAGS -Wno-effc++)

Questo dovrebbe avere l'effetto di aggiungere -Wno-effc++dopo -Weffc++nel comando del compilatore e quest'ultima impostazione ha la meglio. Per vedere il comando completo e verificare che sia effettivamente così, puoi farlo

make VERBOSE=1

Per inciso, uno dei manutentori della GNU C ++ Standard Library presenta un'opinione piuttosto negativa -Weffc++in questa risposta .

Un altro punto è che stai abusando add_definitionsnel senso che stai usando questo per i flag del compilatore piuttosto che per le definizioni del preprocessore previste.

Sarebbe preferibile utilizzare add_compile_options

add_compile_options(-Wall -Weffc++ -pedantic -std=c++0x)

o per le versioni di CMake <3.0 per fare qualcosa di più come:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Weffc++ -pedantic -std=c++0x")

In risposta ad ulteriori domande nei commenti seguenti, credo che sia impossibile rimuovere in modo affidabile un flag su un singolo file. Il motivo è che per ogni dato file sorgente, ha il COMPILE_OPTIONSe 1COMPILE_FLAGS applicato della sua destinazione, ma questi non vengono visualizzati in nessuna delle proprietà per quel file di origine.

Potresti provare a rimuovere il flag del problema da quello del target COMPILE_OPTIONS, quindi applicarlo a ciascuna delle sorgenti del target individualmente, omettendolo dal file sorgente specifico come richiesto.

Tuttavia, sebbene ciò possa funzionare in molti scenari, presenta un paio di problemi.

Primo: le proprietà dei file di origine non includono COMPILE_OPTIONS, solo COMPILE_FLAGS. Questo è un problema perché il COMPILE_OPTIONSdi un target può includere espressioni del generatore , ma COMPILE_FLAGSnon le supporta. Quindi dovresti adattare le espressioni del generatore durante la ricerca della tua bandiera, e in effetti potresti anche dover "analizzare" le espressioni del generatore se la tua bandiera fosse contenuta in una o più per vedere se dovrebbe essere riapplicata alle rimanenti file sorgenti.

Secondo: a partire da CMake v3.0, le destinazioni possono specificare INTERFACE_COMPILE_OPTIONS. Ciò significa che una dipendenza del tuo target può aggiungere o sovrascrivere quella del tuo target COMPILE_OPTIONStramite i suoi INTERFACE_COMPILE_OPTIONS. Quindi dovresti ulteriormente iterare ricorsivamente attraverso tutte le dipendenze del tuo obiettivo (non è un compito particolarmente facile poiché l'elenco di LINK_LIBRARIESper il target può contenere anche espressioni del generatore) per trovare quelle che stanno applicando il flag del problema e provare a rimuoverlo da quelli anche gli obiettivi INTERFACE_COMPILE_OPTIONS.

In questa fase di complessità, cercherò di inviare una patch a CMake per fornire la funzionalità per rimuovere incondizionatamente un flag specifico da un file di origine.


1: si noti che a differenza della COMPILE_FLAGSproprietà sui file di origine, la COMPILE_FLAGSproprietà sulle destinazioni è deprecata.


6
Ma come si impostano effettivamente i flag di compilazione per i file separatamente senza aggiungerli. Ad esempio, voglio utilizzare flag di compilazione diversi per la destinazione risultante rispetto ai file ma poiché sono aggiunti dovrei rimuoverli manualmente. Non esiste una proprietà che non le appenda ma le imposti solo per il file / destinazione specificato?
Baradé

2
Cosa possiamo fare quando -fno-flag non è disponibile (e -fflag è impostato)?
gnzlbg

@ Baradé Non puoi - non per un file sorgente.
Fraser

@gnzlbg Ancora una volta, siamo praticamente bloccati. Ho aggiornato la mia risposta per fornire un po 'più di informazioni (e una possibile soluzione alternativa che probabilmente funzionerebbe in alcuni scenari).
Fraser

Non esiste davvero alcuna soluzione alternativa all'impostazione delle opzioni di compilazione di un singolo file? Devo disabilitare la generazione della copertura gcc per alcuni file che stanno bloccando gcov.
Lothar

5

Sto solo aggiungendo alla risposta corretta di @ Fraser.

Nel caso volessi aggiungere il flag speciale a cartelle specifiche potresti fare:

file(GLOB SPECIAL_SRC_FILES
        "path/one/src/*.cpp"
        "path/two/src/*.cpp")
set_property(SOURCE ${SPECIAL_SRC_FILES} PROPERTY COMPILE_FLAGS -Wno-effc++)

o

file(GLOB SPECIAL_SRC_FILES
        "path/one/src/*.cpp"
        "path/two/src/*.cpp")
set_source_files_properties(${SPECIAL_SRC_FILES} PROPERTIES COMPILE_FLAGS -Wno-effc++)

Si noti che non è consigliabile utilizzare GLOB come discusso qui


0

Utilizzando la risposta di @Fraser, ho creato quanto segue per gestire gli include Qt perché la variabile include più percorsi separati da punto e virgola. Ciò significa che ho dovuto prima aggiungere un foreach()ciclo e creare manualmente i flag di inclusione . Ma questo mi permette di avere un'eccezione: foo.cpp (quel file usa Qt per ora, ma a lungo termine voglio rimuovere quella dipendenza e voglio assicurarmi che Qt non si insinui altrove).

find_package(Qt5Core REQUIRED)
set(QT_INCLUDE_PROPERTIES "")
foreach(DIR ${Qt5Core_INCLUDE_DIRS})
    set(QT_INCLUDE_PROPERTIES "${QT_INCLUDE_PROPERTIES} -isystem ${DIR}")
endforeach()
set_source_files_properties(foo.cpp PROPERTIES
    COMPILE_FLAGS
        ${QT_INCLUDE_PROPERTIES}
)

Si noti anche che uso il -isysteminvece di -Iper evitare alcuni avvisi che altrimenti genererebbero le intestazioni Qt (ho un sacco di avvisi attivati).

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.