In my point of view, a static lib should always links PUBLIC ly to its dependencies, and a shared lib should link PRIVATE ly to its dependencies. For executables, PUBLIC and PRIVATE have no difference, because no targets can link to a executable.
Hi IMHO, I partially agree for the executable part but not for the library one.
First of all it does not depend on the shared/static status.
Let say a lib A depends on a lib B.
If the headers of A that may be included by an application that links A contains symbols from B then target_link_libraries(A PUBLIC B)
otherwise target_link_libraries(A PRIVATE B)
another situation may arise: B symbols are only present in A headers but are not used for A sources.
then target_link_libraries(A INTERFACE B)
for applications I agree that PUBLIC or PRIVATE should not make a difference, yet its cleaner then to use PRIVATE.
I sum up it in the following way (for target_compile_definitions and target_link_libraries): PRIVATE: the target uses the definition/dependency only to be build, not its clients PUBLIC: the target uses the definition/dependency when it is built, its clients also use it INTERFACE: the target does not uses the definition/dependency when it is built, but its clients use it
Not quite. Shared libraries can also link publicly when their header files expose e.g types from the linked library.
For executables, the only use case I know is that loadable modules may link to it on some platforms.
NB there is a scenario that may be confusing:
A uses B privately (no trace of B in its API)
an application C uses A and B
it would be tempting to target_link_libraries(A PUBLIC B) and target_link_libraries(C PRIVATE A) but it would be wrong even if it would work I think.
I would go for: target_link_libraries(A PRIVATE B) target_link_libraries(C PRIVATE A) target_link_libraries(C PRIVATE B)
which describes exactly the nature of the dependencies
As for target_include_directories, it depends on the target nature.
for headers only libraries, I would use INTERFACE for the INSTALL_INTERFACE
For other libraries, I would put headers that may be include by third-party target in a different directory than the one used only by the target.
The first one will be declared PUBLIC for the BUILD_INTERFACE and INSTALL_INTERFACE.
For applications, I would declare only PRIVATE for the BUILD_INTERFACE and INSTALL_INTERFACE.