Case 103: Toolchain Flag Drift¶
| Field | Value |
|---|---|
| Verdict | ๐ข COMPATIBLE |
| Category | Quality (Compatible) |
| Platforms | Linux |
| Flags | Bad practice |
Detected ChangeKinds |
toolchain_flag_drift |
| Source files | examples/case103_toolchain_flag_drift/ |
Category: Build quality signal | Verdict: โ COMPATIBLE
Verdict and consumer impact¶
The public API and every exported symbol are byte-identical between v1
and v2 โ the source files themselves don't differ at all. The only change
is the compiler flag set used to build the shared library: v2 adds
-fshort-enums. In this minimal fixture there are no enums, so nothing in
the symbol table or type layout actually changes and no consumer is
affected today. The finding exists because flag drift is a leading
indicator: the same drift applied to a library that does expose enums,
packed structs, or a different data model would silently change layout
without any source diff to review.
Old/new diff¶
Source is identical; only the build command differs:
gcc -shared -fPIC -g -fvisibility=default -o libv1.so v1.c
-gcc -shared -fPIC -g -fvisibility=default -o libv2.so v2.c
+gcc -shared -fPIC -g -fvisibility=default -fshort-enums -o libv2.so v2.c
abicheck command¶
gcc -shared -fPIC -g -fvisibility=default -o libv1.so v1.c
gcc -shared -fPIC -g -fvisibility=default -fshort-enums -o libv2.so v2.c
abicheck compare libv1.so libv2.so
Expected abicheck finding¶
Verdict: COMPATIBLE (exit 0)
## Quality Issues
- toolchain_flag_drift: ABI-affecting compiler flags changed: added: -fshort-enums
## Environment & Toolchain Drift
- toolchain_flag_drift: ABI-affecting compiler flags changed: added: -fshort-enums
Minimum evidence¶
min_evidence: L1 โ the flag set is read from DWARF's DW_AT_producer
string (GCC embeds its full command-line switches there by default); no
public headers are required. GCC-specific caveat: clang does not embed
command-line flags in DW_AT_producer unless built with
-grecord-command-line, so a default-clang build of this exact fixture
would return NO_CHANGE for the flag drift โ the underlying source/ABI
extraction gap is proven end-to-end by
tests/test_compiler_record_cross_toolchain.py::test_clang_grecord_command_line_flag_drift_detected.
This example is built with GCC deliberately, matching the case's own
PLATFORMS linux / GCC-only scope.
Why abicheck catches it¶
abicheck parses DW_AT_producer from each binary's DWARF debug info and
extracts the ABI-relevant flags it recognizes (-fshort-enums,
-fpack-struct, -fno-common/-fcommon, -m32/-m64, -mabi=,
-fabi-version=, -D_GLIBCXX_USE_CXX11_ABI=, among others), unioned
across all compile units so a flag applied to only some translation units
is not missed. When the extracted flag sets differ between the two
versions it emits toolchain_flag_drift โ a compatible, informational
signal, not a hard break, since nothing observable actually changed in
this binary.
Runtime failure demonstration¶
This case is COMPATIBLE, not a hard break โ there is no crash to
demonstrate. Verified directly: the consumer app behaves identically
whether linked against libv1.so or hot-swapped to libv2.so (no
recompile):
gcc app.c -I. -L. -lv1 -Wl,-rpath,. -o app
./app # โ 5 8.000000
cp libv2.so libv1.so # swap in the v2 build
./app # โ 5 8.000000 (identical output)
No observable effect on existing binaries in this minimal fixture โ the signal is a leading indicator for what happens once the two builds' ABI-affecting flags actually diverge over a type the flag touches.
Safe redesign¶
Build every translation unit of a published library โ and every consumer that shares its ABI surface โ with the same ABI-affecting flag set. Pin the flags in the build system (not just compiler defaults) and treat any detected drift as a release-blocking review item rather than assuming it is harmless because a given snapshot happens not to expose an affected type.
Real-world example: -fshort-enums, -fpack-struct, and the
libstdc++ dual-ABI macro (case 104) are exactly the class of flag that is
invisible in a source diff or a symbol-table diff, yet silently changes
struct/enum layout the moment a consumer's build picks up a slightly
different toolchain default (e.g. an embedded/ARM target where
-fshort-enums is sometimes the platform default).
Cross-tool comparison¶
abidiff/abi-compliance-checker compare binary artifacts and don't read
DW_AT_producer as a distinct ABI-affecting-flags signal โ this
compiler-driven-drift class of finding is unique to abicheck's DWARF
parsing. Not re-verified in this environment (abidiff is not installed
here).
References¶
Source files¶
CMakeLists.txtapp.cv1.cv1.hv2.cv2.h
See also: Examples overview ยท All COMPATIBLE cases ยท Category: Quality (Compatible).