CMake'de uyarı seviyesi nasıl ayarlanır?


116

CMake kullanarak bir proje için (tüm çözüm değil) uyarı seviyesi nasıl ayarlanır ? Visual Studio ve GCC üzerinde çalışmalıdır .

Çeşitli seçenekler buldum ama çoğu ya çalışmıyor ya da belgelerle tutarlı değil gibi görünüyor.

Yanıtlar:


96

GÜNCELLEME: Bu cevap Modern CMake döneminden öncedir. Her mantıklı CMake kullanıcısı, CMAKE_CXX_FLAGSdoğrudan uğraşmaktan kaçınmalı ve target_compile_optionsbunun yerine komutu çağırmalıdır . Önerilen en iyi uygulamayı sunan mrts cevabını kontrol edin .

Buna benzer bir şey yapabilirsiniz:

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

Visual Studio'nun yeni sürümlerinin (en az 2013) /Wallbayrağı (adlı EnableAllWarnings) desteklediğine dikkat edin. Bundan daha fazla uyarı üretir /W4. Ancak deneyimlerime göre çok fazla uyarı üretiyor.
Adam Badura

12
/Walltıpkı clang'lar gibi uyarılar için 'çıkarıcı' bir strateji izlemek istiyorsanız kullanılabilir -Weverything. Etkinleştirmek için uyarıları seçmek yerine, her şeyi etkinleştirir ve ardından devre dışı bırakmak için belirli uyarıları seçersiniz.
bames53

86

Modern CMake'de aşağıdakiler iyi çalışıyor:

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

Meslektaşım alternatif bir versiyon önerdi:

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

${TARGET_NAME}Gerçek hedef adıyla değiştirin . -Werroristeğe bağlıdır, tüm uyarıları hataya dönüştürür.

Ya add_compile_options(...)da yorumlarda @aldo tarafından önerildiği gibi tüm hedeflere uygulamak istiyorsanız kullanın.

Ayrıca, PRIVATEve arasındaki farkı anladığınızdan emin olun PUBLIC(genel seçenekler, verilen hedefe bağlı olan hedefler tarafından miras alınacaktır).


19
Ya da sadece add_compile_options(...)tüm hedeflere uygulamak istiyorsanız.
aldo

1
Bilginize, modern CMake koşulunun else()veya içinde tekrarlanmasını gerektirmez endif().
Timmmm

1
@Timmmm Uyarılar için teşekkürler! Bu sadece bir not mu yoksa koşulları kaldırmamı mı tercih edersiniz?
mrts

1
@helmesjo Hayır, Timmmm CMake koduna 9 Nisan'daki düzenlemeden önceki haliyle atıfta bulunuyordu. Çıkarılan bitleri görmek için düzenleme geçmişine göz atabilirsiniz, bunlar Timmmm'in işaret ettiği şeylerin aynısıdır.
FeRD

2
@aldo ile ilgili sorun add_compile_options(), uyarıların, üzerinden eklenen hedeflere yayılmasıdır add_subdirectory(). Harici kitaplıkları bu şekilde eklerseniz, bu kitaplık farklı uyarı düzeyiyle tasarlanmışsa birçok uyarı alabilirsiniz.
2019

24

Yazdığım bazı CMake modülleri deneysel cross-platfrom uyarı bastırma içerir :

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

Xcode için sonuç:

  • CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSIONXcode özniteliğini ayarlayın (aka yapı ayarları -> uyarılar -> şüpheli örtük dönüştürmeler -> EVET )
  • Derleyici bayrağı ekleyin: -Werror

Makefile gcc ve clang:

  • Derleyici bayrakları ekleyin: -Wconversion,-Werror

Görsel stüdyo:

  • Derleyici bayrakları ekleyin: /WX,/w14244

Bağlantılar


1
utanç verici cmake bu işlevi sağlamıyor
Slava

3
İyi haberler. Cmake posta listesinde değil, burada yayınladığım için özür dilerim, ancak seviye olmadan bu işe yaramaz. Hepsini açık bir şekilde listelemek için çok fazla uyarı var. Bunu yapmanın bir yolunu birleştirmek istiyorsanız, iki ayrı cmake_level - örneğin clang'a dayalı birleşik uyarılar kümesi ve bir derleyiciye özgü anlama sahip native_level. Bunlardan biri muhtemelen seviyeye kısaltılabilir. Sohbeti gerçekten takip etmediysem ve bir
Slava

