I have two CMake application projects, with libraries they share in Git submodules. I include the libraries in the CMake applications using add_subdirectory() and target_link_libraries().
One application uses an RTOS; the other doesn’t (it’s “bare metal”). Some of the shared libraries need to know whether they are building for use with or without the RTOS, and adjust their target_sources() / target_compile_definitions() / target_link_libraries() accordingly. What is the proper modern CMake-esque way to do this?
Currently, the application w/ the RTOS does option(use_rtos "Build libraries with RTOS support" ON)
in the application CMakeLists.txt. This seems like a bad approach, since it sets a cache variable, which (if I understand correctly) is supposed to be override-able by the “user” (application developer at build time, without editing CMakeLists.txt).
I imagine I’d want to set() and check a “normal” (non-cache) variable, but there’s no bool type AFACT.
I think the option is perfectly what you need.
It defines a variable that you can use in your CMakeLists.txt to define the different behaviours your project needs.
The developer can then set the use_rtos to ON or OFF on either the command line, or in his/her IDE. If they don’t provide any value the default given in the option is set. They should not change the cmakelists.txt. In the contrary, that won’t even work because the first time cmake runs it will cache the option and changing it then is only picked up if you clear the cache (but clearing is not necessary if the variable is set from command line or toolchain file).
I believe what you also need are CMakePresets. There you can define the two builds all the configurations/variables that go along with it. The CMakePresets can be used to set the option depending on the preset. A toolchain file can be used to define certain paths differently.
The combination of toolchain and presets should help you direct the configuration phase of cmake appropriately.
As for you question on the cmake way for handling different platforms: Presets is the general answer and toolchains if your are cross compiling.
PS, See https://cmake.org/cmake/help/latest/command/if.html#constant for all the variables that are considered as ‘true’ (wether used from option or from set. I think in this case you need to consider CMake as a soft typed language. the ‘BOOL’ in set(var val CACHE BOOL) is only a hint for cmake-gui and ccmake and not actually used in cmake itself.
Let me clarify: I have two applications, let’s call them app_rtos and app_bare_metal. Both of them have lib1 as a Git submodule, so they each get their own copy of the library source. use_rtos is (and should be) defined in each application’s CMakeLists.txt, such that it is visible to both the application’s and lib1’s CMake configurations.
Ah, this is most helpful, thanks. I think I’ll set(use_rtos TRUE) in app_rtos/CMakeLists.txt, and set(use_rtos FALSE) in app_bare_metal/CMakeLists.txt. Reasoning explained below.
This is part of what was throwing me off. It appears that there is more robust typing for the cache vars than normal vars.
use_rtos should actually not be changeable in these ways, within either application.
I am in fact using CMakePresets and toolchain.cmake (gcc arm none eabi). But again, that is IMO undesirable flexibility in this instance. use_rtos should not be in CMakePresets.json, since “the developer” should not be changing it within the application, regardless of the selected preset.