在CMake中强制使用C99(使用'for'循环初始声明)

Tar*_*arc 24 c c++ c99 cmake

我一直在寻找一种可移植的方法来强制CMake启用编译器的C99功能,以避免出现以下gcc错误:

error: ‘for’ loop initial declarations are only allowed in C99 mode
for (int s = 1; s <= in_para->StepNumber; s++){
^
Run Code Online (Sandbox Code Playgroud)

我也不想检查哪个编译器并附加如下内容:

set(CMAKE_C_FLAGS "-std=c99") # that would be bad
Run Code Online (Sandbox Code Playgroud)

所以我发现这篇文章:在CMake中启用C99以及相关的功能请求:0012300:CMake没有跨平台的方式来请求C99.在这个Mantis bug中,我了解了target_compiler_features之后我发现了这些SOF答案:如何在CMake中激活C++ 11?以及如何使用CMake检测编译器的C++ 11支持.

所以我的问题是:这target_compiler_features将提供一种需要C功能和C++功能的方法吗?现在最简单的方法是什么 - 我目前正在使用CMake 2.8.12.2.这target_compiler_features不是CMake的最新发行版本(3.0.0).你知道什么时候被释放吗?

Dav*_*son 24

创建目标(如库或可执行文件)后,在CMakeLists.txt文件中放置如下行:

set_property(TARGET tgt PROPERTY C_STANDARD 99)
Run Code Online (Sandbox Code Playgroud)

tgt你的目标名称在哪里.

我认为这是在CMake 3.1中添加的,文档在这里:

http://www.cmake.org/cmake/help/v3.1/prop_tgt/C_STANDARD.html

如果您需要支持早于3.1的CMake版本,则可以使用此宏:

macro(use_c99)
  if (CMAKE_VERSION VERSION_LESS "3.1")
    if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
      set (CMAKE_C_FLAGS "-std=gnu99 ${CMAKE_C_FLAGS}")
    endif ()
  else ()
    set (CMAKE_C_STANDARD 99)
  endif ()
endmacro(use_c99)
Run Code Online (Sandbox Code Playgroud)

将该宏放在顶级文件中以使其在任何地方都可见之后,您可以use_c99()在任何CMakeLists文件的顶部写入,该文件定义了包含C99代码的目标.

针对macOS的clang用户,CMake问题#15943

如果您使用CMake和clang来定位MacOS,则会出现一个错误,导致该CMAKE_C_STANDARD功能无法正常工作(不添加任何编译器标志).确保您执行以下操作之一:

  • 使用cmake_minimum_required来要求CMake 3.0或更高版本,或
  • project命令之前,使用以下代码将策略CMP0025设置为NEW,并将其放在CMakeLists.txt文件的顶部:

    # Fix behavior of CMAKE_C_STANDARD when targeting macOS.
    if (POLICY CMP0025)
      cmake_policy(SET CMP0025 NEW)
    endif ()
    
    Run Code Online (Sandbox Code Playgroud)


Tar*_*arc 7

由于这个问题不断受到关注,我在这里总结了我认为今天最好的选择。

以下命令将 C99 设置为 的最低要求target

target_compile_features(target PUBLIC c_std_99)
Run Code Online (Sandbox Code Playgroud)

PUBLIC我认为这是首选方式,因为它针对每个目标,并公开了一种通过INTERFACE和关键字控制可见性的方法PRIVATE- 请参阅参考资料。虽然该target_compile_features命令是在 3.1 版本上引入的,但c_std_99至少需要CMake 3.8

与上面类似,另一种将C99设置为标准的方法target如下:

set_property(TARGET target PROPERTY C_STANDARD 99)
Run Code Online (Sandbox Code Playgroud)

从 CMake 3.1 开始可用。一个可能的缺点是它不强制执行该标准(请参阅参考资料)。因此,设置该C_STANDARD_REQUIRED属性可能会很有用:

set_property(TARGET target PROPERTY C_STANDARD_REQUIRED ON)
Run Code Online (Sandbox Code Playgroud)

上述两个属性的默认值分别为CMAKE_C_STANDARDCMAKE_C_STANDARD_REQUIRED

因此,将 C99 设置为所有目标的默认值的一种可能方法是:

set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED TRUE)
Run Code Online (Sandbox Code Playgroud)

顺便说一句,扩展该target_compile_features方法,如果您只关心某些特定功能,则可能不需要某些特定的语言标准。例如通过设置:

target_compile_features(target PUBLIC c_variadic_macros)
Run Code Online (Sandbox Code Playgroud)

CMake 将谨慎选择适当的标志来强制可变参数宏的可用性。然而,目前 C 语言只有少数这样的功能 - 请参阅CMAKE_C_KNOWN_FEATURES了解完整列表 - 并且循环初始声明不在其中。