Logo

dev-resources.site

for different kinds of informations.

The SYSTEM property from CMake 3.25

Published at
12/9/2022
Categories
cpp
programming
todayilearned
cmake
Author
pgradot
Author
7 person written this
pgradot
open
The SYSTEM property from CMake 3.25

CMake 3.25 introduced a new variable called SYSTEM. It will help us handle warnings from 3rd party libraries. Let's see how!

The issue (with a minimal example project)

Here is a minimal example project to reproduce the issue. It simply prints something with the great fmt library:

#include <fmt/core.h>

int main()
{
    fmt::print("The answer is {}", 42);
}
Enter fullscreen mode Exit fullscreen mode

The library is fetched from GitHub thanks to CMake's FetchContent module:

cmake_minimum_required(VERSION 3.25)
project(CMake_SYSTEM)

# Set C++ standard
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# Fetch fmt from GitHub
include(FetchContent)

FetchContent_Declare(
        fmt
        GIT_REPOSITORY https://github.com/fmtlib/fmt.git
        GIT_TAG 9.1.0
)

FetchContent_MakeAvailable(fmt)

# Create executable
add_executable(${PROJECT_NAME} main.cpp)

target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -pedantic -Wswitch-enum)

target_link_libraries(${PROJECT_NAME} PRIVATE fmt)
Enter fullscreen mode Exit fullscreen mode

The project can be built with:

mkdir build
cd build
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=RELEASE
ninja
Enter fullscreen mode Exit fullscreen mode

There is nothing very fancy here. However: when both C++20 and -Wswitch-enum are used, warnings like these are emitted:

C:/.../cmake_system/build/_deps/fmt-src/include/fmt/core.h:2796:3: warning: enumeration value 'dec' not handled in switch [-Wswitch-enum]
 2796 |   switch (specs.type) {
      |   ^~~~~~
C:/.../cmake_system/build/_deps/fmt-src/include/fmt/core.h:2796:3: warning: enumeration value 'oct' not handled in switch [-Wswitch-enum]
C:/.../cmake_system/build/_deps/fmt-src/include/fmt/core.h:2796:3: warning: enumeration value 'hex_lower' not handled in switch [-Wswitch-enum]
Enter fullscreen mode Exit fullscreen mode

Either use C++17 or remove the compiler option, and the warnings will disappear. Both of these solutions are not satisfying, but it's worth mentioning them because you may not run into the issue if you compile the code without one of these parameters.

The satisfying solution would be to ask GCC to treat fmt's headers as system headers, so that no warning will be emitted.

Before CMake 3.25

To ask GCC to treat a directory as a system include directory, you have to the following in CMake:

target_include_directories(target_name SYSTEM path/to/the/directory).
Enter fullscreen mode Exit fullscreen mode

Here, we don't have any explicit call to target_include_directories() as we directly call target_link_libraries(). There is a generic solution to get the path to any target's include directory, and we simply have to add these two magic lines at the end of our CMakeLists.txt:

get_target_property(fmt_include_dir fmt INTERFACE_INCLUDE_DIRECTORIES)
target_include_directories(${PROJECT_NAME} SYSTEM PRIVATE ${fmt_include_dir})
Enter fullscreen mode Exit fullscreen mode

That's it! Problem solved.

In case you wonder: here, the directory is build/_deps/fmt-src/include. Not something very easy to guess.

CMake 3.25 to the rescue

Obviously, the solution shown in the previous section isn't perfect. For instance, if fmt was used by several targets, we would have to call target_include_directories() several times. In some cases, include_directories() will help if you accept that you can't really control the affected targets.

This is why the SYSTEM target property was created in CMake 3.25:

Specifies that a target is a SYSTEM library. This has the following effects:

  • Entries of INTERFACE_INCLUDE_DIRECTORIES are treated as SYSTEM include directories when compiling consumers.
  • Entries of INTERFACE_SYSTEM_INCLUDE_DIRECTORIES are not affected, and will always be treated as SYSTEM include directories.

There is also a directory property with the same name:

This directory property is used to initialize the SYSTEM target property for targets created in that directory. It is set to true by add_subdirectory() and FetchContent_Declare() when the SYSTEM option is given as an argument to those commands.

How to use the SYSTEM property

With FetchContent_Declare()

To fix our example project, we can simply add a parameter to FetchContent_Declare():

FetchContent_Declare(
        fmt
        GIT_REPOSITORY https://github.com/fmtlib/fmt.git
        GIT_TAG 9.1.0
        SYSTEM
)
Enter fullscreen mode Exit fullscreen mode

The warnings are now gone!

NOTE = I got error with this, but I don't know why:

Manually setting the property

Another solution would be to manually change the property of the target. Just after FetchContent_MakeAvailable(fmt), the target is available and can be modified with set_target_properties(fmt PROPERTIES SYSTEM TRUE).

You can do this with any particular target, and you can do the same with a particular directory thanks to set_directory_properties().

With add_subdirectory()

Let's imagine we had manually downloaded fmt's sources and placed them in our project. We would have called add_subdirectory(fmt_directory SYSTEM) and all the target created there would have been flagged as SYSTEM.

Conclusion

Even if we might feel FetchContent is solely used to get 3rd party libraries from GitHub, this is not the only use case. This is why the SYSTEM is FALSE by default. Personally, I will probably always set it to TRUE when I get libraries from GitHub to avoid warnings!

PS: once upon a time, I wrote an article on how to avoid warnings in specific source files.

cmake Article's
30 articles in total
Favicon
Fixing libdc1394.so.22: cannot open shared object file (ใ… ๏นใ… )
Favicon
Automate Versioning with Git and CMake
Favicon
vcpkg - how to modify dependencies
Favicon
Getting started with GoogleTest and CMake
Favicon
Building a Desktop C++ Barcode Scanner with Slimmed-Down OpenCV and Webcam
Favicon
Use cosmocc to crossโ€compile a CMake project
Favicon
Improve Productivity with CMake and Compiler Cache Integration
Favicon
Conan: Your Embedded Cross-Compilation Champion
Favicon
Streamlining STM32 Projects: VS Code, CMake and clangd
Favicon
Easily add packages to CMake with CPM
Favicon
Jolt Physics raylib: trying 3D C++ Game Physics Engine
Favicon
Using raylib with Dear ImGui: Game Dev Debugging UI
Favicon
Using Jolt with flecs & Dear ImGui: Game Physics Introspection
Favicon
codemapper: join dev team of this sources analysis tool (C++/Qt5)
Favicon
CMake on SMT32 | Episode 8: build with Docker
Favicon
CMake on SMT32 | Episode 7: unit tests
Favicon
[04/52] MOAR CMAKEZ!
Favicon
How to use Flatbuffers in a C++ project with Conan?
Favicon
[03/52] - CMake and Git Submodules: More Advanced Cases
Favicon
get_cmake_version raise SKBuildError(msg) from err
Favicon
Basic C++ Unit Testing with GTest, CMake, and Submodules
Favicon
Felt Cute, Might git rm --rf
Favicon
Install CMake on Windows
Favicon
Maximizing Automation and Scripting in CMake for Efficient Software Development
Favicon
Include custom CMake modules
Favicon
Build a project on Windows 11 using MinGW
Favicon
Cleanup my dependency management with vcpkg
Favicon
CMake cheat sheet!
Favicon
CPM.cmake to make CMake's FetchContent easier
Favicon
The SYSTEM property from CMake 3.25

Featured ones: