Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forcing C99 in CMake (to use 'for' loop initial declaration)

Tags:

c++

c

cmake

c99

I've been searching a portable way to force CMake to enable the compiler's C99 features in order to avoid the following gcc error for instance:

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

I also wouldn't like to check for which compiler and append something like:

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

So I found this post: Enabling C99 in CMake and the associated feature request: 0012300: CMake has no cross-platform way to ask for C99. In this Mantis bug I learned about target_compiler_features and after that I found these SOF answers on it: How to activate C++11 in CMake? and How to detect C++11 support of a compiler with CMake.

So my questions are: this target_compiler_features will provide a way to require a C feature as well as a C++ one? What is the most portable way to achive this by now - I'm currently using CMake 2.8.12.2. The target_compiler_features isn't in CMake's most recent release version (3.0.0). Do you know when it is being released?

like image 429
Tarc Avatar asked Jul 19 '14 11:07

Tarc


People also ask

How do I fix for loop initial declarations are only allowed in C99 mode?

This happens because declaring variables inside a for loop wasn't valid C until C99(which is the standard of C published in 1999), you can either declare your counter outside the for as pointed out by others or use the -std=c99 flag to tell the compiler explicitly that you're using this standard and it should interpret ...

How do I fix for loop initial declarations are only allowed in C99 or C11 mode?

solution. Declaring variables in a for loop is only allowed in C99 or C11 mode, and you need to select C99 as the language standard under Tools/complier option/code generation .

What is C11 mode in C?

C11 (formerly C1X) is an informal name for ISO/IEC 9899:2011, a past standard for the C programming language. It replaced C99 (standard ISO/IEC 9899:1999) and has been superseded by C17 (standard ISO/IEC 9899:2018).


1 Answers

After creating a target such as a library or executable, put a line like this in your CMakeLists.txt file:

set_property(TARGET tgt PROPERTY C_STANDARD 99) 

where tgt is the name of your target.

I think this was added in CMake 3.1, and the documentation is here:

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

If you need to support versions of CMake older than 3.1, you can use this macro:

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) 

After putting that macro in your top-level file so it is visible everywhere, you can just write use_c99() at the top of any CMakeLists file that defines a target with C99 code in it.

CMake issue #15943 for clang users targeting macOS

If you are using CMake and clang to target MacOS there is a bug that can cause the CMAKE_C_STANDARD feature to simply not work (not add any compiler flags). Make sure that you do one of the following things:

  • Use cmake_minimum_required to require CMake 3.0 or later, or
  • Set policy CMP0025 to NEW with the following code at the top of your CMakeLists.txt file before the project command:

    # Fix behavior of CMAKE_C_STANDARD when targeting macOS. if (POLICY CMP0025)   cmake_policy(SET CMP0025 NEW) endif () 
like image 169
David Grayson Avatar answered Sep 30 '22 18:09

David Grayson