จะตั้งระดับการเตือนใน CMake ได้อย่างไร?


116

วิธีการตั้งค่าระดับการเตือนสำหรับโครงการ (ไม่ใช่วิธีการแก้ปัญหาทั้งหมด) โดยใช้CMake ? ควรจะทำงานในVisual StudioและGCC

ฉันพบตัวเลือกต่างๆ แต่ส่วนใหญ่ดูเหมือนจะไม่ได้ผลหรือไม่สอดคล้องกับเอกสาร

คำตอบ:


96

UPDATE: คำตอบนี้มีมาก่อนในยุค Modern CMake ผู้ใช้ CMake ที่มีสติทุกคนควรละเว้นจากการเล่นซอCMAKE_CXX_FLAGSโดยตรงและเรียกใช้target_compile_optionsคำสั่งแทน ตรวจสอบคำตอบของ mrtsซึ่งนำเสนอแนวทางปฏิบัติที่ดีที่สุดที่แนะนำ

คุณสามารถทำสิ่งที่คล้ายกับสิ่งนี้:

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 (อย่างน้อย 2013) สนับสนุน/Wallแฟล็ก (ซึ่งมีชื่อEnableAllWarnings) /W4มันก่อให้เกิดคำเตือนมากยิ่งขึ้นกว่า อย่างไรก็ตามจากประสบการณ์ของฉันมันสร้างคำเตือนมากเกินไป
Adam Badura

12
/Wallสามารถใช้งานได้หากคุณต้องการที่จะปฏิบัติตามกลยุทธ์ 'ลด' -Weverythingคำเตือนเช่นเดียวกับของเสียงดังกราว แทนที่จะเลือกคำเตือนเพื่อเปิดใช้งานให้คุณเปิดใช้งานทุกอย่างแล้วเลือกคำเตือนเฉพาะเพื่อปิดใช้งาน
bames53

86

ใน CMake สมัยใหม่สิ่งต่อไปนี้ใช้ได้ดี:

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

เพื่อนร่วมงานของฉันแนะนำรุ่นอื่น:

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

แทนที่${TARGET_NAME}ด้วยชื่อเป้าหมายจริง-Werrorเป็นทางเลือกซึ่งจะเปลี่ยนคำเตือนทั้งหมดให้เป็นข้อผิดพลาด

หรือใช้ add_compile_options(...)หากคุณต้องการใช้กับเป้าหมายทั้งหมดตามที่ @aldo แนะนำในความคิดเห็น

นอกจากนี้อย่าลืมเข้าใจความแตกต่างระหว่างPRIVATEและPUBLIC(ตัวเลือกสาธารณะจะถูกสืบทอดโดยเป้าหมายที่ขึ้นอยู่กับเป้าหมายที่กำหนด)


19
หรือadd_compile_options(...)หากคุณต้องการใช้กับเป้าหมายทั้งหมด
aldo

1
FYI modern CMake ไม่ต้องการการทำซ้ำเงื่อนไขในelse()หรือendif().
Timmmm

1
@Timmmm ขอบคุณสำหรับหัว! เป็นเพียงบันทึกหรือคุณต้องการให้ฉันลบเงื่อนไข?
mrts

1
@helmesjo ไม่ Timmmm อ้างถึงรหัส CMake ตามที่มีอยู่ก่อนการแก้ไขวันที่ 9 เมษายน คุณสามารถดูประวัติการแก้ไขเพื่อดูบิตที่ถูกลบออกซึ่งเป็นสิ่งเดียวกับที่ Timmmm ชี้ให้เห็น
FeRD

2
@aldo ปัญหาด้วยคือว่าคำเตือนจะเผยแพร่สู่เป้าหมายเพิ่มผ่านadd_compile_options() add_subdirectory()หากคุณรวมไลบรารีภายนอกด้วยวิธีนี้คุณอาจได้รับคำเตือนมากมายหากไลบรารีนั้นได้รับการออกแบบให้มีระดับการเตือนที่แตกต่าง
trozen

24

โมดูล CMakeบางตัวที่ฉันเขียนรวมถึงการป้องกันการเตือนข้ามแพลตจากการทดลอง:

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:

  • ตั้งค่าCLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSIONแอตทริบิวต์ Xcode (aka build settings -> คำเตือน -> การแปลงโดยนัยที่น่าสงสัย -> ใช่ )
  • เพิ่มแฟล็กคอมไพเลอร์: -Werror

Makefile gcc และ clang:

  • เพิ่มแฟล็กคอมไพเลอร์: -Wconversion,-Werror

สตูดิโอภาพ:

  • เพิ่มแฟล็กคอมไพเลอร์: /WX,/w14244

การเชื่อมโยง


1
เป็นเรื่องน่าเสียดายที่ cmake ไม่มีฟังก์ชันนี้
Slava

3
ข่าวดี. ขออภัยที่โพสต์ไว้ที่นี่และไม่ได้อยู่ในรายชื่ออีเมล cmake แต่หากไม่มีระดับนี้จะไม่มีประโยชน์มีคำเตือนมากเกินไปที่จะแสดงรายการทั้งหมดอย่างชัดเจน หากคุณต้องการรวมเข้าด้วยกันวิธีเดียวที่จะทำคือ cmake_level สองชุดที่แยกจากกัน - ชุดคำเตือนที่เป็นหนึ่งเดียวโดยยึดตามเสียงดังและ native_level ที่มีความหมายเฉพาะสำหรับคอมไพเลอร์ หนึ่งในนั้นสามารถลดระดับลงได้ ขออภัยหากฉันไม่ได้ติดตามการสนทนาและมีบางอย่างผิดปกติ
Slava

