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

时间:2014-07-19 11:44:09

标签: c++ c cmake c99

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

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

我也不想检查哪个编译器并附加类似的内容:

set(CMAKE_C_FLAGS "-std=c99") # that would be bad

所以我发现了这篇帖子:Enabling C99 in CMake以及相关的功能请求:0012300: CMake has no cross-platform way to ask for C99。在这个Mantis bug中,我了解了target_compiler_features,之后我发现了这些SOF答案:How to activate C++11 in CMake?How to detect C++11 support of a compiler with CMake

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

6 个答案:

答案 0 :(得分:24)

创建目标(如库或可执行文件)后,在CMakeLists.txt文件中添加如下所示的行:

set_property(TARGET tgt PROPERTY C_STANDARD 99)

其中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)

将宏放在顶级文件中以便它随处可见后,您只需在任何CMakeLists文件的顶部写入use_c99(),该文件定义了包含C99代码的目标。

针对macOS

的clang用户的CMake问题#15943

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

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

    # Fix behavior of CMAKE_C_STANDARD when targeting macOS.
    if (POLICY CMP0025)
      cmake_policy(SET CMP0025 NEW)
    endif ()
    

答案 1 :(得分:0)

编辑CMakeLists

在线添加> 2

set (CMAKE_C_STANDARD 99)

然后

cmake 3 ..

答案 2 :(得分:0)

随着这个问题越来越引起人们的关注,我在这里总结一下我认为是当今最好的选择。

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

target_compile_features(target PUBLIC c_std_99)

我认为这是首选方法,因为它是针对每个目标的,它公开了一种通过PUBLICINTERFACEPRIVATE关键字控制可见性的方法-请参见the reference 。尽管target_compile_features命令是在3.1版本上引入的,但是c_std_99至少需要CMake 3.8

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

set_property(TARGET target PROPERTY C_STANDARD 99)

从CMake 3.1开始可用。可能的缺点是它不执行标准(请参见the reference)。因此,设置C_STANDARD_REQUIRED属性可能会有用:

set_property(TARGET target PROPERTY C_STANDARD_REQUIRED ON)

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

因此使所有目标都默认使用C99的一种可能方法是:

set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED TRUE)

请注意,在target_compile_features方法上进行扩展,如果您只关心某些特定功能,则可能不需要某些特定语言标准。例如,通过设置:

target_compile_features(target PUBLIC c_variadic_macros)

CMake将注意选择适当的标志来强制可变参数宏的可用性。但是,目前只有少数此类功能可用于C语言-有关完整列表,请参见CMAKE_C_KNOWN_FEATURES-并且循环初始声明不在其中。

答案 3 :(得分:-1)

将以下内容添加到CMakeLists.txt文件并再次运行cmake

set(CMAKE_C_FLAGS "std=c99")

答案 4 :(得分:-1)

从CMake 3.0.2起,可以使用add_compile_options(https://cmake.org/cmake/help/latest/command/add_compile_options.html#command:add_compile_options),这是我发现设置C标准的最便捷的方法之一。

在声明目标(使用add_library或add_executable)之前,请务必使用此命令。

下面是一个CMake脚本示例,将C standart设置为C99:

add_compile_options(-std=c99)
add_executable(my_exe ${SOURCES})

答案 5 :(得分:-2)

在libevent中,在CMakeLists.txt中添加以下内容

set (CMAKE_C_FLAGS "-std=gnu99 ${CMAKE_C_FLAGS}")