Skip to main content

ABI compatibility checker for C/C++ shared libraries

Project description

abicheck

CI codecov PyPI version conda-forge Python versions License: Apache 2.0

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:

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

abicheck-0.2.0.tar.gz (640.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

abicheck-0.2.0-py3-none-any.whl (309.3 kB view details)

Uploaded Python 3

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

Hashes for abicheck-0.2.0.tar.gz
Algorithm Hash digest
SHA256 1e5940d165612e92b539df7ad2ece2149f7cf5d1b068f8d3cf6ee87ce8ff3c03
MD5 677e93402b088bce3db69406eb43ac28
BLAKE2b-256 fea967797028d1dcca476101e13041b58233d2f4f6dfe3e9291578e67c52224f

See more details on using hashes here.

Provenance

The following attestation bundles were made for abicheck-0.2.0.tar.gz:

Publisher: publish.yml on napetrov/abicheck

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for abicheck-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a0f43e2769386eac11b680e5ba7bcd1c7672273089f5c74aa980fc201c45cf8c
MD5 5a9580d6fb066d73ddfa27f24f2d2e21
BLAKE2b-256 f6d74c29b2c99be89fbd3dfd758266279c186780a7432288e3d416a01f6fdd5e

See more details on using hashes here.

Provenance

The following attestation bundles were made for abicheck-0.2.0-py3-none-any.whl:

Publisher: publish.yml on napetrov/abicheck

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page