Cmake Top level project has two dependent projects, one child is also dependent on the other child

337 Views Asked by At

I have Project A at the top.

Project A requires library B and library C.

Library B also requires library C by itself.

So, in short. How can I link libraries B and C up to A by just linking B? I have it working now by individually linking all the libraries, but I feel like there is redundancy I could get rid of.

This is part of the CMAKE for Project A at the top:

find_package(libB REQUIRED)
include_directories(${libB_INCLUDE_DIR})
target_link_libraries(${PROJECT_NAME} ${libB_LIBRARY})

find_package(libC REQUIRED)
include_directories(${libC_INCLUDE_DIR})
target_link_libraries(${PROJECT_NAME} ${libC_LIBRARY})

But also within libB I have this in its CMAKE:

find_package(libC REQUIRED)
include_directories(${libC_INCLUDE_DIR})
target_link_libraries(${PROJECT_NAME} ${libC_LIBRARY})

I feel like there is a better way to do this, please let me know. Thank you for any help.

1

There are 1 best solutions below

2
YurkoFlisk On

You can use target_include_directories (documentation) to specify include directories for your target instead of specifying them for all targets of the current directory using include_directories. Among other things, this gives the ability to provide visibility specifiers to your includes dirs, which control whether your include dirs will affect only current target (PRIVATE), only those targets which link to your target (INTERFACE) or both (PUBLIC). The same specifiers are used similarly for target_link_libraries.

So, you can use PUBLIC to avoid duplicating your lib C includes and libraries, and since it is the default specifier, you can omit it. Then, parts of your CMakeLists may look like this:

In project A CMakeLists.txt:

find_package(libB REQUIRED)
target_include_directories(${PROJECT_NAME} ${libB_INCLUDE_DIR})
target_link_libraries(${PROJECT_NAME} ${libB_LIBRARY}) 

In lib B CMakeLists.txt:

find_package(libC REQUIRED)
target_include_directories(${PROJECT_NAME} ${libC_INCLUDE_DIR})
target_link_libraries(${PROJECT_NAME} ${libC_LIBRARY})

If you, e.g., want only lib B to link to lib C, but leave public 'inheritance' of include directories, you could change the last line of lib B CMakeLists.txt excerpt:

target_link_libraries(${PROJECT_NAME} PRIVATE ${libC_LIBRARY})