From: Gavin Lambert (boost_at_[hidden])
Date: 2021-06-08 07:33:28
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.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk