Consecutive target_link_libraries with and without PUBLIC

cmake requires consecutive target_link_libraries invocations to use same syntax. E.g. the following will not work;

target_link_libraries(target PUBLIC A)
target_link_libraries(target B)

Any way to get around that?

target_link_libraries(target PUBLIC A)
target_link_libraries(target PRIVATE B)

You may not know that whether PUBLIC/PRIVATE was used, they may be called from different contexts.

Consider the following;

function(my_add_library library)
   add_library(${library} ${ARGN})
   target_link_libraries(${library} PRIVATE C)
endfunction()

my_add_library(A ...)
target_link_libraries(A B)

But I assume you always know how you want to link B, right? Or are you in a situation where you’re trying to express “link B into target with the same visibility with which A was linked into it”? That would be a very unusual requirement, I’d say.

Note that mixing visibilities is perfectly fine, even in the same command:

target_link_libraries(target PUBLIC A PRIVATE B C PUBLIC D)

target_link_libraries must have a default if PUBLIC/PRIVATE is omitted. Still the following fails.

target_link_libraries(target PUBLIC A)
target_link_libraries(target B)

Does not make sense.

Yes, it has such a default, for when PUBLIC/PRIVATE is omitted always. However, once you use such a keyword in one invocation, you have to use it in all of them.

The way to think about it is to consider target_link_libraries() to have two distinct modes of operation: plain one, and keyword-based one. You can use it just fine in either mode, but you cannot mix modes for the same consuming target.