Regression: C standard not set in newer versions of CMake
In our project, https://gitlab.mel.vin/template/c, CMake is instructed to set the C standard and C++ standard to 11 and 17 respectively. Both C and C++ extensions are also disabled before setting the standards. Following code is available on https://gitlab.mel.vin/template/c/-/blob/master/cmake/code.cmake
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# CMake doesn't allow to propagate this yet, so set it globally
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_CXX_EXTENSIONS OFF)
# general target flags
unset(PROJECT_FLAGS)
unset(PROJECT_LINKER_FLAGS)
unset(PROJECT_INCLUDE_DIRS)
# set warning flags for debug
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
if(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR
CMAKE_C_COMPILER_ID STREQUAL "GNU")
set(PROJECT_FLAGS ${PROJECT_FLAGS}
-Wall
-Wextra
-Wconversion
-pedantic)
if(${WERROR})
set(PROJECT_FLAGS ${PROJECT_FLAGS} -Werror)
endif()
else()
message(WARNING "Warnings not supported for current compiler.")
endif()
endif()
set(PROJECT_INCLUDE_DIRS ${PROJECT_INCLUDE_DIRS}
"${PROJECT_SOURCE_DIR}/include")
install(DIRECTORY include/ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
if(${COVERAGE})
include(coverage)
endif()
if(${CLANG_TIDY})
include(clang_tidy)
endif()
if(${SANITISE})
include(sanitise)
endif()
include(export)
include(version_header)
# create the common C target
add_library(cinterface INTERFACE)
target_compile_options(cinterface INTERFACE ${PROJECT_FLAGS})
target_compile_features(cinterface INTERFACE c_std_11)
target_include_directories(cinterface INTERFACE ${PROJECT_INCLUDE_DIRS})
target_link_options(cinterface INTERFACE ${PROJECT_LINKER_FLAGS})
# create the common CXX target
add_library(cxxinterface INTERFACE)
target_compile_options(cxxinterface INTERFACE ${PROJECT_FLAGS})
target_compile_features(cxxinterface INTERFACE cxx_std_17)
target_include_directories(cxxinterface INTERFACE ${PROJECT_INCLUDE_DIRS})
target_link_options(cxxinterface INTERFACE ${PROJECT_LINKER_FLAGS})
add_subdirectory(src)
if(${TEST})
enable_testing()
include(doctest)
add_subdirectory(test)
endif()
When running VERBOSE=1 make
after setting up the project with CMake version 3.18.4-1 (Debian testing),
- C standard is not enforced by the compiler (absence of
-std=c11
flag). - C standard is enforced by the compiler (presence of
-std=c++17
flag).
However with Cmake version 3.13.4-1 (Debian buster), both standards are enforced meaning it works as intended. This may be a regression bug with newer versions.
CMake was invoked as follows.
% cmake -DCMAKE_BUILD_TYPE:STRING=Debug -DCOVERAGE:BOOL=ON -DTEST:BOOL=ON -DWERROR:BOOL=ON ..
Tested with both GCC (Debian 10.2.0-16) 10.2.0 and Clang version 9.0.1-15.
The output from CMake version 3.18.4 shown in the following, minified, snippet:
[ 10%] Building C object src/CMakeFiles/c_template.dir/add.c.o
cd /home/renken/dev/vermware/template/c/build/src && /usr/bin/cc -DC_TEMPLATE_EXPORTS -I/home/renken/dev/vermware/template/c/include -I/home/renken/dev/vermware/template/c/build/include -g -fPIC -Wall -Wextra -Wconversion -pedantic -Werror --coverage -o CMakeFiles/c_template.dir/add.c.o -c /home/renken/dev/vermware/template/c/src/add.c
[ 90%] Building CXX object test/CMakeFiles/test_add.dir/add.cpp.o
cd /home/renken/dev/vermware/template/c/build/test && /usr/bin/c++ -I/home/renken/dev/vermware/template/c/include -I/home/renken/dev/vermware/template/c/build/include -g -Wall -Wextra -Wconversion -pedantic -Werror --coverage -std=c++17 -o CMakeFiles/test_add.dir/add.cpp.o -c /home/renken/dev/vermware/template/c/test/add.cpp
Keep in mind that applying the following diff results -std=c11
to show up.
diff --git a/cmake/code.cmake b/cmake/code.cmake
index 9bf3b9d..cba9525 100644
--- a/cmake/code.cmake
+++ b/cmake/code.cmake
@@ -3,6 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# CMake doesn't allow to propagate this yet, so set it globally
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_CXX_EXTENSIONS OFF)
+set(CMAKE_C_STANDARD 11)
# general target flags
unset(PROJECT_FLAGS)
Though this is, I think, the old way of writing CMake.