CMake提示编译器不支持-Werror但实际可用,是配置问题还是bug?
问题根源:不是CMake Bug,是检测逻辑的顺序问题
你遇到的情况其实不是CMake的bug,而是检测flag的顺序和CMake测试程序的细节导致的误判。
为什么-Werror检测会失败?
CMake的CheckCCompilerFlag函数在测试flag时,会编译一个默认的测试程序,大致长这样:
#ifdef __cplusplus extern "C" #endif int main(int argc, char** argv) { return 0; }
注意这里的argc和argv是未使用的变量。
你的问题出在foreach循环的逻辑:你先检测-Wall,然后立刻把它加到CMAKE_C_FLAGS里。接下来检测-Werror的时候,CMake会用当前的CMAKE_C_FLAGS(已经包含-Wall)加上-Werror来编译测试程序。
-Wall会启用-Wunused-variable警告,测试程序里的未使用参数会触发这个警告;而-Werror会把所有警告转为错误,导致测试编译失败——CMake因此误判为编译器不支持-Werror。
但实际编译你的noinit.c时,-Werror确实能正常工作,因为你的代码本身有未初始化变量的警告,-Werror会把它转为错误,这才是你想要的效果。
修复方案
你只需要调整检测和添加flag的顺序,先完成所有flag的检测,再统一添加到CMAKE_C_FLAGS,这样检测-Werror时就不会受到-Wall的影响:
cmake_minimum_required(VERSION 3.1 FATAL_ERROR) project(cmake_compiler_flag_test C) set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) include(CheckCCompilerFlag) list(APPEND COMPILER_FLAGS_TO_USE "-Wall" "-Werror") # 第一步:先批量检测所有flags,此时CMAKE_C_FLAGS还是空的 foreach (FLAG IN LISTS COMPILER_FLAGS_TO_USE) check_c_compiler_flag(${FLAG} COMPILER_SUPPORTS_${FLAG}) endforeach() # 第二步:统一把flags添加到CMAKE_C_FLAGS foreach (FLAG IN LISTS COMPILER_FLAGS_TO_USE) string(APPEND CMAKE_C_FLAGS " ${FLAG}") endforeach() add_executable(noinit noinit.c)
额外建议
对于-Werror这类几乎所有现代编译器(GCC、Clang、MSVC都有等价实现)都支持的flag,其实可以跳过检测直接添加。如果需要跨编译器兼容,可以针对不同编译器设置对应的flag:
if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") list(APPEND COMPILER_FLAGS_TO_USE "-Wall" "-Werror") elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC") list(APPEND COMPILER_FLAGS_TO_USE "/W4" "/WX") endif()
内容的提问来源于stack exchange,提问作者Matjaž
相关产品推荐
相关产品推荐

