CMake 指示编译器不支持标志,但它支持

CMake indicates compiler does not support flag but it does

我正在使用 CMake 配置 C 项目的可移植编译,我想检查使用的编译器是否支持我愿意使用的各种编译标志。

假设我有这个简单的 C 文件 noinit.c,它使用了一个未初始化的变量:

#include <stdio.h>

int main(void)
{
    int i; // Uninitialized
    printf("%d\n", i+2);
    return 0;
}

我希望编译器引发错误,所以我使用标志 -Wall -Werror。这是我的 CMakeLists.txt 文件:

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")
foreach (FLAG IN LISTS COMPILER_FLAGS_TO_USE)
    # Check if the compiler supports the flag. The result of this test
    # is printed to STDOUT when calling `cmake`.
    check_c_compiler_flag(${FLAG} COMPILER_SUPPORTS_${FLAG})
    # Regardless of the test, force the usage of the flag anyway.
    string(APPEND CMAKE_C_FLAGS " ${FLAG}")
endforeach()

add_executable(noinit noinit.c)

当我调用 CMake 时,它​​说我的编译器不支持 -Werror

> mkdir build
> cd build
> cmake ..
-- The C compiler identification is AppleClang 9.1.0.9020039
-- Check for working C compiler: /Library/Developer/CommandLineTools/usr/bin/cc
-- Check for working C compiler: /Library/Developer/CommandLineTools/usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Performing Test COMPILER_SUPPORTS_-Wall
-- Performing Test COMPILER_SUPPORTS_-Wall - Success
-- Performing Test COMPILER_SUPPORTS_-Werror
-- Performing Test COMPILER_SUPPORTS_-Werror - Failed  # <-- NOTICE THE FAIL HERE!
-- Configuring done
-- Generating done
-- Build files have been written to: /some/path/to/cmake_compiler_flag_test/build

但是当我调用编译器(它支持该标志)时,它实际上按预期工作并引发有关未初始化变量的错误:

> make
[ 50%] Building C object CMakeFiles/noinit.dir/noinit.c.o
/some/path/to/cmake_compiler_flag_test/noinit.c:5:20: error: variable 'i' is
      uninitialized when used here [-Werror,-Wuninitialized]
    printf("%d\n", i+2);
                   ^
/some/path/to/cmake_compiler_flag_test/noinit.c:4:10: note: initialize the
      variable 'i' to silence this warning
    int i; // Uninitialized
         ^
          = 0
1 error generated.
make[2]: *** [CMakeFiles/noinit.dir/noinit.c.o] Error 1
make[1]: *** [CMakeFiles/noinit.dir/all] Error 2
make: *** [all] Error 2

是我的 CMake 配置有问题还是这是 CMake 错误?

本次测试使用的工具及其版本:

CMakeFiles/CMakeError.log 有点暴露:

In file included from <built-in>:341: 
<command line>:1:27: error: ISO C99 requires whitespace after 
the macro name [-Werror,-Wc99-extensions] 
#define COMPILER_SUPPORTS_-Werror 1

1 error generated.

您的变量名创建 (COMPILER_SUPPORTS_${FLAG}) 似乎失败了,因为名称中有一个连字符 -。在添加之前,您需要从 ${FLAG} 中删除连字符,或者找到其他方法。

根据您自己的建议,您可以添加行

string(REPLACE "-" "" FLAG_NO_HYPHEN ${FLAG})

编译标志测试之前,然后使用

check_c_compiler_flag(${FLAG} COMPILER_SUPPORTS_${FLAG_NO_HYPHEN})

相反。


对我来说真正奇怪的是 -Wall 似乎成功了,这可能会让你失望(如果两者都失败了,更明显的是 CMakeLists.txt 中有些不对劲)。
颠倒顶部附近 list(...) 中两个标志字符串的顺序实际上会导致两个测试失败。

CMakeFiles/CMakeOutput.log,在这种情况下,显示

In file included from <built-in>:341:
<command line>:1:27: warning: ISO C99 requires whitespace after the
macro name [-Wc99-extensions]
#define COMPILER_SUPPORTS_-Wall 1

1 warning generated.

这里只是一个警告,但是顺序相反,两个测试都会出错。

也许有人知道这是为什么,并可以发表评论。或者它只是 CMake 中的一个错误。