Multiple targets, propagate options to libraries, circular dependencies

Hello. Ok, I’m a total newbee with CMake. I need a little help to point me into the right direction to go. I must solve several problems:

  1. I need to build to targets: Firmware and Bootloader. Both require different global build and link options. I understand that target_compile_options/definitions is the preferred way over add_compile_options/definitions. But I need to propagate the options/definitions to all components (libraries) built for the target. It seems that only the options are propagated to the dependant targets, not the oposite direction. Is there a way to build the libraries per target with the specific options?

  2. For several libraries I need to specify additional compiler switches (-freestanding). Can I add these switches in the main project CMakeLists.txt file, and for a specific target?

  3. One component is Operating System. The OS depends on headers/defines of adaptation layer (another component), but the adaptation layer depends on the headers of the OS. Actually there are more dependencies, like the adaptation component depends on additional components, etc. E.g I need to propagate the list of all include directories required by the adaptation layer back to the OS component, while the adaptation component needs to know the public include directories of the OS. The OS and the adaptation layer are defined in directories, each have its own CMakeLists.txt and project. How to solve the circular dependency?

The easies way that I can think of would be to use some global variables to propagate the options/include directories to the libraries, but I assume this is a way to hell.

I’ve made some progress and I’m able to build the entire FW now. I found out I can add libraries using target_link_libraries in sub-folders, which are first defined later in my main CML. With this technique I’m able to propagate the dependencies to the libraries. This does not solve the problem of different configuration for different targets.

I still however need to solve one major issue I have with cyclic dependencies and weak symbols. Explanation: generic interrupt handlers are defined as weak functions to be able to be overwritten by specific implementation.

I’m forced to create STATIC libraries because cmake complains about cyclic dependencies when using OBJECT libraries. The problem is that because of the static libraries the weak/strong symbols are not resolved correctly - e.g. the symbol is used from the first static library. I would need to use object library to for this purpose.

How to solve it?

I have many subfolders each building an static library now. These libraries are usually consumed by multiple other libraries and so on. Just for the purpose to propagate the include directories and to be able to build the final executable.

No, consuming a library does not change the library being consumed. That quickly gets into “unsolvable” graph theory questions and it also means the order that the graph is evaluated can change the results. You’ll need a target per configuration (whether it comes from a new target in the source or a different build tree for the same source tree).

Compilation usage requirements do not support being in a cycle (linking static libraries can be a cycle, but where the cycle is broken to linearize it is undefined).

Maybe OBJECT libraries can be part of a cycle. However, we prefer to deny things instead of leaving open unconsidered cases as it is an easier upgrade path. @brad.king?