1
@ void.pointer geçerli bir noktayı yükseltir. Sizin önerilen yanıt okur: " Ben değilim bu özelliği eklemeyi planlıyoruz" . Bazı üstünkörü araştırma yaptığınızı ve şimdi başka birinin sizin için ağır işi yapmasını umduğunuzu söylemez. Uygulamayla ilişkilendirilmek istemiyorsanız (ve ilerlemesiyle ilgili sorular), cevabınızı düzenlemeniz ve bir yıldan uzun süredir ilerleme kaydetmediğiniz görevle olan ilişkinizi kesmeniz gerekir.
2017

"Bir yıldan fazla bir süre sonra, hala ilerleme yok." - Şimdi bu olduğunu geçerli bir nokta. Sıfır ilerleme ile bir yıldan fazla bir süre geçti . Bu, terk edilmiş bir projenin çok güçlü bir göstergesidir. Bizi yanlış kanıtlamak istiyorsan, bize biraz ilerleme göster. Bu olmadı, ancak önerdiğiniz yanıt hala özelliğin CMake'ye eklenmek üzere olduğunu gösteriyor. Yıllardır kullanılamayacak bir özellik hakkında neden bu kadar yaygara yapasınız? Bu hiç yardımcı olmuyor. Ya biraz ilerleme gösterin ya da yanıtınızı daha az yanıltıcı olacak şekilde düzenleyin.
2017

5
Anlıyor gibi görünmüyorsun. Bir özelliği uygulayacağınızı önerirseniz, bu özelliği zamanında uygulamanız gerekir. Aksi takdirde, önerdiğiniz cevaptan bu sözü çıkarmanız istenir. Söz konusu özelliği uygulamak için sıfır taahhüt gösterdiniz, bu nedenle aksini iddia etmeyin. Bunun büyük olduğunu anlıyorum. Ayrıca bunu başaramayacağınızı da anlıyorum. Sizden sadece cevabınızın bunu yansıtmasını istiyorum.
IInspectable

6

Şimdiye kadar bulduğum en iyi çözüm (derleyici kontrolü dahil):

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

Bu, Visual Studio'da uyarı düzeyi 2'yi ayarlayacaktır. Sanırım bir ile -W2GCC'de de işe yarayacak (test edilmemiş).

@ Williams'dan güncelleme: -WallGCC için olmalıdır .


6
GCC için uyarı bayrağı , gcc.gnu.org/onlinedocs/gcc/Warning-Options.html-Wall-Wextra
Milliams

1
Kullandığım liste -W -Wall -Wextra -pedantic. -WextraIIRC -W, GCC'nin sonraki bir sürümünde değiştirildi , ancak her ikisini de uyumluluk uğruna bırakıyorum.
Jimmio92

2
Add_definitions'ın amaçlanan amacı bu değildir ( "önişlemci tanımları eklemeye yöneliktir" ). Bu sadece bir en iyi uygulama önerisi de değildir. Bu komuta aktarılan bağımsız değişkenler, onları beklemeyen araçları (örneğin kaynak derleyicisi) çağıran oluşturulan derleme betiklerinde görünecektir.
IInspectable

Bu bir "derleyici denetimi" değil, bir derleme aracı denetimi.
Thomas

3

Gereğince CKağıt 3.17.1 belgeleri :

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 ve Clang bu bayrakları paylaşır, bu nedenle bu, 3'ünü de kapsamalıdır.


Bunu kullanma. Bunun yerine target_compile_options () kullanın. En son belgeye atıfta bulunmak "doğru" gibi görünüyor, ancak bu yalnızca geriye dönük uyumluluk için eski bir giriştir.
caoanan

1
@caoanan Dokümantasyon bunun için geriye dönük uyumluluktan bahsetmiyor. add_compile_optionsdizin çapındadır, oysa target_compile_optionsyalnızca tek bir hedef içindir.
TehWan

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

Eğer target_compile_options- cmake kullanırsanız, çift /W*bayrak kullanmaya çalışacaktır , bu da derleyici tarafından uyarı verecektir.


Bunun için teşekkürler. Ben safça add_compile_optionssadece /W3, geçersiz kılınan tonlarca uyarı almak için kullanıyordum /W4. CMake'nin bu temel seçeneği ele almadığı gerçeği (uyarı seviyesini belirleme) inanılamaz.
Diriliş
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.