141

如何使用CMake项目(不是整个解决方案)设置警告级别?应该在Visual StudioGCC上工作。

我找到了各种选项,但大多数似乎要么不起作用,要么与文档不一致。

4

7 回答 7

130

在现代 CMake 中,以下内容运行良好:

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

我的同事建议了一个替代版本:

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

替换${TARGET_NAME}为实际的目标名称。-Werror是可选的,它将所有警告变成错误。

或者add_compile_options(...),如果您想按照@aldo 在评论中的建议将其应用于所有目标,请使用。

此外,请务必了解和之间的区别PRIVATEPUBLIC公共选项将由依赖于给定目标的目标继承)。

于 2018-06-15T20:23:54.667 回答
104

更新:这个答案早于现代 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()
于 2010-09-29T00:57:45.883 回答
27

我编写的一些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_CONVERSIONXcode 属性(又名构建设置->警告->可疑隐式转换-> YES
  • 添加编译器标志:-Werror

Makefile gcc 和 clang:

  • 添加编译器标志:-Wconversion,-Werror

视觉工作室:

  • 添加编译器标志:/WX,/w14244

链接

于 2014-06-24T06:23:46.727 回答
14

根据Cmake 3.23 文档

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 个。

于 2020-04-23T07:17:41.387 回答
9

这是迄今为止我找到的最佳解决方案(包括编译器检查):

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

GCC 等效项是-Wall(未经测试)。

于 2010-03-03T06:23:32.150 回答
3
if(MSVC)
    string(REGEX REPLACE "/W[1-3]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
endif()

如果您使用target_compile_options- cmake 将尝试使用双重/W*标志,这将由编译器发出警告。

于 2020-04-05T10:18:48.420 回答
0

如何使用 CMake 为项目(不是整个解决方案)设置警告级别?

(我认为这意味着一个 CMake目标,而不是一个 CMake项目。)

我找到了各种选项,但大多数似乎要么不起作用,要么与文档不一致。

Kitware 的 API 可能会阻止您使构建系统变得脆弱和容易出错。这个问题的其他答案所鼓励的特殊情况至少违反了现代 CMake 构建系统的两个重要原则......

首先,不要在 CMakeLists.txt 文件中指定特定于工具链的详细信息。它使构建系统变得脆弱。例如,如果工具链的未来版本中出现新警告,编译器将发出错误,您的用户可能需要破解您的项目才能构建目标。

相反,编写与工具链无关的 CMakeLists.txt 文件并保留用户在他们认为合适时进行自定义的能力。理想情况下,您的项目应该使用 vanilla 工具链配置在任何地方构建 - 即使默认情况下不会启用您首选的警告。

其次,如果您打算将二进制文件链接在一起,标志应该是一致的。这降低了可能导致程序格式错误的不兼容风险。但是,警告标志不太可能影响代码生成,因此在链接在一起的目标之间改变这些可能是安全的。

所以...如果您希望为每个工具链指定标志,并且如果您绝对必须为不同的目标使用不同的标志,请使用自定义变量:

# CMakeLists.txt
project(my_project)

add_executable(my_target source_file.cpp)
target_compile_options(my_target PRIVATE "${MY_PROJECT_ELEVATED_WARNING_FLAGS}")

有很多方法可以设置这些变量,例如 CMakeCache.txt、工具链文件和 via CMAKE_PROJECT_INCLUDE_BEFORE。但最简单的方法是在配置期间在命令行上,对于 GCC

cmake -DMY_PROJECT_ELEVATED_WARNING_FLAGS:STRING="-Wall;-Wextra;-Wpedantic;-Werror" <path-to-project>

对于 MSVC

cmake -DMY_PROJECT_ELEVATED_WARNING_FLAGS:STRING="/W4;/WX" <path-to-project>
于 2021-12-30T16:09:07.183 回答