Search code examples
cmakebuild-system

Good CMake Style: Inherit Properties


Daniel Pfeifer, in his presentation "Effective CMake", makes a point, that it is advisable to avoid variable definitions as much as possible.

Now, how does one get properties into a variety of build targets. That is, for example

   target_include_directories(base_IncludeFlags
                              INTERFACE 
                              first/dir
                              second/dir
                              ...)

defines a set of include directories. Instead of defining the exact same include directories for target_a, target_b, and target_c, I would like to let those targets inherit the include directories from 'base_target', with something like

target_link_libraries(target_a PUBLIC base_IncludeFlags) 
target_link_libraries(target_b PUBLIC base_IncludeFlags)
target_link_libraries(target_c PUBLIC base_IncludeFlags)

where base_IncludeFlags is shall not be a real physical target, rather something like an abstract base class or interface.

On the other hand, I do not want to use include_directories since this affects all targets. Is it better to use foreach? What is the most elegant way to do this? Shall I make base_target a library and add dependencies?


Solution

  • What I want is a target that is not actually physically produced, but which propagates some common properties.

    Exactly for that purpose CMake has INTERFACE library - container for different properties, which are propagated when this library is linked into another target.

    Example:

    # Create "container" target
    add_library(base_target INTERFACE)
    
    # Add some INTERFACE properties for that target
    target_include_directories(base_target INTERFACE 
                              first/dir
                              second/dir)
    
    # Some 'other_target' (library or executable) may easily consume all common properties:
    target_link_libraries(other_target PUBLIC base_target)
    # Now 'other_target' has aforementioned include directories too.
    # Instead of PUBLIC other linking types (PRIVATE, INTERFACE) may be used.