Skip to content

Getting Started

abicheck compares two versions of a C/C++ shared library and tells you whether existing binaries will break. It supports ELF (Linux), PE/COFF (Windows), and Mach-O (macOS) binaries.

On all platforms it provides binary metadata analysis (exports, imports, dependencies) and header AST analysis (via castxml). Debug info cross-check uses DWARF (Linux, macOS) and PDB (Windows).

Platforms: Linux, Windows, macOS.


Which command do I need?

abicheck ships several commands. Pick the one that matches your question:

Your question Command See
Does upgrading this library break existing consumers? abicheck compare §2 below
Does my application still work with the new library version? abicheck appcompat §5 below
Will this binary load and run correctly in this sysroot? abicheck stack-check CLI Usage
Does my library dependency tree resolve without unresolved symbols? abicheck deps CLI Usage
I'm migrating from abi-compliance-checker and want the same flags. abicheck compat Migrating from ABICC
Save a reusable ABI baseline for CI. abicheck dump §4 below

If you're unsure, start with abicheck compare — it's the default workflow.


1) Install abicheck

pip install abicheck
# or
conda install -c conda-forge abicheck

Requirements

  • Python 3.10+
  • castxml + C/C++ compiler — for header AST analysis (optional but recommended, all platforms)

All Python dependencies (pyelftools, pefile, macholib) come with abicheck install. Without castxml, abicheck still works in binary-only mode.

Option A: system packages

# Ubuntu / Debian
sudo apt-get update && sudo apt-get install -y castxml gcc g++
# macOS
brew install castxml
# plus Xcode Command Line Tools for clang
# create env and install abicheck (recipe includes required analysis deps)
# Python >= 3.10 is required; any supported version works
conda create -n abicheck -c conda-forge python=3.12 abicheck
conda activate abicheck

No extra manual dependency installation is required when using the conda-forge package.

Install from source

git clone https://github.com/napetrov/abicheck.git
cd abicheck
pip install -e .

2) First check (using repo examples)

The repo includes 74 ABI scenario examples with paired v1/v2 sources and headers. Browse them in the Examples & Case Encyclopedia, or pick one and run it locally:

cd examples/case01_symbol_removal
# Build v1 and v2 shared libraries
gcc -shared -fPIC -g v1.c -o libv1.so
gcc -shared -fPIC -g v2.c -o libv2.so
# Compare
abicheck compare libv1.so libv2.so --old-header v1.h --new-header v2.h
# Verdict: BREAKING (symbol 'helper' was removed)

For your own library:

abicheck compare libfoo.so.1 libfoo.so.2 \
  --old-header include/v1/foo.h --new-header include/v2/foo.h

If the header is the same for both versions:

abicheck compare libfoo.so.1 libfoo.so.2 -H include/foo.h

You can also pass a header directory (recursive scan for *.h, *.hpp, ...):

abicheck compare libfoo.so.1 libfoo.so.2 -H include/

If no headers are provided for ELF inputs, abicheck falls back to symbols-only mode and prints a warning (weaker analysis: may miss type/signature ABI breaks).


3) Output formats

abicheck supports four output formats: markdown (default), json, sarif, html.

Markdown (default, printed to stdout):

abicheck compare libfoo.so.1 libfoo.so.2 -H foo.h

JSON — machine-readable, includes precise verdict field:

abicheck compare libfoo.so.1 libfoo.so.2 -H foo.h --format json -o result.json

SARIF — for GitHub Code Scanning:

abicheck compare libfoo.so.1 libfoo.so.2 -H foo.h --format sarif -o abi.sarif

HTML — standalone human-readable report:

abicheck compare libfoo.so.1 libfoo.so.2 -H foo.h --format html -o report.html

4) Snapshot workflow (for CI baselines)

Save a snapshot once per release, then compare against new builds without re-dumping:

# Save baseline (header is baked into the snapshot)
abicheck dump libfoo.so -H include/foo.h --version 1.0 -o baseline.json
# Compare saved baseline against current build
abicheck compare baseline.json ./build/libfoo.so \
  --new-header include/foo.h --new-version 2.0-dev
# Or compare two snapshots (no headers needed — already baked in)
abicheck compare old.json new.json

compare auto-detects each input: .so files are dumped on-the-fly, .json snapshots are loaded directly. You can mix them freely.

Language mode

Use --lang c for pure C libraries (default is c++):

abicheck dump libfoo.so -H foo.h --lang c -o snap.json

Cross-compilation

When analysing libraries built for a different architecture:

abicheck dump libfoo.so -H include/foo.h \
  --gcc-prefix aarch64-linux-gnu- \
  --sysroot /opt/sysroots/aarch64 \
  -o snap.json

Available flags: --gcc-path, --gcc-prefix, --gcc-options, --sysroot, --nostdinc.

Verbose output

abicheck compare old.json new.json -v

5) Application compatibility check

Check whether your application is affected by a library update — filtering out irrelevant changes:

abicheck appcompat ./myapp libfoo.so.1 libfoo.so.2 -H include/foo.h

This parses your application binary to find which library symbols it actually uses, then shows only the changes that matter. If the library removed a function your app never calls, it won't appear in the report.

Quick symbol availability check (no old library needed):

abicheck appcompat ./myapp --check-against libfoo.so.2

See Application Compatibility for the full reference.


6) Exit codes and CI

Exit code Verdict Meaning
0 NO_CHANGE / COMPATIBLE / COMPATIBLE_WITH_RISK Safe — no binary ABI break
1 Tool/runtime error
2 API_BREAK Source-level API break (binary still works)
4 BREAKING Binary ABI break

Full reference (including compat mode): Exit Codes

GitHub Actions example

Save a baseline once at release time, then compare every new build:

# Release step — save baseline as an artifact
abicheck dump ./build/libfoo.so -H include/foo.h \
  --version 1.0 -o abi-baseline.json
# Upload abi-baseline.json as a release artifact
# CI step — compare new build against saved baseline
steps:
  - name: Download ABI baseline
    uses: actions/download-artifact@v4
    with:
      name: abi-baseline

  - name: Compare ABI
    run: |
      abicheck compare abi-baseline.json ./build/libfoo.so \
        --new-header include/foo.h \
        --format sarif -o abi.sarif

  - uses: github/codeql-action/upload-sarif@v3
    if: always()
    with:
      sarif_file: abi.sarif

Next steps