Case 148: Header Build-Context Mismatch (Cross-Source Flagship)¶
| Field | Value |
|---|---|
| Verdict | 🟠 API_BREAK |
| Category | API Break |
| Classification | Scenario — Capability / evidence demonstration · audit |
| Platforms | Linux |
| Flags | API break |
Detected ChangeKinds |
header_build_context_mismatch |
| Source files | catalog/cases/case148_xcheck_header_build_mismatch/ |
| Related rules | header-build-context-mismatch |
| Subject | Export/declaration mismatches |
Category: API Break (Audit) | Verdict: 🟠 API_BREAK
Verdict and consumer impact¶
Single-release audit: one build's evidence checked against itself, no
baseline comparison. This finding's own kind is classified API_BREAK (the severity
ground-truth row above); the audit itself reports no compatibility
verdict and, by default, exits 0 — an audit has no baseline to break
against, so it never emits 2/4, the compatibility family's
own break codes. Gating on a hygiene finding like this one is opt-in via the
orthogonal audit-gate axis
:
adding --severity-preset default (or strict) reproduces legacy scan's
gating decision on this exact finding, but through its own exit code 3,
never 2, so a hygiene gate can't be mistaken for a real compatibility
break — measured live: abicheck compare --no-baseline snapshot.abi.json
exits 0, abicheck compare --no-baseline snapshot.abi.json
--severity-preset default exits 3. The finding: the public headers
were parsed without the build's actual ABI-relevant flags
(glibcxx_use_cxx11_abi, -DBIG_BUFFERS), so the layout a context-free
header parse reports is not the layout the shipped binary actually has. A
consumer who compiles against these headers with the project's documented
build flags gets a different struct layout than the header-only view
implied — silently, with no compiler warning, because nothing in the header
text or the binary alone says the parse context was wrong. Only cross-checking
the header's macro context against the build's real compile flags surfaces
the divergence.
What this snapshot contains¶
snapshot.abi.json is a single, hand-built AbiSnapshot for one build of
libdemo.so, carrying both the header-derived layout and the build's actual
compile context:
| Source in the snapshot | What it records |
|---|---|
| Public-header AST (L2, context-free parse) | a layout parsed without -DBIG_BUFFERS and without the project's glibcxx_use_cxx11_abi setting — reported with full confidence, and wrong |
Build config (L3, build_source.build_config / compile flags) |
the project actually compiles this TU with -DBIG_BUFFERS=1 and a pinned glibcxx_use_cxx11_abi value |
abicheck command¶
compare --no-baseline, not scan
0.6 makes this the declared spelling for a single-build audit, and
retires scan. This case was blocked on that migration until
2026-09-09; the audit now reports the finding below directly, and
tests/parity/test_no_baseline_audit_corpus_parity.py pins that it
reports at least every check scan does, counted per finding kind,
while manufacturing no comparison of its own (no verdict, no
changes[] entry).
Expected abicheck finding¶
# ABI audit: libdemo.so (no baseline)
OLD side: **declared absent** (`--no-baseline`) -- this is an audit of the candidate build alone, not a compatibility comparison. No additions, removals, or compatibility verdict are reported.
- Candidate version: `1.0`
- Acquisition state (OLD): `declared_absent`
- Evidence tiers: header
## Candidate-side findings
| Finding | Symbol | Severity | State | Detail |
| --- | --- | --- | --- | --- |
| `header_build_context_mismatch` | `-` | potential_breaking | present in this build | Public headers were parsed without the build's ABI-relevant context: the build records 2 ABI-affecting flag(s) (define:BIG_BUFFERS, glibcxx_use_cxx11_abi) but the header AST was captured context-free, so the declared API surface may not match the shipped translation units. Re-dump the headers with the build's compile_commands.json. |
Minimum evidence¶
min_evidence: L3 — the L2 header-AST layout alone is reported with full
confidence and no signal that anything is wrong; only the L3 build
config's actual compile flags give abicheck something to cross-check the
L2 macro context against. Without L3 evidence the check is skipped
outright (as seen on cases that lack it, e.g. case149's coverage line for
this same check), never a false clean.
Why abicheck catches it¶
| Source | What it sees alone |
|---|---|
| Binary (L0/L1) | a valid layout — blind to which macros produced it |
| Header AST (L2) | a layout parsed without -DBIG_BUFFERS → the wrong layout, reported with full confidence |
| Build flags (L3) | the project compiled the TU with -DBIG_BUFFERS=1 |
| Combination | L2 macros ↔ L3 flags disagree → header_build_context_mismatch (API_BREAK) |
header_build_context_mismatch is a cross-source check: abicheck compares
the macro/flag context the header AST was parsed under against the build
system's actual compile flags for that translation unit. Neither source
alone carries both halves of the fact — the header parse doesn't know what
the build actually used, and the build flags alone don't know what the
header parse assumed.
Why this matters for a real release¶
A context-free header parse is the common case for any ABI tool run without build integration — most CI pipelines run the header scan once, separately from the actual build. If that scan silently reports a layout that disagrees with what the compiler produces, every downstream layout-based finding (struct sizes, member offsets, vtable slots) inherits the error with full confidence and no warning. Catching the mismatch here means the project fixes its scan invocation (or its build) before a consumer trusts a wrong layout report.
Safe redesign¶
Parse the public headers with the same ABI-relevant flags the build uses —
feed abicheck the project's compile database (--sources/--build-info)
so the header AST is built under the real macro context, instead of a bare
-H include/ pass with no build integration.
Cross-tool comparison¶
header_build_context_mismatch is a cross-source check unique to
abicheck's audit mode — it reconciles the macro context a header parse
assumed against the build system's actual compile flags for the same
translation unit, which isn't something abidiff/abi-compliance-checker
do (they diff two ABI dumps against each other, not a single build's header
parse against its own build config).
Source files¶
snapshot.abi.json
See also: Compatibility Catalog · All API_BREAK cases · Category: API Break · Subject: Export/declaration mismatches.