Làm cách nào để đặt mức cảnh báo trong CMake?


116

Làm cách nào để đặt mức cảnh báo cho một dự án (không phải toàn bộ giải pháp) bằng CMake ? Nên làm việc trên Visual StudioGCC .

Tôi tìm thấy các tùy chọn khác nhau nhưng hầu hết dường như không hoạt động hoặc không phù hợp với tài liệu.

Câu trả lời:


96

CẬP NHẬT: Câu trả lời này có trước kỷ nguyên CMake hiện đại. Mỗi người dùng CMake lành mạnh nên kiềm chế CMAKE_CXX_FLAGStrực tiếp và target_compile_optionsthay vào đó gọi lệnh. Kiểm tra câu trả lời của mrts trong đó trình bày thực tiễn tốt nhất được đề nghị.

Bạn có thể làm một cái gì đó tương tự như thế này:

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

Lưu ý rằng các phiên bản mới của Visual Studio (ít nhất là 2013) /Wallcờ hỗ trợ (được đặt tên EnableAllWarnings). Nó tạo ra nhiều cảnh báo hơn /W4. Tuy nhiên từ kinh nghiệm của tôi, nó tạo ra quá nhiều cảnh báo.
Adam Badura

12
/Wallcó thể sử dụng được nếu bạn muốn theo chiến lược 'trừ' để cảnh báo, giống như tiếng kêu -Weverything. Thay vì chọn cảnh báo để bật, bạn kích hoạt mọi thứ và sau đó chọn cảnh báo cụ thể để tắt.
bames53

86

Trong CMake hiện đại, các công việc sau đây hoạt động tốt:

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

Đồng nghiệp của tôi đề xuất một phiên bản thay thế:

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

Thay thế ${TARGET_NAME}bằng tên mục tiêu thực tế. -Werrorlà tùy chọn, nó biến tất cả các cảnh báo thành lỗi.

Hoặc sử dụng add_compile_options(...)nếu bạn muốn áp dụng nó cho tất cả các mục tiêu theo đề xuất của @aldo trong các bình luận.

Ngoài ra, hãy chắc chắn hiểu sự khác biệt giữa PRIVATEPUBLIC(các tùy chọn công khai sẽ được kế thừa bởi các mục tiêu phụ thuộc vào mục tiêu đã cho).


19
Hoặc đơn giản add_compile_options(...)nếu bạn muốn áp dụng nó cho tất cả các mục tiêu.
aldo

1
CMake hiện đại của FYI không yêu cầu lặp lại điều kiện trong else()hoặc endif().
Timmmm

1
@Timmmm Cảm ơn những người đứng đầu! Nó chỉ là một ghi chú hoặc bạn muốn tôi loại bỏ các điều kiện?
mrts

1
@helmesjo Không, Timmmm đã đề cập đến mã CMake vì nó đã tồn tại trước khi chỉnh sửa ngày 9 tháng 4. Bạn có thể xem lịch sử chỉnh sửa để xem các bit đã bị xóa, đó là những điều tương tự Timmmm đã chỉ ra.
FeRD

2
@aldo vấn đề với add_compile_options()là các cảnh báo sẽ lan truyền đến các mục tiêu được thêm thông qua add_subdirectory(). Nếu bạn bao gồm các thư viện bên ngoài theo cách này, bạn có thể nhận được rất nhiều cảnh báo nếu thư viện đó được thiết kế với các mức cảnh báo khác nhau.
trozen

24

Một số mô-đun CMake tôi đã viết bao gồm thử nghiệm cảnh báo chéo- thử nghiệm chéo :

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

Kết quả cho Xcode:

  • Đặt CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSIONthuộc tính Xcode (còn gọi là cài đặt bản dựng -> cảnh báo -> chuyển đổi ẩn đáng ngờ -> )
  • Thêm cờ biên dịch: -Werror

Makefile gcc và clang:

  • Thêm cờ biên dịch : -Wconversion,-Werror

Visual Studio:

  • Thêm cờ biên dịch : /WX,/w14244

Liên kết


1
đó là một cmake xấu hổ không cung cấp chức năng này
Slava

3
Tin tốt. Xin lỗi để đăng nó ở đây và không có trong danh sách gửi thư cmake, nhưng không có cấp độ này sẽ vô ích, chỉ có quá nhiều cảnh báo để liệt kê tất cả chúng một cách rõ ràng. Nếu bạn muốn hợp nhất nó, một cách để thực hiện đó là hai cmake_level riêng biệt - tập hợp các cảnh báo, dựa trên clang và local_level với ý nghĩa cụ thể cho trình biên dịch. Một trong số họ có thể được rút ngắn để cấp. Xin lỗi nếu tôi không thực sự theo dõi cuộc trò chuyện và có gì đó không ổn
Slava

