Come impostare il livello di avviso in CMake?


116

Come impostare il livello di avviso per un progetto (non l'intera soluzione) utilizzando CMake ? Dovrebbe funzionare su Visual Studio e GCC .

Ho trovato varie opzioni ma la maggior parte sembra non funzionare o non è coerente con la documentazione.

Risposte:


96

AGGIORNAMENTO: Questa risposta precede l'era Modern CMake. Ogni utente sano di CMake dovrebbe astenersi dal giocherellare CMAKE_CXX_FLAGSdirettamente e chiamare target_compile_optionsinvece il comando. Controlla la risposta di mrts che presenta le migliori pratiche consigliate.

Puoi fare qualcosa di simile a questo:

if(MSVC)
  # Force to always compile with W4
  if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
    string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
  else()
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
  endif()
elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
  # Update if necessary
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic")
endif()

Si noti che le nuove versioni di Visual Studio (almeno 2013) supportano il /Wallflag (denominato EnableAllWarnings). Produce ancora più avvisi di /W4. Tuttavia, dalla mia esperienza, produce troppi avvertimenti.
Adam Badura

12
/Wallè utilizzabile se si desidera seguire una strategia "sottrattiva" per gli avvisi, proprio come quella di clang -Weverything. Invece di selezionare gli avvisi da abilitare, abiliti tutto e quindi seleziona avvisi specifici da disabilitare.
bames53

86

Nella moderna CMake, quanto segue funziona bene:

if(MSVC)
  target_compile_options(${TARGET_NAME} PRIVATE /W4 /WX)
else()
  target_compile_options(${TARGET_NAME} PRIVATE -Wall -Wextra -pedantic -Werror)
endif()

Il mio collega ha suggerito una versione alternativa:

target_compile_options(${TARGET_NAME} PRIVATE
  $<$<CXX_COMPILER_ID:MSVC>:/W4 /WX>
  $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra -pedantic -Werror>
)

Sostituisci ${TARGET_NAME}con il nome effettivo del target. -Werrorè opzionale, trasforma tutti gli avvisi in errori.

Oppure usa add_compile_options(...)se vuoi applicarlo a tutti i target come suggerito da @aldo nei commenti.

Inoltre, assicurati di comprendere la differenza tra PRIVATEe PUBLIC(le opzioni pubbliche saranno ereditate dai target che dipendono dal target specificato).


19
O semplicemente add_compile_options(...)se vuoi applicarlo a tutti i target.
aldo

1
Cordiali saluti, CMake moderno non richiede di ripetere la condizione in else()o endif().
Timmmm

1
@Timmmm Grazie per l'avvertenza! È solo una nota o preferisci che rimuova le condizioni?
mrts

1
@helmesjo No, Timmmm si riferiva al codice CMake così come esisteva prima della modifica del 9 aprile. Puoi dare un'occhiata alla cronologia delle modifiche per vedere i bit che sono stati rimossi, che sono le stesse cose che Timmmm stava evidenziando.
FeRD

2
@aldo il problema add_compile_options()è che gli avvisi si propagheranno ai target aggiunti tramite add_subdirectory(). Se includi librerie esterne in questo modo potresti ricevere molti avvisi se quella libreria è stata progettata con un livello di avviso diverso.
trozen

24

Alcuni moduli CMake che ho scritto includono la soppressione sperimentale degli avvisi su piattaforme incrociate :

sugar_generate_warning_flags(
    target_compile_options
    target_properties
    ENABLE conversion
    TREAT_AS_ERRORS ALL
)

set_target_properties(
    foo
    PROPERTIES
    ${target_properties}
    COMPILE_OPTIONS
    "${target_compile_options}"
)

Risultato per Xcode:

  • Imposta l' CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSIONattributo Xcode (ovvero impostazioni di build -> avvisi -> conversioni implicite sospette -> )
  • Aggiungi flag del compilatore: -Werror

Makefile gcc e clang:

  • Aggiungere flag di compilazione: -Wconversion,-Werror

Studio visivo:

  • Aggiungere flag di compilazione: /WX,/w14244

link


1
è un peccato che cmake non fornisca questa funzionalità
Slava

3
Buone notizie. Mi dispiace postarlo qui e non nella mailing list di cmake, ma senza livello sarà inutile, ci sono troppi avvisi per elencarli tutti esplicitamente. Se vuoi unificarlo, un modo per farlo è due separati cmake_level: un set unificato di avvisi, basato ad esempio su clang, e native_level con il significato specifico per un compilatore. Uno di questi può essere probabilmente ridotto a livello. Scusa se non ho davvero seguito la conversazione e ho sbagliato qualcosa
Slava

1
@ void.pointer solleva un punto valido. La tua risposta proposta è: " Ho intenzione di aggiungere questa funzione" . Non dice che hai fatto qualche ricerca superficiale e ora speri che qualcun altro faccia il lavoro pesante per te. Se non vuoi essere attribuito all'implementazione (e alle domande sul suo progresso), devi modificare la tua risposta e dissociarti dal compito su cui non hai fatto progressi da oltre un anno.
Rilevabile

"Più di un anno dopo, ancora nessun progresso." - Questo è un punto valido. Più di un anno sono passati, con lo zero progresso. Questa è un'indicazione molto forte di un progetto abbandonato. Se vuoi dimostrare che abbiamo torto, mostraci alcuni progressi. Ciò non è accaduto, ma la tua risposta proposta suggerisce ancora che la funzionalità sta per essere aggiunta a CMake. Perché fare tante storie su una funzionalità che non sarà disponibile tra anni? Non è affatto utile. O mostra dei progressi o modifica la tua risposta per essere meno fuorviante.
Rilevabile il

5
Non sembri capire. Se suggerisci di implementare una funzione, devi implementarla a tempo debito. In caso contrario, ti viene chiesto di rimuovere quella promessa dalla risposta proposta. Hai mostrato un impegno pari a zero nell'implementazione di tale funzionalità, quindi non pretendere diversamente. Capisco che sia grande. Capisco anche che potresti non essere in grado di farcela. Ti sto semplicemente chiedendo di fare in modo che la tua risposta lo rifletta.
Rilevabile il

6

Ecco la migliore soluzione che ho trovato finora (incluso un controllo del compilatore):

if(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)")
    add_definitions(/W2)
endif()

Questo imposterà il livello di avviso 2 in Visual Studio. Suppongo che con un -W2funzionerebbe anche in GCC (non testato).

Aggiornamento da @Williams: dovrebbe essere -Wallper GCC.


6
Il flag di avviso per GCC sarebbe -Walle forse -Wextracome dettagliato su gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
Milliams

1
L'elenco che uso è -W -Wall -Wextra -pedantic. -WextraIIRC è stato sostituito -Win una versione successiva di GCC, ma li lascio entrambi per motivi di compatibilità.
Jimmio92

2
Questo non è lo scopo previsto di add_definitions ( "ha lo scopo di aggiungere definizioni del preprocessore" ). Non è nemmeno solo una raccomandazione sulle migliori pratiche. Gli argomenti passati a questo comando verranno visualizzati negli script di compilazione generati invocando strumenti che non li aspettano (ad esempio il compilatore di risorse).
Rilevabile

Non è un "controllo del compilatore", è un controllo dello strumento di compilazione.
Thomas,

3

Come da documentazione Cmake 3.17.1 :

if (MSVC)
    # warning level 4 and all warnings as errors
    add_compile_options(/W4 /WX)
else()
    # lots of warnings and all warnings as errors
    add_compile_options(-Wall -Wextra -pedantic -Werror)
endif()

GCC e Clang condividono questi flag, quindi questo dovrebbe coprire tutti e 3.


Non usare questo. Utilizza invece target_compile_options (). Fare riferimento all'ultimo documento sembra essere "corretto", ma è un'antica voce semplicemente per compatibilità con le versioni precedenti.
caoanan

1
@caoanan La documentazione non menziona nulla di compatibilità con le versioni precedenti per questo. add_compile_optionsè a livello di directory, mentre target_compile_optionsè solo per un singolo obiettivo.
TehWan

2
if(MSVC)
    string(REGEX REPLACE "/W[1-3]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
endif()

Se usi target_compile_options- cmake proverà a usare il doppio /W*flag, che darà un avvertimento dal compilatore.


Grazie per questo. Stavo usando ingenuamente l' add_compile_optionsunico per ottenere tonnellate di avvertimenti che /W3vengono ignorati /W4. Il fatto che CMake non stia affrontando questa opzione rudimentale (impostazione del livello di avviso) è incredibile.
Resurrezione il
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.