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

rvpgvaaj  于 2022-11-11  发布在  其他
关注(0)|答案(7)|浏览(667)

我一直在寻找一种可移植的方法来强制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)中。您知道它何时发布吗?

iqih9akk

iqih9akk1#

创建库或可执行文件等目标后,在CMakeLists.txt文件中放入如下一行:

set_property(TARGET tgt PROPERTY C_STANDARD 99)

其中tgt是目标的名称。
我认为这是在CMake 3.1中添加的,文档在这里:
http://www.cmake.org/cmake/help/latest/prop_tgt/C_STANDARD.html
如果需要支持CMake 3.1之前的版本,可以使用以下宏:

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代码的目标。

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

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

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

# Fix behavior of CMAKE_C_STANDARD when targeting macOS.

  if (POLICY CMP0025)
    cmake_policy(SET CMP0025 NEW)
  endif ()
gxwragnw

gxwragnw2#

由于这个问题不断受到关注,我在这里总结了我认为今天最好的选择。
以下命令将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--循环初始声明不在其中。

fjnneemd

fjnneemd3#

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

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

yx2lnoni4#

编辑CMakeList
添加行〉2

set (CMAKE_C_STANDARD 99)

然后

cmake 3 ..
kdfy810k

kdfy810k5#

C_STANDARD property允许使用将C标准应用于特定目标,而不是全局应用。下面将C99应用于mytarget

set_property(TARGET mytarget PROPERTY C_STANDARD 99)
6l7fqoea

6l7fqoea6#

从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)。
下面是一个将C标准设置为C99的CMake脚本示例:

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

gzszwxb47#

将以下内容添加到CMakeLists.txt文件中,然后再次运行cmake

set(CMAKE_C_FLAGS "std=c99")

相关问题