The place for warning flags is in the CMakePresets.json or a custom toolchain file. Only hard usage requirements belong in the CMakeLists.txt files. Your code successfully compiling has nothing to do with which warnings you use.
Furthermore, you should generally apply warning flags consistently across your project. Don't use the build system to bury problems in your code. If your compiler is throwing a false positive, add compiler-speicific pragmas (guarded by the necessary ifdefs, as needed) to locally disable warnings around the problematic code.
Here's how I would write your top-level CMakeLists.txt
cmake_minimum_required(VERSION 3.21)
project(proj LANGUAGES C ASM)
set(CMAKE_C_STANDARD 11
CACHE STRING "Version of the C standard to use")
option(CMAKE_C_STANDARD_REQUIRED "Enable to enforce strict C standard selection" ON)
option(CMAKE_C_EXTENSIONS "Enable to allow compiler-specific C extensions" OFF)
add_subdirectory(src/lib/somelib)
add_executable(my_executable src/app/main.c)
target_link_libraries(my_executable PRIVATE somelib)
In CMakePresets.json:
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 21,
"patch": 0
},
"configurePresets": [
{
"name": "default",
"displayName": "Default",
"description": "Default build options for GCC-compatible compilers",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_C_FLAGS": "-Wall -Wextra -pedantic"
}
}
]
}
Compile with
$ cmake --preset default
I have written about the rationale for this elsewhere, so I'll post links to those references.
- https://alexreinking.com/blog/how-to-use-cmake-without-the-agonizing-pain-part-2.html
- https://stackoverflow.com/a/68094639/2137996
The gist is that the meaning of a warning flag is dependent on the compiler vendor, variant, and version, and so putting them in your CMakeLists.txt attaches a very brittle dependency on those things. It makes compiler upgrades and changes unnecessarily difficult and makes your build harder to distribute and reuse, even within a company.
Additionally, you should avoid using relative paths in target_include_directories
and library targets should generally guard their paths with $<BUILD_INTERFACE:...>
to be ready for installation / export.
target_include_directories(
somelib PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>")