How to make CMake use gnu17 C standard instead of ISO C17 - c

I am trying to force CMake to pass std=gnu17 instead of std=c17 to GCC.
I tried:
set_property(TARGET "${MyProject_${Compile_Type}_NAME}" PROPERTY C_STANDARD gnu17)
in the CMakeLists.txt but I get the following error:
CMake Error at CMakeLists.txt:260 (add_executable):
C_STANDARD is set to invalid value 'gnu17'
The same happens when I try gnu11 instead of gnu17.
The reason I want it to pass the flag is that I am using one of the GCC extensions and that produces a warning when using -pedantic warning levels (which I would prefer to keep using).
Please notice this is specifically about C, not C++.

Usually, CMake will use -std=gnu17 with plain C_STANDARD 17.
But if you want to be sure that CMake will use compiler-specific extensions, then you may set also C_EXTENSIONS property:
set_target_properties(<...> PROPERTIES
C_STANDARD 17
C_EXTENSIONS ON
)
If your code works only with a specific compiler and its extentions, then you probably want to also check a compiler:
if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
message(FATAL_ERROR "The project requires g++ to be used as C++ compiler"
endif()

Related

Compile with Clang and use GETTEXT

I have a automake enabled project which I would like to compile with clang. I have added a configure option to enable clang:
AC_ARG_ENABLE([clang],
[AS_HELP_STRING([--enable-clang],[use clang instead of gcc as C compiler.])])
#Use C99 compilation mode
if test "x$enable_clang" = "xyes"; then
# clang uses c99 mode by default, so we just set CC to clang and we are done
CC="clang";
else
# We do not need to set CC as the default is gcc, but we need to set it to
# use C99 compilation mode
CFLAGS="$CFLAGS -std=c99";
fi
Further up in the file I have also the following two macros, to enable gettext functionality:
AM_GNU_GETTEXT_VERSION([0.18.1])
AM_GNU_GETTEXT([external])
If these two macros are present then configure ignores that the CC variable is set to clang and falls back to gcc. I have to comment out the gettext macros and then clang is used.
Obviously there is some problem with GETTEXT and clang. Am I using the wrong macro, or is clang not able to use the gnu gettext library? How can I fix this?
Have you tried to set CC to clang before you check for libraries (like gettext)? – Some programmer dude
Nice that worked. – lanoxx

Enable C99 in Qt Creator

I've created a Plain C project in Qt Creator in Linux, but I'm getting this error:
error: 'for' loop initial declarations are only allowed in C99 mode
note: use option -std=c99 or -std=gnu99 to compile your code
What should I put in my *.pro file to enable C99?
QMAKE_CFLAGS += -std=c99
This worked for me, even though it is not documented and the intellisense doesn't recognize it.
You could set QMAKE_CC or QMAKE_CFLAGS_DEBUG and QMAKE_CFLAGS_RELEASE to contain -std=c99, e.g. add into your .pro file
QMAKE_CC= gcc -std=c99

How to compile a Linux kernel module using -std=gnu99?

I've recently learned how to program simple character drivers and while playing around with the code I noticed that I get a lot of the following GCC warnings thrown for my C99 code:
warning: ISO C90 forbids mixed declarations and code
I assume this is because the main Linux kernel Makefile is set to compile using a non-C99 standard. I searched around I found this answer here on stackoverflow: How to use make and compile as C99?
So I naturally tried the following in my Makefile:
ccflags-y := -std=gnu99
Unfortunately this didn't silence the GCC warnings. I checked the verbose output of make and verified that GCC is indeed executed with the -std=gnu99 tacked on at the end; so I'm a bit confused.
How do I properly compile a Linux kernel module using the -std=gnu99 option?
EDIT:
I noticed the GCC output shows this option: -Wdeclaration-after-statement. Is this why I am getting the warnings even with the -std=gnu99 option?
It turns out that -std=gnu99 does in fact work; I began seeing errors regarding C99 features after removing the compiler flag. So that meant something else was causing the warnings to print out besides the -std= option.
After parsing through the verbose output via make V=1, I discovered the -Wdeclaration-after-statement option as part of the GCC execution. This was the cause of the ISO C90 mixed declaration warnings I saw.
To disable the ISO C90 warnings, pass this to GCC: -Wno-declaration-after-statement.
For example:
ccflags-y := -std=gnu99 -Wno-declaration-after-statement
You can also specify the flag in your Makefile, if you have one:
FLAGS=-std=gnu99

Can I skip cmake compiler tests or avoid "error: unrecognized option '-rdynamic'"

compilation options for cmake (on windows) for ARM target system but when I run configure it's starting compiler tests:
CMake Error at D:/Program Files/CMake 2.8/share/cmake-2.8/Modules/CMakeTestCCompiler.cmake:52 (MESSAGE):
The C compiler "D:/Program Files/yagarto/bin/arm-none-eabi-gcc.exe" is not
able to compile a simple test program.
It fails with the following output:
Change Dir: D:/merge/complex/build/CMakeFiles/CMakeTmp
Run Build Command:D:/PROGRA~1/YAGART~1/bin/make.exe "cmTryCompileExec/fast"
D:/PROGRA~1/YAGART~1/bin/make.exe -f
CMakeFiles/cmTryCompileExec.dir/build.make
CMakeFiles/cmTryCompileExec.dir/build
make.exe[1]: Entering directory
`D:/merge/complex/build/CMakeFiles/CMakeTmp'
"D:/Program Files/CMake 2.8/bin/cmake.exe" -E cmake_progress_report
D:/merge/complex/build/CMakeFiles/CMakeTmp/CMakeFiles 1
Building C object CMakeFiles/cmTryCompileExec.dir/testCCompiler.c.o
"D:/Program Files/yagarto/bin/arm-none-eabi-gcc.exe" -o
CMakeFiles/cmTryCompileExec.dir/testCCompiler.c.o -c
D:/merge/complex/build/CMakeFiles/CMakeTmp/testCCompiler.c
Linking C executable cmTryCompileExec
"D:/Program Files/yagarto/bin/arm-none-eabi-gcc.exe"
"CMakeFiles/cmTryCompileExec.dir/testCCompiler.c.o" -o cmTryCompileExec
-rdynamic
arm-none-eabi-gcc.exe: error: unrecognized option '-rdynamic'
make.exe[1]: *** [cmTryCompileExec] Error 1
Using Yagatdo 4.6.* cross-compilation toolchain
How can I skip this tests or fix -rdynamic error that I am getting?
You can set CMAKE_<LANG>_COMPILER_WORKS to true to suppress further compiler checks for that language.
set(CMAKE_C_COMPILER_WORKS 1)
You can skip the compiler checks by adding NONE to your project call:
project(<projectname> NONE)
but this can have pretty far-reaching effects. For full details, run
cmake --help-command project
I'm not familiar with ARM, so this is probably not your best option here. I guess you'd be better to see if there's a way to fix the -rdynamic flag.
EDIT:
It looks like this was identified as a bug which is effectively still unresolved. The comments in the bug report mention adding the following lines as a workaround (presumably before your project call):
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
It seems you target actually something else than Linux, so you should tell cmake that you are cross-compiling for the generic case:
SET(CMAKE_SYSTEM_NAME Generic)
Followed by (optionally, but nice to specify):
SET(CMAKE_SYSTEM_PROCESSOR arm)
SET(CMAKE_CROSSCOMPILING 1)
However, if you specify (which you likely did because this is stated in a lot of examples online):
SET(CMAKE_SYSTEM_NAME Linux)
Then cmake will load the configuration files from (suppose version 2.8) the file:
/usr/share/cmake-2.8/Modules/Platform/Linux.cmake
from which it is likely to load:
/usr/share/cmake-2.8/Modules/Platform/Linux-GNU.cmake
Here the -rdynamic flag is set for historical reasons:
macro(__linux_compiler_gnu lang)
# We pass this for historical reasons. Projects may have
# executables that use dlopen but do not set ENABLE_EXPORTS.
set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-rdynamic")
endmacro()
Rather than disabling the tests as indeed is done by specifying NONE as the PROJECT argument, it seems setting the CMAKE_SYSTEM_NAME (to something else than Linux, for instance Generic) is what you actually want to do.
If you're just compiling a static library and you want to avoid having CMake test that the compiler can generate binaries, you can set the variable CMAKE_TRY_COMPILE_TARGET_TYPE.
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
When cross compiling for Windows, where there is no -rdynamic option, you can use
-DCMAKE_SYSTEM_NAME="Windows"
with cmake. Then Cmake will skip the test with -rdynamic.

autoconf set -fPIC only when necessary

I'm writing a shared library using autoconf/libtool which I want to compile for Linux and for Windows (Using the mingw cross-compiler). For Linux (and maybe other platforms which support it) I need to set -fPIC. So I put it into the CFLAGS in Makefile.am. But when I cross-compile it with mingw then gcc complains with a warning:
warning: -fPIC ignored for target (all code is position independent)
So obviously this option is not needed for Windows code. It is only a warning but I want to get rid of it anyway. How can I do this? Maybe there is already a libtool/autoconf feature which checks if the option is supported and only sets it when needed so I don't have to do this manually in Makefile.am?
You shouldn't need to set -fPIC manually, libtool will add it if you tell it what type of binary/library you're building.
lib_LTLIBRARIES = mylibrary.la
mylibrary_la_SOURCES = mylibrary.c
This can produce both a mylibrary.so with PIC (if needed) and a mylibrary.a without, depending on other Autoconf/Automake options. (Probably something like .dll and .lib on Windows, but I don't use that platform.)
I have used the following in configure.ac to add -fPIC conditionally:
AC_MSG_CHECKING(whether fPIC compiler option is accepted)
SAVED_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -fPIC -Werror"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [return 0;])],
[AC_MSG_RESULT(yes)
CFLAGS="$SAVED_CFLAGS -fPIC"],
[AC_MSG_RESULT(no)
CFLAGS="$SAVED_CFLAGS"])

Resources