How $<LINK_ONLY:...> really works?

I need to understand this $<LINK_ONLY:...> genex in INTERFACE_LINK_LIBRARIES in the package config file.

I don’t understand what is written in the documentation.

Content of …, except while collecting Transitive Usage Requirements, in which case it is the empty string.

Imagine a project with CoreLib and SomeExe that depends on this CoreLib and the CoreLib depends on MySQL::MySQL (MySQL client library).

CoreLib contains:

target_link_libraries(CoreLib PRIVATE/PUBLIC/INTERFACE MySQL::MySQL)

I have observed if I do the static build (BUILD_SHARED_LIB=OFF) and target_link_libraries() is PRIVATE then:

INTERFACE_LINK_LIBRARIES \$<LINK_ONLY:MySQL::MySQL>

If I do the shared build (BUILD_SHARED_LIB=ON) and target_link_libraries() is PRIVATE then INTERFACE_LINK_LIBRARIES of course doesn’t contain the MySQL::MySQL dependency (this is clear).

In all other cases (PUBLIC/INTERFACE and shared/static builds) it behaves normally (standard behavior; this is also clear):

INTERFACE_LINK_LIBRARIES MySQL::MySQL

So this special behavior is only applied for static builds when the dependency is PRIVATE.

What it means? Is this dependency propagated in this case? (static PRIVATE) I don’t get it.

Thx for advice.

Static libraries don’t really have a link phase. Very cruedly they are just an archive of object files that will be propagated to a real link line ( creation of a shared library or executable ).

So in your case you have stated a static library requires mysql, since you are static library that means the consumer of your static library needs to link against mysql ( since you don’t have a link line ).

Now since you have said PRIVATE linking that means you didn’t want compiler includes, defines, options, etc that are part of the MySQL::MySQL target to be propagated. To make this requirement true while propagating the MySQL::MySQL target as a dependency we wrap it in $<LINK_ONLY>. Therefore consumers of your static library satisify the requirements of static libraries and dependencies, but aren’t impacted by other transitive properties as requested by PRIVATE.

So that means that the MySQL::MySQL dependency will be propagated down to the SomeExe during exe linking? Of course without includes, defines, options, etc. but only for static builds and only if the target_link_libraries() was PRIVATE.

I understand what you are writing but it’s complex.

That is correct.

So the end goal is to always create a correct build or executable. The implementation details of static libraries require CMake to punch through the PRIVATE keyword and pass specific things to ensure we don’t end up with link errors.