CMake can omit the C standard flag
Summary
After a recent system update, I started getting an error in my text editor: “unknown type name bool
.” I fixed this by adding the following to CMakeLists.txt:
set_property(TARGET <target> PROPERTY C_STANDARD_REQUIRED ON)
Why it happened
This error was pretty surprising for a few reasons, not least because the project still compiled fine!
My codebase compiles under the C23 standard, where bool
is a built-in type. This isn’t valid under previous C standards, though, where bool
is a macro that’s created by the <stdbool.h>
header.
CMake defaults to using the system compiler. Here, that’s GCC. After the system update, GCC defaulted to compiling code under the C23 standard.
GCC then defaults to compiling code under the C23 standard, and CMake knows this and omits -std=c23
by default.
However, my IDE isn’t using GCC’s language server for diagnostics (because GCC doesn’t have one); it’s using the clangd
language server. So how does clangd
know which language standard to interpret your codebase as?
Because this is C, the compiler is given command-line options by various nonstandard turing-complete build runners. Language servers can’t really hook into this, as they’re started by the editor and don’t really want to interface with the build system mess.
To solve this, Manuel Klimek proposed exporting compile_commands.json
(then cxx_commands.json
) from CMake. Later, this was gated behind the CMAKE_EXPORT_COMPILE_COMMANDS
variable, which can be enabled by adding -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
to your command-line CMake invocation.
This file provides each source file’s compiler arguments. In my case, it looked something like this:
[
{
"directory": [...],
"command": "/usr/bin/cc -g -Wall -Wextra -Werror -fsanitize=undefined -o [...]/file.c.o -c [...]/file.c",
"file": [...],
"output": [...]
}
]
Importantly, clangd
is from Clang infrastructure. This means it (re-)uses Clang’s command-line argument parsing! And when CMake omits the -std=c23
flag, Clang compiles under its default standard: C17.
The fix
Enabling the C_STANDARD_REQUIRED target property tells CMake to never omit this flag; the corresponding target property for C++ is CXX_STANDARD_REQUIRED
.