Including headers from library within same project

Hello *,

I have a project where I am building one application and a bunch of (mostly shared) libraries; the application is set up with project(myapp C CXX) and the libraries are set up with add_library(mod_plugin1 MODULE myplugin1.cpp) or add_library(mod_plugin2 STATIC myplugin2.cpp). All of the libaries reside in subdirectories with their own CMakeLists.txt which are then included by add_subdirectory.

There are several libraries and I do/will not know which of them are present as users may choose freely which ones to compile.

So far, this is all fine and works.

Today, it became clear that one specific, statically linked library (let’s call it “mod_utils”) is needed by some of the other libraries as well. So I added to the depending libraries (f.e. mod_plugin1):

    target_link_libraries(mod_plugin1
            mod_utils
    )

This works, but I don’t have access to the libraries header files during compilation of mod_plugin1.

I didn’t find a good solution to that; currently there is a global variable set in the root CMakeLists.txt that holds the include path for mod_utils and add that variable to target_include_directories:

target_include_system_directories(mod_plugin1
            # ...
            ${mod_utils_inc_path}
    )

This variable can’t be set in mod_utils’ CMakeListst.txt though, since I can not control the order or execution in CMake.

Since this solution does require a change of the main CMakeLists.txt: is there a better way to keep this modular? I looked into mod_plugin1_SOURCE_DIR but that’s only available for projects, not for libraries.

Thanks
Sebastian

This is a prime use case for CMake’s usage requirements feature. When you define settings (such as include directories, compilation options, etc.) for a library, you can specify where they apply:

  • Apply only when building the library itself (use keyword PRIVATE)
  • Apply only to consumers of the library, i.e. those who link against the library (use keyword INTERFACE)
  • Apply to both the library and its consumers (use keyword PUBLIC)

In your case, it would look like this:

CMakeList defining mod_utils:

add_library(mod_utils STATIC ...)
target_include_directories(mod_utils PUBLIC wherever/includes/are)

Using PUBLIC will ensure that the include directory applies both to the library mod_utils and to all who link against it.

CMakeList defining mod_plugin1:

add_library(mod_plugin1 MODULE ...)
target_link_libraries(mod_plugin1
  mod_utils
)

Nothing more needs to be done here, the usage requirements will be propagated by CMake automatically.

Oh … ooooooooh! I completely forgot about the possibility to use PUBLIC in target_include_directories! That makes things so much easier and cleaner … :slight_smile:

Thanks a lot,
Sebastian