Troubleshooting¶
Use this page when a run fails to start (setup/environment) or when results look surprising (false positive, false negative, or unexpected verdict).
0) Setup & environment failures¶
"castxml not found in PATH"¶
Header AST analysis requires castxml. pip install abicheck does not install it,
so any command that passes headers (--old-header / --new-header / -H) fails with
this error until castxml is on your PATH.
# Ubuntu / Debian
sudo apt-get install -y castxml gcc g++
# macOS
brew install castxml
# Windows (PowerShell, admin)
choco install castxml
# conda (any OS) — bundles castxml + compiler automatically
conda install -c conda-forge abicheck
No castxml and can't install it? Run binary-only mode by omitting the header flags — abicheck falls back to DWARF/symbols analysis (weaker, but catches symbol- and layout-level breaks):
"command not found: abicheck" or wrong tool runs¶
Some distros ship unrelated tools with similar names (abi-compliance-checker
wrappers in Debian devscripts, or abicheck in Fedora's libabigail-tools).
Confirm you're running this project:
If a different tool shadows it, invoke via the module form: python -m abicheck.
Header parsing fails or finds nothing¶
If castxml runs but reports parse errors or an empty surface, the inputs usually
don't match the build environment of the analyzed .so:
- Pass the same include dirs the library was built with:
-I include/ -I deps/include/. - Pass the same preprocessor macros:
--gcc-options "-DFEATURE_X=1 -DNDEBUG". - Best option: feed the real build flags from
compile_commands.jsonwith-p build/(see CLI Usage → Build-context capture). - For pure C libraries, add
--lang c(the default isc++).
castxml aborts in system headers (_Float32, __assume__)¶
castxml drives an internal Clang while emulating your host GCC. If that bundled Clang is older than your host gcc/glibc, parsing your library's headers can fail inside the system headers — before abicheck compares anything — with errors like:
unknown type name '_Float32'(also_Float64/_Float128) — glibc's sized-float types, understood by Clang ≥ 16.- a parse failure on the GCC 13+ libstdc++
__assume__attribute — understood by Clang ≥ 18.
The fix is a castxml built against a newer Clang — the recommended floor is
bundled Clang ≥ 18. The conda-forge castxml package bundles a recent Clang
and a matching compiler, which is the most reliable option:
abicheck detects this case and appends your detected castxml --version plus the
recommended floor to the error. As an alternative, point abicheck at a
clang-parsable toolchain/sysroot with --gcc-path / --sysroot. A
#ifdef __cplusplus extern "C" C header that fails only under --lang c should
be scanned without --lang c (castxml always parses in a C++-aware mode).
1) "Why did I get API_BREAK/BREAKING unexpectedly?"¶
Check header/binary mismatch first¶
- Are these the exact headers used to build the analyzed
.so? - Are required
-Dmacros the same as build time? - Is include search path the same as build environment?
If not, fix input parity and rerun.
2) "Why is verdict COMPATIBLE, but I expected NO_CHANGE?"¶
COMPATIBLE means real differences exist (new symbols, policy changes) but no binary break.
Run JSON output for detail:
abicheck compare old.json new.json --format json -o result.json
python3 -c "import json; r=json.load(open('result.json')); print(r['verdict']); print(len(r['changes']))"
3) "How does compat mode report API_BREAK?"¶
abicheck compat uses ABICC-style report text, but still returns exit code 2
for source-level API_BREAK conditions.
If you need an explicit API_BREAK verdict string in machine-readable output,
use abicheck compare --format json.
4) "Why are deep type changes not detected?"¶
Check if the binary has DWARF debug info:
# Check for embedded DWARF sections
readelf -S libfoo.so | grep -E "\.debug_info|\.zdebug_info" || echo "No DWARF sections"
# Check for externally linked split-debug files
readelf --debug-dump=links libfoo.so # shows .gnu_debuglink / .gnu_debugaltlink references
readelf --debug-dump=follow-links libfoo.so # follows the link and inspects linked debug-info
Without DWARF, Tier 3/4 checks are limited. Use debug builds (-g) for deeper analysis.
If the binary uses split debug (separate .debug file), the linked debug info is still
analysed automatically when --debug-dump=follow-links can resolve the path.
5) CI script says success but report shows changes¶
Remember: compare exit code 0 includes both NO_CHANGE and COMPATIBLE.
If you need exact policy, parse JSON verdict instead of checking $? == 0.
6) Still unsure?¶
Open an issue with:
- command line used
- tool version (abicheck --version)
- minimal header + .so pair
- JSON output (--format json)