1
@ void.pulum tăng điểm hợp lệ. Câu trả lời được đề xuất của bạn là: " Tôi đang dự định thêm tính năng này" . Điều đó không nói lên rằng bạn đã thực hiện một số nghiên cứu về chữ thảo và bây giờ hy vọng người khác sẽ thực hiện công việc nặng nhọc cho bạn. Nếu bạn không muốn được quy cho việc triển khai (và câu hỏi về tiến trình của nó), bạn cần chỉnh sửa câu trả lời của mình và tách bản thân khỏi nhiệm vụ mà bạn chưa đạt được tiến bộ nào trong hơn một năm.
IInspectable

"Hơn một năm sau, vẫn không có tiến triển." - Bây giờ đó một điểm hợp lệ. Hơn một năm đã trôi qua, với tiến độ bằng không . Đó là một dấu hiệu rất mạnh mẽ của một dự án bị bỏ rơi. Nếu bạn muốn chứng minh chúng tôi sai, hãy cho chúng tôi thấy một số tiến bộ. Điều đó đã không xảy ra, nhưng câu trả lời được đề xuất của bạn vẫn cho thấy, tính năng này sắp được thêm vào CMake. Tại sao làm cho tất cả những ồn ào về một tính năng sẽ không có sẵn trong nhiều năm? Điều đó không hữu ích chút nào. Hoặc hiển thị một số tiến bộ, hoặc chỉnh sửa câu trả lời của bạn để ít gây hiểu lầm hơn.
IInspectable

5
Bạn không có vẻ hiểu. Nếu bạn đề xuất rằng bạn sẽ triển khai một tính năng, thì bạn cần triển khai tính năng đó trong thời gian tới hạn. Không, bạn được yêu cầu xóa lời hứa đó khỏi câu trả lời được đề xuất. Bạn đã thể hiện không cam kết thực hiện tính năng nói trên, vì vậy đừng yêu cầu khác. Tôi hiểu rằng nó là lớn. Tôi cũng hiểu rằng bạn có thể không có khả năng thực hiện điều này. Tôi chỉ đơn giản là yêu cầu bạn làm cho câu trả lời của bạn phản ánh điều đó.
IInspectable

6

Đây là giải pháp tốt nhất tôi tìm thấy cho đến nay (bao gồm kiểm tra trình biên dịch):

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

Điều này sẽ đặt cảnh báo cấp 2 trong Visual Studio. Tôi cho rằng với -W2nó cũng sẽ hoạt động trong GCC (chưa được kiểm tra).

Cập nhật từ @Williams: Nó nên -Walldành cho GCC.


6
Cờ cảnh báo cho GCC sẽ -Wallvà có thể -Wextranhư chi tiết tại gcc.gnu.org/onlinesocs/gcc/Warning-Options.html
Milliams

1
Danh sách tôi sử dụng là -W -Wall -Wextra -pedantic. -WextraIIRC thay thế -Wtrong phiên bản GCC sau này, nhưng tôi để cả hai vì lợi ích tương thích.
Jimmio92

2
Đó không phải là mục đích dự định của add_def định nghĩa ( "dự định thêm định nghĩa tiền xử lý" ). Nó không chỉ là một khuyến nghị thực hành tốt nhất. Các đối số được truyền cho lệnh này sẽ hiển thị trong các tập lệnh xây dựng được tạo ra gọi các công cụ không mong đợi chúng (ví dụ: trình biên dịch tài nguyên).
IInspectable

Đó không phải là "kiểm tra trình biên dịch", đó là kiểm tra công cụ xây dựng.
Thomas

3

Theo tài liệu 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 và Clang chia sẻ những lá cờ này, vì vậy điều này sẽ bao gồm cả 3.


Đừng dùng cái này. Thay vào đó, hãy sử dụng target_compile_options (). Đề cập đến tài liệu mới nhất có vẻ là "chính xác", nhưng đó là một mục cổ xưa chỉ để tương thích ngược.
caoan

1
@caoanan Tài liệu đề cập không có gì tương thích ngược cho việc này. add_compile_optionslà toàn thư mục, trong khi target_compile_optionschỉ dành cho một mục tiêu.
TehWan

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

Nếu bạn sử dụng target_compile_options- cmake sẽ cố gắng sử dụng /W*cờ kép , điều này sẽ đưa ra cảnh báo bởi trình biên dịch.


Cảm ơn vì điều đó. Tôi đã ngây thơ sử dụng cách add_compile_optionsduy nhất để nhận được vô số cảnh báo /W3đang bị tràn ngập /W4. Thực tế tha CMake không giải quyết tùy chọn thô sơ này (đặt mức cảnh báo) là vượt quá niềm tin.
Phục sinh
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.