ABI compatibility checker for C/C++ shared libraries
Project description
abicheck
abicheck is a command-line tool that detects breaking changes in C/C++ shared libraries before they reach production. It compares two versions of a shared library — along with their public headers — and reports whether existing binaries will continue to work or break at runtime.
Typical problems it catches: removed or renamed symbols, changed function signatures, struct layout drift, vtable reordering, enum value reassignment, and 114 other ABI/API incompatibilities that cause crashes, silent data corruption, or linker failures after a library upgrade.
Platforms: Linux (ELF), Windows (PE/COFF), macOS (Mach-O). Binary metadata and header AST analysis on all platforms; debug info cross-check uses DWARF (Linux, macOS) and PDB (Windows).
Installation
Install from PyPI:
pip install abicheck
Or with conda:
conda install -c conda-forge abicheck
Prerequisites
| Requirement | Notes |
|---|---|
| Python >= 3.10 | All platforms |
castxml |
Clang-based C/C++ AST parser for header analysis (all platforms) |
g++ or clang++ |
Must be accessible to castxml |
castxml and a C++ compiler are required for header AST analysis. Without them, abicheck still works in binary-only mode (exports, imports, dependencies).
Ubuntu / Debian:
sudo apt install castxml g++
macOS:
brew install castxml
conda (all platforms):
conda install -c conda-forge castxml
Install from source
git clone https://github.com/napetrov/abicheck.git
cd abicheck
Runtime only:
pip install -e .
With test and lint dependencies:
pip install -e ".[dev]"
Quick start
Compare two library versions
abicheck compare libfoo.so.1 libfoo.so.2 \
--old-header include/v1/foo.h --new-header include/v2/foo.h
Use -H when both versions share the same header:
abicheck compare libfoo.so.1 libfoo.so.2 -H include/foo.h
Save a baseline snapshot, then compare against new builds
abicheck dump libfoo.so -H include/foo.h --version 1.0 -o baseline.json
abicheck compare baseline.json ./build/libfoo.so --new-header include/foo.h
Output formats
Available formats: markdown (default), json, sarif, html.
abicheck compare old.so new.so -H foo.h --format json -o report.json
abicheck compare old.so new.so -H foo.h --format sarif -o report.sarif
abicheck compare old.so new.so -H foo.h --format html -o report.html
Check application compatibility
Check whether your application (not just the library) is affected by a library update. Unlike compare (which shows all library changes), appcompat filters the diff to show only changes that affect the symbols your application actually uses.
Full check — does my app break with the new libfoo?
abicheck appcompat ./myapp libfoo.so.1 libfoo.so.2 -H include/foo.h
Quick check — does this library have all symbols my app needs?
abicheck appcompat ./myapp --check-against libfoo.so.2
See Application Compatibility for full details.
Full-stack dependency validation (Linux ELF)
Check whether a binary will load and run correctly in a given environment by resolving its full dependency tree, simulating symbol binding, and detecting ABI-breaking changes across all loaded DSOs.
Show dependency tree and symbol binding status:
abicheck deps /usr/bin/python3
Compare a binary's full stack across two sysroots:
abicheck stack-check usr/bin/myapp \
--baseline /rootfs/v1 --candidate /rootfs/v2
Include dependency info in a regular compare:
abicheck compare old.so new.so -H foo.h --follow-deps
For the full CLI reference see the documentation.
Exit codes
Use these exit codes to gate CI pipelines. Non-zero exits can fail your build when breaking changes are detected.
compare / compare-release
| Exit code | Verdict | Meaning |
|---|---|---|
0 |
NO_CHANGE / COMPATIBLE / COMPATIBLE_WITH_RISK |
Safe — no binary ABI break |
1 |
SEVERITY_ERROR |
Severity-driven error (with --severity-* flags) |
2 |
API_BREAK |
Source-level break (recompile needed, binary may still work) |
4 |
BREAKING |
Binary ABI break (old binaries will crash or misbehave) |
8 |
REMOVED_LIBRARY |
Library removed in new version (compare-release only) |
stack-check
| Exit code | Verdict | Meaning |
|---|---|---|
0 |
PASS |
Binary loads and no harmful ABI changes |
1 |
WARN |
Binary loads but ABI risk in dependencies |
4 |
FAIL |
Load failure or ABI break in dependency stack |
appcompat
| Exit code | Verdict | Meaning |
|---|---|---|
0 |
COMPATIBLE |
App is not affected by the library change |
2 |
API_BREAK |
App uses changed API (recompile needed) |
4 |
BREAKING |
App will crash or misbehave with new library |
See the full exit code reference for CI gate patterns.
GitHub Action
Basic usage:
- uses: napetrov/abicheck@v1
with:
old-library: abi-baseline.json
new-library: build/libfoo.so
new-header: include/foo.h
With SARIF upload to GitHub Code Scanning:
- uses: napetrov/abicheck@v1
with:
old-library: abi-baseline.json
new-library: build/libfoo.so
new-header: include/foo.h
format: sarif
upload-sarif: true
Fail on both ABI and API breaks:
- uses: napetrov/abicheck@v1
with:
old-library: abi-baseline.json
new-library: build/libfoo.so
new-header: include/foo.h
fail-on-breaking: true
fail-on-api-break: true
Use the action's outputs to control downstream steps:
- uses: napetrov/abicheck@v1
id: abi
with:
old-library: abi-baseline.json
new-library: build/libfoo.so
new-header: include/foo.h
- run: echo "ABI verdict was ${{ steps.abi.outputs.verdict }}"
The action installs Python, castxml, and abicheck automatically. Available outputs: verdict, exit-code, report-path. See the full GitHub Action documentation for cross-compilation and matrix builds.
Policy profiles
Policies control how detected changes are classified. A change that is BREAKING under strict_abi might be downgraded to COMPATIBLE under sdk_vendor.
| Profile | Use case |
|---|---|
strict_abi (default) |
System libraries, public SDKs |
sdk_vendor |
Vendor SDKs, optional extensions |
plugin_abi |
Plugins rebuilt with host |
abicheck compare old.so new.so -H foo.h --policy sdk_vendor
Use a custom YAML policy file for per-kind verdict overrides:
abicheck compare old.so new.so -H foo.h --policy-file my-policy.yaml
See Policy Profiles for full details including YAML format.
Suppression files
Suppress known or intentional changes so they don't fail CI:
abicheck compare old.so new.so -H foo.h --suppress suppressions.yaml
Example suppressions.yaml:
version: 1
suppressions:
# Exact symbol match
- symbol: "_ZN3foo6Client10disconnectEv"
change_kind: "func_removed"
reason: "Client::disconnect() deprecated in v1.8, removed in v2.0"
# Pattern match — suppress all changes in internal namespaces
- symbol_pattern: ".*N6detail.*"
reason: "detail:: namespace is not part of public ABI"
# All change kinds for a symbol
- symbol: "_ZN3foo12LegacyHandleEv"
reason: "LegacyHandle replaced by Handle alias — shim keeps compat"
ABICC-format suppression files are also supported for easier migration. See Migrating from ABICC for details.
ABICC drop-in replacement
If you're migrating from abi-compliance-checker, abicheck provides a compatibility CLI:
Before (ABICC):
abi-compliance-checker -lib libfoo -old old.xml -new new.xml -report-path r.html
After (abicheck — same flags):
abicheck compat check -lib libfoo -old old.xml -new new.xml -report-path r.html
See Migrating from ABICC for the full migration guide.
Examples
The examples/ directory contains 63 real-world ABI scenarios — each with paired v1/v2 source code and a consumer app that demonstrates the actual failure.
Build an example:
cd examples
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build --target case01_symbol_removal_v1 case01_symbol_removal_v2 --config Debug
Run abicheck on it:
abicheck compare build/case01_symbol_removal/libv1.so build/case01_symbol_removal/libv2.so \
--old-header case01_symbol_removal/v1.h --new-header case01_symbol_removal/v2.h
Expected output verdict: BREAKING — symbol 'helper' was removed.
Covers: symbol removal, type/signature changes, struct layout, enums, vtables, qualifiers, templates, and more. See Breaking Cases Catalog and ABI Breaks Explained for the full guide.
Python API
abicheck can be used as a library for programmatic ABI checks:
from pathlib import Path
from abicheck.service import run_compare
result, old_snapshot, new_snapshot = run_compare(
old_input=Path("libfoo.so.1"),
new_input=Path("libfoo.so.2"),
old_headers=[Path("include/v1/foo.h")],
new_headers=[Path("include/v2/foo.h")],
)
print(result.verdict) # e.g. Verdict.BREAKING
print(len(result.changes)) # number of detected changes
run_compare also accepts optional parameters for includes, version labels, language ("c++" or "c"), suppression files, policy selection, and PDB paths. See abicheck.service for the full signature.
Documentation
Full documentation is available at napetrov.github.io/abicheck.
Getting started:
User guide:
- CLI Usage
- Application compatibility — check if your app breaks with a library update
- Policy profiles
- Output formats (SARIF, JSON, HTML)
- GitHub Action
- Migrating from ABICC
- MCP Integration
Concepts:
Reference:
Contributing
See CONTRIBUTING.md for setup instructions, testing, code style, and PR workflow.
License
Licensed under the Apache License, Version 2.0. See LICENSE and NOTICE.md.
Copyright 2026 Nikolay Petrov
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file abicheck-0.2.0.tar.gz.
File metadata
- Download URL: abicheck-0.2.0.tar.gz
- Upload date:
- Size: 640.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1e5940d165612e92b539df7ad2ece2149f7cf5d1b068f8d3cf6ee87ce8ff3c03
|
|
| MD5 |
677e93402b088bce3db69406eb43ac28
|
|
| BLAKE2b-256 |
fea967797028d1dcca476101e13041b58233d2f4f6dfe3e9291578e67c52224f
|
Provenance
The following attestation bundles were made for abicheck-0.2.0.tar.gz:
Publisher:
publish.yml on napetrov/abicheck
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
abicheck-0.2.0.tar.gz -
Subject digest:
1e5940d165612e92b539df7ad2ece2149f7cf5d1b068f8d3cf6ee87ce8ff3c03 - Sigstore transparency entry: 1154170680
- Sigstore integration time:
-
Permalink:
napetrov/abicheck@3c6208224774fa9abbb212019b73317c2593e68c -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/napetrov
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3c6208224774fa9abbb212019b73317c2593e68c -
Trigger Event:
release
-
Statement type:
File details
Details for the file abicheck-0.2.0-py3-none-any.whl.
File metadata
- Download URL: abicheck-0.2.0-py3-none-any.whl
- Upload date:
- Size: 309.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a0f43e2769386eac11b680e5ba7bcd1c7672273089f5c74aa980fc201c45cf8c
|
|
| MD5 |
5a9580d6fb066d73ddfa27f24f2d2e21
|
|
| BLAKE2b-256 |
f6d74c29b2c99be89fbd3dfd758266279c186780a7432288e3d416a01f6fdd5e
|
Provenance
The following attestation bundles were made for abicheck-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on napetrov/abicheck
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
abicheck-0.2.0-py3-none-any.whl -
Subject digest:
a0f43e2769386eac11b680e5ba7bcd1c7672273089f5c74aa980fc201c45cf8c - Sigstore transparency entry: 1154170682
- Sigstore integration time:
-
Permalink:
napetrov/abicheck@3c6208224774fa9abbb212019b73317c2593e68c -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/napetrov
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3c6208224774fa9abbb212019b73317c2593e68c -
Trigger Event:
release
-
Statement type: