Properties for compilation shall be propagated transitively. (eg. target_include_directories(PUBLIC/INTERFACE)
Libraries shall be specified as add_library(SHARED).
The linker shall use directly specified library targets.
add_library(A SHARED)
target_compile_definitions(A PUBLIC FOO)
add_library(B SHARED)
target_compile_definitions(B PUBLIC BAR)
target_link_libraries(B PUBLIC A)
add_library(C SHARED)
target_compile_definitions(C PUBLIC HOGE)
target_link_libraries(C PUBLIC B)
add_executable(X)
target_link_libraries(X PRIVATE A C)
I will see each definition below in compilation;
A: -DFOO
B: -DFOO-DBAR
C: -DFOO-DBAR-DHOGE
X: Same as C
This is expected and desirable to my use.
OTOH, I will see libraries in each linker command line below;
A: (none)
B: A
C: BA
X: CBA
I would like to enforce link libraries as directly depends by target_link_libraries.
A: (none)
B: A
C: B (excludes A)
X: CA (excludes B)
To enforce direct depends, I could specify PRIVATE for each target_link_libraries. But it prevents transitive target_compile_definitions, like;
A: -DFOO
B: -DFOO-DBAR
C: -DBAR-DHOGE (A’s -DFOO is invisible)
X: -DFOO-DHOGE (B’s -DBAR is invisible)
Can I make compatible “target_compile_definitions is propagated transitively but linking shall use direct depends only”?
The upcoming COMPILE_ONLY generator expression for CMake 3.27 should simplify this.
You would have something like:
add_library(A SHARED)
target_compile_definitions(A PUBLIC FOO)
add_library(B SHARED)
target_compile_definitions(B PUBLIC BAR)
target_link_libraries(B PUBLIC $<COMPILE_ONLY:A> PRIVATE A)
add_library(C SHARED)
target_compile_definitions(C PUBLIC HOGE)
target_link_libraries(C PUBLIC $<COMPILE_ONLY:B> PRIVATE B)
add_executable(X)
target_link_libraries(X PRIVATE A C)
This assumes every library should have its interface library. I think it would be intrusive a bit. Even if the genex to prune undefined libs for each target_link_libraries would be introduced, I also think the latter solution would be less intrusive.
Although I haven’t tried master, I expect it would work.
I have confirmed $<COMPILE_ONLY> could be emulated with like target_link_libraries(B INTERFACE $<IF:$<BOOL:$<LINK_ONLY:1>>,,A>)
As consistency to CMAKE_LINK_WHAT_YOU_USE, I think introducing an option might be introduced like CMAKE_LINK_ONLY_DIRECT_USE.