FWIW, the most common biting issue is when mixing static/shared.
All-static and all-shared are usually pretty safe.
But when libraries A and B both use dependency C, and either of A and B is shared, then C must be shared as well -- things will often break horribly if C is static.
(Having said that, what actually happens is highly dependent on whether using Windows or something UNIXy, and for the latter what symbol visibility level is being used. And for some libraries and some platforms/settings then there will be no apparent problems.)
But this sort of thing is usually why tools like CMake prefer to offer global settings to configure static/shared rather than letting it be configured on a target-by-target basis. You *can* override that, but it is at your own peril. (Or that of the downstream app.)
A header-only library cannot *link* to anything, or it is not
Yes, that is why I think providing foo::shared and foo::static is usually(!) an anti-pattern. You should just have foo (i.e. Boost::foo) and let CMake decide what that should be based on BUILD_SHARED (the one variable whose naming is bad) Of course this still allows to build your Boost::foo explicitely as static or shared in which case the problem is also avoided as then only one version of it exists anyway. header-only. Depends on what you mean by "link". In CMake-terms this includes "depends on", which IMO is correct. So e.g. a header-only threading library will depend on pthreads, so it will link to pthreads. Of course you could omit linking to pthread at the cost of the user having to find out on what this "header-only" library depends on and having to link all those manually.