cmakecmake-presets

How to specify CMake Preset for subdirectories?


I have a big library with a lot of options that I recently converted to CMake from make, with a lot of options. I use configuration presets to have multiple profiles. The library is developed by my team, while the applications building over it are developed by other teams. The library provides common functionalities and is a must to be consumed by the apps. We were seeking to provide sane default options via presets.

Right now, I want to build a toy app over it.

I have the following directory structure where a CMakePresets.json file is located in the subdirectory (my_lib/, which is actually a git submodule).

main.cpp
CMakeLists.txt // Top-Level CMakeLists
my_lib/
------> lib.c // simplified view of the functionalities here
------> lib.h
------> CMakeLists.txt
------> CMakePresets.json
# Top level CMakeLists.txt
project(toy_app)
add_subdirectory(my_complex_lib)

set(SOURCES main.cpp)
add_executable(toy_app ${SOURCES})
target_link_libraries(toy_app my_lib)

Running cmake --list-presets at the top level won't detect sub-directories presets.


The question is how to specify the preset from the top-level invocation or even provide a default one in the CMakelists inside the library?

Trial #1

I have found the idea of default preset was rejected ( https://gitlab.kitware.com/cmake/cmake/-/issues/21417 )

Trial #2

I tried to add CMakePresets.json at the top level and included the one inside my_lib and it worked.

Running cmake --list-presets on the top level can find presets right now.

I wonder if there are other solutions?


Solution

  • As you indicate in your question post "Trial #2", yes, you can include other json files following the CMakePresets.json schema into CMakePresets.json files. See the docs on includes for more info. Here's an example from the docs:

    {
      ...
      "include": [
        "otherThings.json",
        "moreThings.json"
      ],
      ...
    }
    

    So as you found out, you can keep your main CMakePresets.json file in the subdirectory and create another one in the project's root directory that includes the subdirectory one, or you can do it the other way around: Put your main one in the project's root directory and create one that just includes it in the subdirectory.

    This could be useful if you wanted to generate buildsystems for both the root directory and the subdirectory. I.e. you want your subdirectory's CMake config to be able to be used as a standalone project. In that case you might be making it a git submodule of the root project, or using a monorepo structure for the users of various parts of your project.

    If you're going with a git submodule, then you couldn't put a main CMakePresets.json file in the project's root directory and include it in the submodule because the submodule repo should stand alone without knowing about what uses it as a submodule. In that case, you could put the main CMakePresets.json in the repo that gets used as a submodule, or just make two "copies" of the same CMakePresets.json file- one for each repo.

    If you wanted to have a utility CMakePreset.json file with comon things used by multiple repos, you could create a repo with just that utility file and include that repo as a submodule to all your other repos and then use the CMakePresets.json's "include" mechanism to pull in those utility preset configurations into the repo's own CMakePresets.json file.