我一直在寻找一种可移植的方法来强制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代码的目标.
如果您使用CMake和clang来定位MacOS,则会出现一个错误,导致该CMAKE_C_STANDARD
功能无法正常工作(不添加任何编译器标志).确保您执行以下操作之一:
在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)由于这个问题不断受到关注,我在这里总结了我认为今天最好的选择。
以下命令将 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_STANDARD
和CMAKE_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了解完整列表 - 并且循环初始声明不在其中。