1
@ void.pointer เพิ่มจุดที่ถูกต้อง คำตอบที่คุณเสนออ่าน: " ผมวางแผนที่จะเพิ่มคุณลักษณะนี้" ไม่ได้บอกว่าคุณได้ทำการวิจัยคร่าวๆและตอนนี้หวังว่าจะให้คนอื่นช่วยยกของหนักให้คุณ หากคุณไม่ต้องการนำมาประกอบกับการนำไปใช้งาน (และคำถามเกี่ยวกับความคืบหน้า) คุณต้องแก้ไขคำตอบของคุณและแยกตัวเองออกจากงานที่คุณยังไม่มีความคืบหน้าใด ๆ ในช่วงเวลาหนึ่งปี
IInspectable

"ปีต่อมาก็ยังไม่มีอะไรคืบหน้า" - ตอนนี้เป็นจุดที่ถูกต้อง เวลาผ่านไปกว่าหนึ่งปีโดยไม่มีความคืบหน้า นั่นเป็นข้อบ่งชี้ที่ชัดเจนมากถึงโครงการที่ถูกทิ้งร้าง หากคุณต้องการพิสูจน์ว่าเราผิดโปรดแสดงความคืบหน้าให้เราทราบ ยังไม่เกิดขึ้น แต่คำตอบที่คุณเสนอยังคงแนะนำว่าคุณลักษณะนี้กำลังจะถูกเพิ่มลงใน CMake ทำไมต้องวุ่นวายกับฟีเจอร์ที่ไม่สามารถใช้งานได้ในหลายปี? นั่นไม่เป็นประโยชน์เลย แสดงความคืบหน้าบางอย่างหรือแก้ไขคำตอบของคุณเพื่อให้เข้าใจผิดน้อยลง
IInspectable

5
ดูเหมือนคุณจะไม่เข้าใจ หากคุณแนะนำว่าคุณกำลังจะติดตั้งคุณลักษณะคุณจะต้องใช้คุณลักษณะนั้นในเวลาที่กำหนด หากทำไม่สำเร็จระบบจะขอให้คุณลบคำสัญญานั้นออกจากคำตอบที่คุณเสนอ คุณได้แสดงความมุ่งมั่นที่จะใช้คุณลักษณะดังกล่าวเป็นศูนย์ดังนั้นอย่าอ้างสิทธิ์เป็นอย่างอื่น ผมเข้าใจว่ามันใหญ่ ฉันเข้าใจด้วยว่าคุณอาจไม่สามารถดึงสิ่งนี้ออกไปได้ ฉันแค่ขอให้คุณตอบสนองความต้องการของคุณ
IInspectable

6

นี่คือทางออกที่ดีที่สุดที่ฉันพบ (รวมถึงการตรวจสอบคอมไพเลอร์):

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

สิ่งนี้จะตั้งค่าคำเตือนระดับ 2 ใน Visual Studio ฉันคิดว่า-W2มันจะใช้ได้ใน GCC ด้วย (ยังไม่ทดลอง)

อัปเดตจาก @ วิลเลียมส์: ควรเป็น-Wallสำหรับ GCC


6
ธงคำเตือนสำหรับ GCC จะเป็น-Wallและอาจมี-Wextraรายละเอียดได้ที่gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
Milliams

1
รายการที่ฉันใช้คือ-W -Wall -Wextra -pedantic. -WextraIIRC ถูกแทนที่-Wใน GCC เวอร์ชันที่ใหม่กว่า แต่ฉันปล่อยให้ทั้งสองอย่างเข้ากันได้
Jimmio92

2
นั่นไม่ใช่จุดประสงค์ของadd_definitions ( "มีไว้เพื่อเพิ่มคำจำกัดความของตัวประมวลผลล่วงหน้า" ) ไม่ใช่แค่คำแนะนำแนวทางปฏิบัติที่ดีที่สุดเท่านั้น อาร์กิวเมนต์ที่ส่งไปยังคำสั่งนี้จะปรากฏขึ้นในบิลด์สคริปต์ที่สร้างขึ้นโดยเรียกใช้เครื่องมือที่ไม่คาดหวัง (เช่นคอมไพเลอร์รีซอร์ส)
IInspectable

นั่นไม่ใช่ "การตรวจสอบคอมไพเลอร์" แต่เป็นการตรวจสอบเครื่องมือสร้าง
โธมัส

3

ตามเอกสาร 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 และ Clang แชร์ค่าสถานะเหล่านี้ดังนั้นสิ่งนี้ควรครอบคลุมทั้ง 3 อย่าง


อย่าใช้สิ่งนี้ ให้ใช้ target_compile_options () แทน การอ้างถึงเอกสารล่าสุดดูเหมือนจะ "ถูกต้อง" แต่เป็นรายการโบราณที่ใช้สำหรับความเข้ากันได้แบบย้อนหลังเท่านั้น
caoanan

1
@caoanan เอกสารระบุว่าไม่มีอะไรที่เข้ากันได้ย้อนหลังสำหรับสิ่งนี้ add_compile_optionsเป็นไดเร็กทอรีกว้างในขณะที่ใช้target_compile_optionsสำหรับเป้าหมายเดียว
TehWan

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

หากคุณใช้target_compile_options- cmake จะพยายามใช้/W*แฟล็กคู่ซึ่งจะเตือนโดยคอมไพเลอร์


ขอบคุณสำหรับสิ่งนี้. ผมได้อย่างไร้เดียงสาใช้add_compile_optionsเท่านั้นที่จะได้รับตันของคำเตือนที่จะถูกแทนที่ด้วย/W3 /W4ความจริงที่ว่า CMake ไม่ได้กล่าวถึงตัวเลือกพื้นฐานนี้ (การตั้งค่าระดับการเตือน) อยู่นอกเหนือความเชื่อ
คืนชีพ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.