Frederic Simonis
Frederic Simonis

Reputation: 21

How to manage private dependecies of library with unit tests target in modern target based cmake

I have a library A with public and private dependencies. The unit tests are contained in a separate executable ATests which requires to link against both the private and the public dependencies of A.

Currently, I explicitly link all private dependencies of A to the unit tests ATest. This results in a lot of code duplication which becomes increasingly difficult to understand/maintain.

add_library(A)
target_link_libraries(A PUBLIC Pub1 PRIVATE Priv1 Priv2)

add_executable(ATests)
target_link_libraries(ATests PRIVATE A Priv1 Priv2)

I thought about creating a separate interface library APrivDeps for the private dependencies of A, however, this looks like a hack. I have serious doubts that this is portable and will mess up the static linking due to the link dependency propagation. (I would have to export the helper library APrivDeps.)

add_library(APrivDeps)
target_link_libraries(APrivDeps PUBLIC Priv1 Priv2)

add_library(A)
target_link_libraries(A PUBLIC Pub1 PRIVATE ADeps)

add_executable(ATests)
target_link_libraries(ATests PRIVATE A ADeps)

I expect some method that keeps the configuration short and free of code duplication while still following the target based principle of modern CMake.

Upvotes: 1

Views: 295

Answers (1)

Frank Miller
Frank Miller

Reputation: 41

It is possible to explicitly propagate private dependencies. One way to do this is with the TARGET_PROPERTY generator expression.

add_library(A)
target_link_libraries(A PUBLIC Pub1 PRIVATE Priv1 Priv2)

add_executable(ATests)
target_link_libraries(ATests PRIVATE A $<TARGET_PROPERTY:A,LINK_LIBRARIES>)

It may also be necessary to propagate other properties like INCLUDE_DIRECTORIES, COMPILE_OPTIONS, and so on. This does feel a bit like breaking the target based principle of modern CMake so use judiciously. To me it seems to be a reasonable approach for unit tests.

Upvotes: 1

Related Questions