When $<TARGET_PROPERTY:prop>
appears in INTERFACE_LINK_LIBRARIES
, it evaluates to the value of the property on the target whose transitive link closure is currently being computed. That can be a different value for every downstream consumer through an entire chain, but one might only set the property on a subset of the downstream targets (such as just the final executables)
Apparently,
U
can query theH_IMPL
property of the executable (with several layers in between?).
Yes.
Is there some similar mechanism by which
L1
andL2
could set a property up-stream?
No. Since usage requirements can be defined in terms of properties, allowing them to also set properties would create a computationally intractable problem.
You just need to make each executable’s decision about what board to use based on a property, rather than by what other libraries it links. Rather than setting H_IMPL
to L1
or L2
directly, define a logical BOARD
property, and link executables to an intermediate board selection interface instead of B1
or B2
directly:
add_library(H INTERFACE)
target_include_directories(H INTERFACE ...)
add_library(L1 STATIC l1.c)
target_link_libraries(L1 PRIVATE H)
add_library(L2 STATIC l2.c)
target_link_libraries(L2 PRIVATE H)
add_library(U STATIC u.c)
target_link_libraries(U PRIVATE H
"$<$<STREQUAL:$<TARGET_PROPERTY:BOARD>,Type1>:L1>"
"$<$<STREQUAL:$<TARGET_PROPERTY:BOARD>,Type2>:L2>"
)
add_library(B1 STATIC b1.c)
target_link_libraries(B1 PRIVATE L1)
add_library(B2 STATIC b2.c)
target_link_libraries(B2 PRIVATE L2)
# Executables link this and set their BOARD property to select a board type.
add_library(B INTERFACE)
target_link_libraries(B INTERFACE
"$<$<STREQUAL:$<TARGET_PROPERTY:BOARD>,Type1>:B1>"
"$<$<STREQUAL:$<TARGET_PROPERTY:BOARD>,Type2>:B2>"
)
add_library(M STATIC m.c)
target_link_libraries(M PRIVATE U)
add_executable(E1 e.c)
target_link_libraries(E1 PRIVATE M B)
set_property(TARGET E1 PROPERTY BOARD Type1)
add_executable(E2 e.c)
target_link_libraries(E2 PRIVATE M B)
set_property(TARGET E2 PROPERTY BOARD Type2)