abi = "c" names a boundary, not a languageStatus: Accepted
abi is merged with must_equal: the labels reaching a target must all be
the same string, and a difference is abi-mismatch before linking. The
purpose is stated in 13-semantics.md — turn a
would-be runtime ODR breakage into a build failure.
A C library and a C++ consumer, both written honestly, produce different labels:
# the library
[lib.hashx.public]
abi = "gnu11"
# the consumer, in its own language
[bin.hashcxx.private]
abi = "gnu++17"
The build is refused. It is not wrong about the strings; it is wrong about
what it is checking. An ODR violation is one entity in C++ having more than
one definition, and it does not arise across an extern "C" boundary: a C
function has no overloading, no templates, no inline instantiation, and no
name mangling. Both sides may be built by different languages and still
agree on everything that call actually depends on.
The workaround available today is worse than the failure. The consumer copies the library’s label:
abi = "gnu11" # not this program's ABI; the library's
Then it builds and runs. But the label has stopped describing an ABI and started naming “the set of things that use hashx”. A design that puts ABI checking at its center cannot afford labels that mean that (issue #78).
For the library author it is worse still. A library is written without knowing its consumers, so fixing one label forces it on every consumer. The asymmetry — the author does not know the language, the consumer wants to state its own — is what makes this show up when distributing a library and not when building a single tree, where the same person writes both sides and naturally makes the labels agree.
An ABI label may name a boundary instead of a language. One such label
exists: c.
[lib.hashx.public]
abi = "c" # this surface is the C ABI; the consumer's language is its own business
A c label is compatible with every label. In a must_equal merge over
abi:
c values do not participate in the comparisonc label, so a real constraint is never
hidden by onec, the result is cEverything else is unchanged. Two labels that both name a language must
still be equal, and the diagnostic is the same abi-mismatch.
The exemption belongs to the ABI label vocabulary, not to must_equal.
must_equal on any other property still means equality; c is a
distinguished value of Type::AbiLabel, which is the type the rule is being
applied to.
gnu11 on a
C++ target means that target really is gnu11, not that it uses a
particular libraryc never weakens a check it was not asked to weaken. It declines to add
a constraint; it does not remove one. A tree whose dependency declares
gnu11 still propagates gnu11 through a c surface, because that
constraint is real and reaching furtherabi = "c" is a claim about the headers, and nothing verifies
it. That is true of every label today — they are hand-written
(91-implementation-status.md) — but the
claim c makes is narrower and more checkable than a language label, and
is the natural thing for an IDL or a header scan to confirm latergnu11 for a C library would
reintroduce exactly this failure, so the distinction has to exist below
the label, not only in what an author typesabi-mismatch says nothing about c. Pointing a mismatched
pair at this label is a separate, easy change; it is deliberately not part
of this decision, which is about what the label system can express