Wie stelle ich die Warnstufe in CMake ein?

116

Wie kann ich mit CMake die Warnstufe für ein Projekt (nicht die gesamte Lösung) festlegen ? Sollte unter Visual Studio und GCC funktionieren .

Ich habe verschiedene Optionen gefunden, aber die meisten scheinen entweder nicht zu funktionieren oder stimmen nicht mit der Dokumentation überein.

Wernight
quelle

Antworten:

96

UPDATE: Diese Antwort stammt aus der Zeit vor dem Modern CMake. Jeder vernünftige CMake-Benutzer sollte nicht CMAKE_CXX_FLAGSdirekt herumspielen und target_compile_optionsstattdessen den Befehl aufrufen . Überprüfen Sie die Antwort des mrts, die die empfohlenen Best Practices enthält.

Sie können etwas Ähnliches tun:

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()
Mloskot
quelle
Beachten Sie, dass neue Versionen von Visual Studio (mindestens 2013) das /WallFlag (mit dem Namen EnableAllWarnings) unterstützen. Es werden noch mehr Warnungen ausgegeben als /W4. Nach meiner Erfahrung werden jedoch viel zu viele Warnungen ausgegeben.
Adam Badura
12
/Wallist verwendbar, wenn Sie eine "subtraktive" Strategie für Warnungen verfolgen möchten, genau wie bei Clangs -Weverything. Anstatt die zu aktivierenden Warnungen auszuwählen, aktivieren Sie alles und wählen dann bestimmte zu deaktivierende Warnungen aus.
Bames53
86

Im modernen CMake funktioniert Folgendes gut:

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

Mein Kollege schlug eine alternative Version vor:

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

Durch ${TARGET_NAME}den tatsächlichen Zielnamen ersetzen . -Werrorist optional, verwandelt alle Warnungen in Fehler.

Oder verwenden add_compile_options(...)Sie, wenn Sie es auf alle Ziele anwenden möchten, wie von @aldo in den Kommentaren vorgeschlagen.

Stellen Sie außerdem sicher, dass Sie den Unterschied zwischen PRIVATEund verstehen PUBLIC(öffentliche Optionen werden von Zielen geerbt, die vom angegebenen Ziel abhängen).

mrts
quelle
19
Oder einfach, add_compile_options(...)wenn Sie es auf alle Ziele anwenden möchten.
Aldo
1
Zu Ihrer Information, modernes CMake erfordert nicht das Wiederholen des Zustands in else()oder endif().
Timmmm
1
@Timmmm Danke für das Heads Up! Ist es nur eine Notiz oder möchten Sie, dass ich die Bedingungen entferne?
Herr
1
@helmesjo Nein, Timmmm bezog sich auf den CMake-Code, wie er vor der Bearbeitung am 9. April existierte. Sie können sich den Bearbeitungsverlauf ansehen, um zu sehen, welche Bits entfernt wurden. Dies sind die gleichen Dinge, auf die Timmmm hingewiesen hat.
FeRD
2
@aldo das Problem mit add_compile_options()ist, dass die Warnungen an Ziele weitergegeben werden, die über hinzugefügt wurden add_subdirectory(). Wenn Sie auf diese Weise externe Bibliotheken einschließen, erhalten Sie möglicherweise viele Warnungen, wenn diese Bibliothek mit einer anderen Warnstufe entworfen wurde.
trozen
24

Einige CMake-Module, die ich geschrieben habe, enthalten experimentelle plattformübergreifende Warnunterdrückung :

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

Ergebnis für Xcode:

  • Legen Sie das CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSIONXcode-Attribut fest (auch bekannt als Build-Einstellungen -> Warnungen -> verdächtige implizite Konvertierungen -> JA )
  • Compiler-Flag hinzufügen: -Werror

Makefile gcc und clang:

  • In Compiler - Flags: -Wconversion,-Werror

Visual Studio:

  • In Compiler - Flags: /WX,/w14244

Links

xaxxon
quelle
1
Es ist eine Schande, dass cmake diese Funktionalität nicht bietet
Slava
3
Gute Nachrichten. Es tut mir leid, es hier und nicht in der cmake-Mailingliste zu posten, aber ohne Level ist dies nutzlos. Es gibt einfach zu viele Warnungen, um sie alle explizit aufzulisten. Wenn Sie es auf eine Weise vereinheitlichen möchten, sind dies zwei separate cmake_level - einheitliche Warnungen, die beispielsweise auf clang basieren, und native_level mit der für einen Compiler spezifischen Bedeutung. Einer von ihnen kann wahrscheinlich auf Level gekürzt werden. Tut mir leid, wenn ich dem Gespräch nicht wirklich gefolgt bin und etwas falsch gemacht habe
Slava
1
@ void.pointer löst einen gültigen Punkt aus. Ihre vorgeschlagene Antwort lautet: " Ich plane, diese Funktion hinzuzufügen" . Es heißt nicht, dass Sie einige flüchtige Nachforschungen angestellt haben und jetzt hoffen, dass jemand anderes das schwere Heben für Sie erledigt. Wenn Sie nicht mit der Implementierung (und Fragen zum Fortschritt) in Verbindung gebracht werden möchten, müssen Sie Ihre Antwort bearbeiten und sich von der Aufgabe trennen, bei der Sie seit mehr als einem Jahr keine Fortschritte erzielt haben.
Unsichtbarer
"Über ein Jahr später noch keine Fortschritte." - Das ist ein gültiger Punkt. Mehr als ein Jahr vergangen ist , mit Null Fortschritt. Das ist ein sehr starker Hinweis auf ein aufgegebenes Projekt. Wenn Sie uns das Gegenteil beweisen wollen, zeigen Sie uns einige Fortschritte. Das ist nicht geschehen, aber Ihre vorgeschlagene Antwort deutet immer noch darauf hin, dass die Funktion gerade erst zu CMake hinzugefügt wird. Warum so viel Aufhebens um eine Funktion machen, die in den nächsten Jahren nicht mehr verfügbar sein wird? Das ist überhaupt nicht hilfreich. Zeigen Sie entweder Fortschritte an oder bearbeiten Sie Ihre Antwort so, dass sie weniger irreführend ist.
Unsichtbarer
5
Sie scheinen nicht zu verstehen. Wenn Sie vorschlagen, dass Sie eine Funktion implementieren, müssen Sie diese Funktion rechtzeitig implementieren. Andernfalls werden Sie gebeten, dieses Versprechen aus Ihrer vorgeschlagenen Antwort zu entfernen. Sie haben keine Verpflichtung zur Implementierung dieser Funktion gezeigt, behaupten Sie also nichts anderes. Ich verstehe, dass es groß ist. Ich verstehe auch, dass Sie möglicherweise nicht in der Lage sind, dies durchzuziehen. Ich bitte Sie lediglich, Ihre Antwort dies widerzuspiegeln.
Unsichtbarer
6

Hier ist die beste Lösung, die ich bisher gefunden habe (einschließlich einer Compilerprüfung):

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

Dadurch wird die Warnstufe 2 in Visual Studio festgelegt. Ich nehme an mit einem-W2 würde es auch in GCC funktionieren (ungetestet).

Update von @Williams: Es sollte -Wallfür GCC sein.

Wernight
quelle
6
Das Warnflag für GCC wäre -Wallund vielleicht -Wextraso detailliert unter gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
Milliams
1
Die Liste, die ich benutze, ist -W -Wall -Wextra -pedantic. -WextraIIRC wurde -Win einer späteren Version von GCC ersetzt, aber ich lasse beide aus Kompatibilitätsgründen.
Jimmio92
2
Dies ist nicht der beabsichtigte Zweck von add_definitions ( "es ist beabsichtigt, Präprozessordefinitionen hinzuzufügen" ). Es ist auch nicht nur eine Best-Practice-Empfehlung. An diesen Befehl übergebene Argumente werden in den generierten Build-Skripten angezeigt, die Tools aufrufen, die sie nicht erwarten (z. B. den Ressourcen-Compiler).
Unsichtbarer
Dies ist keine "Compiler-Prüfung", sondern eine Prüfung des Build-Tools.
Thomas
3

Wie pro Cmake 3.17.1 Dokumentation :

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 und Clang teilen sich diese Flags, daher sollte dies alle 3 abdecken.

Jay
quelle
Benutze das nicht. Verwenden Sie stattdessen target_compile_options (). Der Verweis auf das neueste Dokument scheint "korrekt" zu sein, aber es ist ein alter Eintrag, nur um die Abwärtskompatibilität zu gewährleisten.
Caoanan
1
@caoanan In der Dokumentation wird nichts von Abwärtskompatibilität erwähnt. add_compile_optionsist verzeichnisweit, während target_compile_optionses sich nur um ein einzelnes Ziel handelt.
Der
2
if(MSVC)
    string(REGEX REPLACE "/W[1-3]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
endif()

Wenn Sie target_compile_options- cmake verwenden, wird versucht, das Doppelflag zu /W*verwenden, das vom Compiler gewarnt wird.

TarmoPikaro
quelle
Danke dafür. Ich habe naiv die add_compile_optionseinzige verwendet, um Tonnen von Warnungen zu erhalten, /W3mit denen überschrieben wird /W4. Die Tatsache, dass CMake diese rudimentäre Option (Einstellen der Warnstufe) nicht anspricht, ist unglaublich.
Auferstehung