如何在CMake中消除特定的编译器警告

4

CMake在生成Makefile项目时似乎会附加一些默认的编译器标志,例如-Wall-Wextra等等。其中一个默认标志是-Wsign-conversion,我想从列表中删除它。可以通过添加抑制标志-Wno-sign-conversion来实现。

target_compile_options(myTarget PRIVATE "-Wno-sign-conversion")

没有任何效果。采用“现代化的CMake”应该怎么做呢?


1
我刚刚使用CMake 3.20进行了检查,发现它默认不设置任何警告标志。它设置的标志是用于调试构建的“-g”,以及用于发布构建的“-O3 -DNDEBUG”。我记得最近有一系列的更改来减少默认标志的数量,所以也许你使用的CMake版本太旧了。但我认为更有可能的是你自己的项目或者你包含的某些内容添加了警告标志(例如,如果你有工具链文件,则可能是由工具链文件添加的)。 - Corristo
2个回答

6

如果您不想查询编译器的ID /名称和/或版本(很快会变得混乱),则可以使用CheckCCompilerFlag(或CheckCXXCompilerFlag)。这里的技巧是不要检查警告禁用标志,而是检查警告本身。例如:

include(CheckCCompilerFlag)
check_c_compiler_flag(-Wsign-conversion HAVE_SIGN_CONVERSION)

if (HAVE_SIGN_CONVERSION)
    target_compile_options(target_name PRIVATE -Wno-sign-conversion)
endif (HAVE_SIGN_CONVERSION)

需要注意的是,建议避免直接设置CMAKE_C_FLAGS和/或CMAKE_CXX_FLAGS。如有可能,请使用target_compile_options仅为需要这样做的目标禁用警告。如果要全局禁用它,请使用add_compile_options

请注意,如果您的构建脚本的其他部分直接设置这些标志,您仍可能会收到警告(例如,如果某人执行set(CMAKE_CXX_FLAGS"${CMAKE_CXX_FLAGS} -Wsign-conversion"))。这也是避免直接设置CMAKE_C_FLAGSCMAKE_CXX_FLAGS的原因之一,因为它变得极其难以控制发生了什么。

选项添加的顺序也很重要。以下最小示例说明了这一点(假设example.cpp包含将触发-Wsign-conversion警告的代码):

project(example)

add_executable(example example.cpp)
target_compile_options(example PRIVATE -Wsign-conversion)
target_compile_options(example PRIVATE -Wno-sign-conversion)

这将抑制警告。编译器被这样调用:/usr/bin/c++ -Wsign-conversion -Wno-sign-conversion

我们可以交换这两个target_compile_options调用:

project(example)

add_executable(example example.cpp)
target_compile_options(example PRIVATE -Wno-sign-conversion)
target_compile_options(example PRIVATE -Wsign-conversion)

在这种情况下,编译器是这样调用的:/usr/bin/c++ -Wno-sign-conversion -Wsign-conversion 这会触发警告。

1
只是为了补充一下:这些编译器检查在配置项目时会有不可忽视的开销。因此,如果你知道你的项目支持的每个GCC和Clang版本(例如,如果你需要C++20功能,但只有警告存在的版本中才可用),最好检查编译器ID而非进行这些检查。 - Corristo
这是事实,但通常你只需要配置一次项目。它可能仍然会影响到你的持续集成构建时间,所以值得考虑,但我个人更愿意花更长的时间来配置,而不是使用嵌套的if/else来判断编译器ID和版本(个人观点,没有正确的做法,取决于你的用例和优先级)。 - icebp
问题在于,与我的原始示例一样,如果HAVE_SIGN_CONVERSION == true并且您添加了禁用标志,那么Makefile中将会出现以下类似的内容:... -Wall -Wextra ... -Wsign-conversion -Wno-sign-conversion。在GCC中,如果已经设置了相应的“正向”标志,添加任何警告标志的-no版本似乎是无效的。 - Ignorant
1
如果你按照这个顺序设置警告,它们不应该被触发:-Wsign-conversion -Wno-sign-conversion-Wconversion也会启用-Wsign-conversion,你能否在禁用-Wsign-conversion后检查一下是否启用了该标志? - icebp
1
所以也许在你禁用它之后,旗帜就会被启用了?是的,看起来你走在正确的轨道上。另外,正如@Corristo建议的那样,这些旗帜可能是由主项目包含的依赖项添加的。我需要进一步调查一下。谢谢! - Ignorant
显示剩余3条评论

0

我不太确定这是否是“现代CMake”,但我使用类似于此来设置gcc标志,直接在cmake_minimum_required变量之后。

set (CMAKE_CXX_STANDARD 17)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-sign-conversion")
endif()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接