On 8/06/2021 4:53 pm, Edward Diener wrote:
I do not know CMake, so maybe my comment is irrelevant, but it seems natural to me that a header-only library would always choose to use some other dependent library as header-only, even when that other library had static or shared variants. In other words I applaud the decision of Boost.Test to provide a header-only variant and can not even begin to process the fact that CMake can not deal with Boost.Test as a header-only library, if that is indeed the case.
A problem occurs when program P uses library A as static or shared and then wants to use header-only library B which also uses library A. For this to work, one of the following must be true: 1. library B can figure out how program P chose to link to it and links to it the exact same way. 2. library A is written such that in header-only mode it uses entirely separate namespaces from its compiled modes; then B can link to it in header-only mode without conflicting with other uses. #2 is rarely true, because it's more work for both users and maintainers (inline namespaces make it actually *feasible*, but still require people to actually have considered the problem in the first place). #1 is putting the cart before the horse, which can be problematic (but nevertheless, is the "solution" most often taken, by "bubbling down" settings from the parent projects) -- but it only works as long as everyone respects them and everything gets compiled with matching settings. (#1 also affect dependencies on the CRT itself, which is why most have big global hammers to specify whether linking to the CRT statically or dynamically, and why everything explodes when these settings don't match between compilation units.) When these conditions are not met, you end up with an ODR violation. Which often works anyway by coincidence, especially in libraries without singletons, but you're tap-dancing over a minefield. (And even doing #2 will land you with disjoint singleton "islands", but at least that way it's presumably deliberate.) (The safest way out of this minefield is to ensure that header-only libraries either have no separate dependencies, or at least only ever reference dependencies that do not have a compiled variant. This is of course a scaling problem.) TLDR: C++ is extremely ODR-prone and libraries are very fragile things.