CMake表示编译器不支持标志,但确实如此

时间:2018-05-19 08:21:49

标签: c cmake compiler-warnings

我正在使用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错误?

用于此测试的工具及其版本:

  • macOS 10.13.4
  • CMake 3.11.2
  • 测试的编译器(两者都显示相同的问题):
    • Apple LLVM版本9.1.0(clang-902.0.39.1)
    • gcc-8(Homebrew GCC 8.1.0)8.1.0

1 个答案:

答案 0 :(得分:1)

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中的一个错误。