Metadata-Version: 2.1
Name: abicheck
Version: 0.5.0
Summary: ABI compatibility checker for C/C++ shared libraries
Author-email: Nikolay Petrov <sfasp.post@gmail.com>
License: Apache-2.0
Project-URL: Repository, https://github.com/abicheck/abicheck
Project-URL: Documentation, https://abicheck.github.io/abicheck/
Project-URL: Bug Tracker, https://github.com/abicheck/abicheck/issues
Project-URL: Changelog, https://github.com/abicheck/abicheck/blob/main/CHANGELOG.md
Keywords: abi,api,compatibility,checker,shared-library,elf,pe,macho,dwarf,castxml
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: MacOS
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: click >=8.0
Requires-Dist: rich-click >=1.7
Requires-Dist: pyyaml >=6.0
Requires-Dist: defusedxml >=0.7.1
Requires-Dist: pyelftools >=0.29
Requires-Dist: packaging >=21.0
Requires-Dist: pefile >=2023.2.7
Requires-Dist: macholib >=1.16
Provides-Extra: dev
Requires-Dist: pytest >=7.0 ; extra == 'dev'
Requires-Dist: pytest-cov ; extra == 'dev'
Requires-Dist: pytest-xdist >=3.0 ; extra == 'dev'
Requires-Dist: filelock >=3.0 ; extra == 'dev'
Requires-Dist: hypothesis >=6.0 ; extra == 'dev'
Requires-Dist: ruff >=0.3 ; extra == 'dev'
Requires-Dist: mypy ==1.19.1 ; extra == 'dev'
Requires-Dist: types-PyYAML ; extra == 'dev'
Requires-Dist: jsonschema >=4.0 ; extra == 'dev'
Provides-Extra: mcp
Requires-Dist: mcp[cli] >=1.2.0 ; extra == 'mcp'
Provides-Extra: validation
Requires-Dist: zstandard >=0.21 ; extra == 'validation'

# abicheck

[![CI](https://github.com/abicheck/abicheck/actions/workflows/ci.yml/badge.svg)](https://github.com/abicheck/abicheck/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/abicheck/abicheck/branch/main/graph/badge.svg)](https://codecov.io/gh/abicheck/abicheck)
[![PyPI version](https://img.shields.io/pypi/v/abicheck.svg)](https://pypi.org/project/abicheck/)
[![conda-forge](https://img.shields.io/conda/vn/conda-forge/abicheck.svg)](https://anaconda.org/conda-forge/abicheck)
[![Python versions](https://img.shields.io/pypi/pyversions/abicheck.svg)](https://pypi.org/project/abicheck/)
[![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)

**abicheck** combines binary, debug, header, build, and (optionally) source evidence to detect the widest practical set of mechanical C/C++ ABI/API compatibility breaks — while reporting exactly which finding classes weren't checkable with the evidence you gave it, rather than silently passing. 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.

It catches removed or renamed symbols, changed function signatures, struct layout drift, vtable reordering, enum value reassignment, and many more — **361 ABI/API change types** in total — that cause crashes, silent data corruption, or linker failures after a library upgrade.

> **Platforms:** Linux (ELF), Windows (PE/COFF), macOS (Mach-O). Binary and header AST analysis on all platforms; debug-info cross-check uses DWARF (Linux, macOS) and PDB (Windows). MinGW-built DLLs are validated end-to-end in CI; native MSVC+PDB verdicts are experimental (the CI lane is non-blocking until proven stable) — see [Platform Support](https://abicheck.github.io/abicheck/reference/platforms/).

**Full documentation:** **[abicheck.github.io/abicheck](https://abicheck.github.io/abicheck/)**

---

## Key features

- **Reads multiple sources of information.** abicheck doesn't rely on a single view of a library. It overlays up to **five independent, additive sources** — the compiled binary, its debug symbols, its public headers, its build-system data, and (optionally) its sources — and lets the strongest evidence win. Each source finds breaks the weaker ones are blind to, and *removes* false positives the weaker ones would raise. See [How it works](#how-it-works--multiple-sources-of-information) below.
- **Detects most of what causes ABI/API breaks.** **361 change types** across functions, variables, structs/classes, enums, unions, typedefs, templates, and platform/linker metadata — removed or renamed symbols, changed signatures and parameter lists, struct/class layout drift, field-offset shifts, vtable reordering, enum value reassignment, qualifier/`noexcept`/access changes, calling-convention and packing changes, symbol-version and SONAME drift, dependency leaks, and more. Each is classified as `BREAKING`, `API_BREAK`, `COMPATIBLE_WITH_RISK`, or `COMPATIBLE`. See the [Change Kind Reference](https://abicheck.github.io/abicheck/reference/change-kinds/).
- **Cross-platform.** Linux (ELF), Windows (PE/COFF), and macOS (Mach-O) binaries, with debug-info cross-checks from DWARF, PDB, BTF, and CTF. See [Platform Support](https://abicheck.github.io/abicheck/reference/platforms/) for what's validated in CI per platform (native MSVC+PDB verdicts are experimental).
- **Built for CI.** Deterministic [exit codes](https://abicheck.github.io/abicheck/reference/exit-codes/), SARIF/JSON/Markdown/HTML/JUnit output, snapshot-based [baselines](https://abicheck.github.io/abicheck/user-guide/baseline-management/), [policy profiles](https://abicheck.github.io/abicheck/user-guide/policies/) and [suppressions](https://abicheck.github.io/abicheck/user-guide/suppressions/), and a first-class [GitHub Action](https://abicheck.github.io/abicheck/user-guide/github-action/).
- **Public-surface scoping.** Filters findings to the library's *public* ABI surface so internal-only changes don't fail your build — fewer false positives than symbol-only tools.
- **More than one library at a time.** Compare co-versioned multi-library releases as a single bundle ([`compare` on directory/package inputs](https://abicheck.github.io/abicheck/user-guide/multi-binary/)), check whether a specific application still works ([`compare --used-by`](https://abicheck.github.io/abicheck/user-guide/appcompat/)), or validate a binary's full dependency stack across sysroots ([`deps compare`](https://abicheck.github.io/abicheck/user-guide/cli-usage/)).
- **Drop-in for existing tools.** A [`compat`](https://abicheck.github.io/abicheck/user-guide/from-abicc/) mode mirrors `abi-compliance-checker` flags, and migration guides cover [ABICC](https://abicheck.github.io/abicheck/user-guide/from-abicc/) and [libabigail](https://abicheck.github.io/abicheck/user-guide/from-libabigail/).
- **Agent- and script-friendly.** Structured JSON, a [Python API](#python-api), and an [MCP server](https://abicheck.github.io/abicheck/user-guide/mcp-integration/) for AI-driven workflows. Pure Python (3.10+), no heavyweight native toolchain required for binary-only mode.

---

## How it works — multiple sources of information

abicheck treats compatibility analysis as a question of **evidence**: the more independent sources you give it about a library, the more it can prove — and the fewer false positives it raises. There are **five layers**, ordered from the least input to the most. Each one *adds* facts the previous cannot see; none is complete on its own.

| Layer | Source you provide | Read by | What it newly reveals |
|:-----:|--------------------|---------|------------------------|
| **L0** | **Just the binary** — a stripped `.so` / `.dll` / `.dylib` | ELF/PE/COFF/Mach-O parsers (`pyelftools`, `pefile`, `macholib`) | Exported symbols, SONAME/install-name, symbol versions, visibility, binding, `DT_NEEDED`/`LC_LOAD_DYLIB` dependencies |
| **L1** | **+ Debug symbols** — a `-g` build or sidecar debug file | DWARF, PDB, BTF, CTF | Type **layout**: struct/class sizes, field offsets, enum *values*, vtable slots, calling convention, packing/alignment |
| **L2** | **+ Public headers** — `-H include/` | castxml AST | Source-level **API**: signatures, overloads, access (`public`/`private`), `final`/`explicit`/`noexcept`, templates, default args, public/internal scoping |
| **L3** | **+ Build system data & options** — `-p build/` | compile DB / CMake / Ninja / Bazel / Make | The flags the library was *actually* built with: `-std`, `_GLIBCXX_USE_CXX11_ABI`, `-fvisibility`, `-fabi-version`, toolchain/sysroot, export maps |
| **L4** | **+ Sources** — a build/source pack | per-TU source ABI replay | Facts that never reach the binary: macro/`constexpr` values, default-argument *values*, inline/template bodies, uninstantiated templates |

The layers are **independent and additive, not a fallback chain** — abicheck overlays every source you give it and computes one worst-wins verdict, under the *authority rule*: artifact-backed evidence (L0/L1/L2) is authoritative for the shipped-ABI verdict, while build/source evidence (L3/L4) *explains, localizes, scopes, or adds confidence* to a finding (and can raise its own source-/API-level findings) but never silently deletes an artifact-proven break.

> **A sixth code you may see in the docs:** `L5` is the source *reachability graph* abicheck **derives** from L3/L4 evidence — you provide five sources (L0–L4); L5 is computed, never an input. It appears in the [`scan` documentation](https://abicheck.github.io/abicheck/concepts/evidence-and-detectability/).

With less input, abicheck degrades gracefully *down the staircase* rather than failing — a stripped binary with no headers collapses toward symbol-only checking — and `abicheck dump --dry-run` reports exactly which layers it found. The best input you can give it is **old library + new library + matching public headers + debug info + build data**. See [Evidence & Detectability](https://abicheck.github.io/abicheck/concepts/evidence-and-detectability/) for what each source can and cannot see, and [Architecture](https://abicheck.github.io/abicheck/concepts/architecture/) for how the layers are reconciled.

---

## Installation

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

`abicheck` also needs `castxml` and a C++ compiler for header AST analysis (the conda-forge package pulls these in automatically). Without them, abicheck still works in binary-only mode. See [Getting Started](https://abicheck.github.io/abicheck/getting-started/) for per-platform setup and cross-compilation.

> **Naming note:** the PyPI/conda-forge package (`abicheck`) is distinct from the older SourceForge `abicheck` that is still packaged by some Linux distributions, and from similarly named ABI tools such as `abi-compliance-checker` wrappers or Fedora's `libabigail-tools`. Run `abicheck --version` to confirm — it should print `abicheck X.Y.Z (abicheck/abicheck)`. If there is a conflict, invoke via `python -m abicheck`.

---

## Quick start

Compare two library versions:

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

Save a baseline snapshot at release time, then compare every new build against it:

```bash
abicheck dump libfoo.so -H include/foo.h --version 1.0 -o baseline.json
abicheck compare baseline.json ./build/libfoo.so --header new=include/foo.h
```

Supported output formats: `markdown` (default), `json`, `sarif`, `html`, and `junit`.

```bash
abicheck compare old.so new.so -H foo.h --format sarif -o report.sarif
```

See [Getting Started](https://abicheck.github.io/abicheck/getting-started/) for the full tutorial and [CLI Usage](https://abicheck.github.io/abicheck/user-guide/cli-usage/) for the complete command reference.

---

## Which command do I need?

abicheck's whole CLI is exactly 5 root commands: `dump`, `compare`, `scan`, `deps`, `compat`.

| I want to… | Use |
|------------|-----|
| Check whether a library upgrade breaks existing consumers | [`abicheck compare`](https://abicheck.github.io/abicheck/user-guide/cli-usage/) |
| Compare **a multi-library release** (a co-versioned bundle, e.g. oneDAL) as a single bundle | [`abicheck compare`](https://abicheck.github.io/abicheck/user-guide/multi-binary/) |
| Check whether **my application** breaks with a new library version | [`abicheck compare --used-by APP`](https://abicheck.github.io/abicheck/user-guide/appcompat/) |
| Check whether a **plugin** still satisfies its host's required entrypoints | [`abicheck compare --required-symbol SYM`](https://abicheck.github.io/abicheck/user-guide/plugin-systems/) |
| Run a deterministic source-intelligence scan (classify → audit → optional compare) | [`abicheck scan ARTIFACT`](https://abicheck.github.io/abicheck/user-guide/scan-levels/) |
| Validate a binary's full dependency stack across two sysroots | [`abicheck deps compare`](https://abicheck.github.io/abicheck/user-guide/cli-usage/) |
| Drop-in replacement for `abi-compliance-checker` | [`abicheck compat`](https://abicheck.github.io/abicheck/user-guide/from-abicc/) |
| Save a reusable ABI snapshot | [`abicheck dump`](https://abicheck.github.io/abicheck/getting-started/) |

---

## Exit codes

Use these to gate CI pipelines.

| Exit code | Verdict | Meaning |
|-----------|---------|---------|
| `0` | `NO_CHANGE` / `COMPATIBLE` / `COMPATIBLE_WITH_RISK` | Safe — no binary ABI break |
| `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 (multi-library compare with `--fail-on-removed-library`) |

Any active severity setting (a `--severity-*` flag or a severity value in `.abicheck.yml`) switches `compare` to a severity-based scheme where `1` means an error-level *finding* in the addition/quality categories (`0` still passes, `4` is still worst). `scan`, `deps compare`, and `compat` add per-command codes (e.g. `scan` also has a `5` for `--budget` overflow). The canonical matrix is the [exit code reference](https://abicheck.github.io/abicheck/reference/exit-codes/); how snapshots, policies, suppressions, and severity combine into the exit code is covered in [CI Gating](https://abicheck.github.io/abicheck/user-guide/ci-gating/).

---

## GitHub Action

```yaml
- uses: abicheck/abicheck@v0.3.0
  with:
    old-library: abi-baseline.json
    new-library: build/libfoo.so
    new-header: include/foo.h
    format: sarif
    upload-sarif: true
```

The action installs Python, castxml, and abicheck automatically. Outputs: `verdict`, `exit-code`, `report-path`. See the [GitHub Action docs](https://abicheck.github.io/abicheck/user-guide/github-action/) for matrix builds, cross-compilation, and gating flags (`fail-on-breaking`, `fail-on-api-break`).

The default compare path only needs normal checkout access. Extra repository permissions are needed only for optional GitHub integrations: `pull-requests: write` for PR comments and `security-events: write` for SARIF upload.

---

## Policies and suppressions

Policies classify detected changes (`BREAKING`, `COMPATIBLE`, …); suppressions silence known or intentional changes so they don't fail CI.

```bash
abicheck compare old.so new.so -H foo.h \
  --policy sdk_vendor \
  --suppress suppressions.yaml
```

Built-in profiles: `strict_abi` (default), `sdk_vendor`, `plugin_abi`. Custom YAML policies are supported, and the ABICC compat CLI accepts `-symbols-list`/`-types-list` whitelist flags.

Full references:
- [Policy Profiles](https://abicheck.github.io/abicheck/user-guide/policies/)
- [Suppressions](https://abicheck.github.io/abicheck/user-guide/suppressions/) (YAML schema, expiry, justification)
- [Migrating from ABICC](https://abicheck.github.io/abicheck/user-guide/from-abicc/)

---

## Python API

```python
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
```

See the [Python API guide](https://abicheck.github.io/abicheck/user-guide/python-api/)
for snapshots, custom policies, and rendering, plus the
[MCP server integration](https://abicheck.github.io/abicheck/user-guide/mcp-integration/)
for AI-agent workflows.

---

## Examples

The [`examples/`](examples/README.md) directory contains **186 real-world ABI/API scenarios** (181 single-library cases plus 5 multi-library bundle cases) with ground-truth verdicts. Most are single-library `v1`/`v2` examples with a consumer app; the G20 audit/cross-source cases (143–151) are single-build snapshots demonstrating intra-version cross-checks; the L3/L4/L5 build/source-only cases (152–161) ship hand-built evidence-model fixture pairs demonstrating failures no artifact layer can see; case 164 ships a guard-annotated fixture pair demonstrating a build-context-cleared header false positive (ADR-039); bundle/release-level cases use release-style layouts. The full catalog is the development regression corpus; a smaller historical cross-tool subset is kept in the reference docs for release-to-release comparison with libabigail and ABICC.

The authoritative completeness gate is the full example matrix: compiler lanes, runtime smoke, bundle validation, and dedicated proof owners are aggregated into exactly one row per ground-truth case. A green single-library lane or a `libv1.so`/`libv2.so` pair scan is not full-catalog proof. See the [full example validation runbook](docs/development/examples-validation-runbook.md) for runner selection, the reproducible workflow, artifact semantics, and agent rules.

---

## Validation snapshot

The main validation target is the full **186-case catalog**. To scan it for the current checkout:

```bash
python scripts/benchmark_comparison.py --suite all
```

The command writes `benchmark_reports/benchmark_report.json` with the selected suite, abicheck version, git commit, tool versions, the `ground_truth.json` SHA-256, and per-tool accuracy. Cases that require bundle/release harnesses or unavailable compiler features are marked as unscored instead of being folded into single-library verdict accuracy.

For apples-to-apples comparison with libabigail and ABICC, release workflows also run the historical pinned cross-tool subset (`case01`-`case73` + `case26b`) and attach that report to GitHub Releases:

```bash
python scripts/benchmark_comparison.py --suite pinned74
```

### Detection by evidence source

The [five sources of information](#how-it-works--multiple-sources-of-information) each find breaks the weaker sources are blind to. The table below is derived from the `examples/ground_truth.json` minimum-evidence labels of all 169 catalog cases. The `--evidence-tiers` mode empirically scans the runnable catalog at L0-L3; L4 source-pack measurement is tracked as a separate extension:

```bash
python scripts/benchmark_comparison.py --evidence-tiers
```

| Source you provide | Cumulative cases reaching the correct verdict |
|--------------------|:---------------------------------------------:|
| Just the binary (`L0`) | 52 / 169 (31%) |
| + Debug symbols (`L1`) | 119 / 169 (70%) |
| + Public headers (`L2`) | 150 / 169 (89%) |
| + Build data (`L3`) | 160 / 169 (95%) |
| + Sources (`L4`) | 166 / 169 (98%) |
| + Source graph (`L5`) | 169 / 169 (100%) |

More evidence also *removes* false positives (e.g. header scoping correctly dismisses internal-struct changes). This staircase is a **discoverability floor** — the minimum source that unlocks the correct verdict per case — not a blind accuracy score; for the stricter number that also penalizes false positives across the whole catalog, see the [full-catalog benchmark](https://abicheck.github.io/abicheck/reference/tool-comparison/#full-catalog-benchmark-2026-07-12-all-170-cases) (L3-L5 scores 90.0% there, with 7 known false positives). See [Evidence & Detectability](https://abicheck.github.io/abicheck/concepts/evidence-and-detectability/) for what each source reveals and [Benchmarking by evidence tier](https://abicheck.github.io/abicheck/reference/tool-comparison/#benchmarking-by-evidence-tier) for the methodology.

Per-case matrix, methodology, full-catalog notes, and the pinned cross-tool comparison table: [Tool Comparison & Benchmarks](https://abicheck.github.io/abicheck/reference/tool-comparison/).

---

## Documentation

- **Start here:** [Getting Started](https://abicheck.github.io/abicheck/getting-started/)
- **User guide:** [CLI Usage](https://abicheck.github.io/abicheck/user-guide/cli-usage/) · [Application compatibility](https://abicheck.github.io/abicheck/user-guide/appcompat/) · [Output formats](https://abicheck.github.io/abicheck/user-guide/output-formats/) · [GitHub Action](https://abicheck.github.io/abicheck/user-guide/github-action/)
- **Concepts:** [Verdicts](https://abicheck.github.io/abicheck/concepts/verdicts/) · [Architecture](https://abicheck.github.io/abicheck/concepts/architecture/) · [ABI/API Handling & Recommendations](https://abicheck.github.io/abicheck/concepts/abi-api-handling/) · [Limitations](https://abicheck.github.io/abicheck/concepts/limitations/)
- **Reference:** [Change Kinds](https://abicheck.github.io/abicheck/reference/change-kinds/) · [Exit Codes](https://abicheck.github.io/abicheck/reference/exit-codes/) · [Platforms](https://abicheck.github.io/abicheck/reference/platforms/) · [Tool Comparison](https://abicheck.github.io/abicheck/reference/tool-comparison/)
- **Troubleshooting:** [Troubleshooting guide](https://abicheck.github.io/abicheck/troubleshooting/)

### Citation and machine-readable metadata

- GitHub renders [CITATION.cff](CITATION.cff) through **Cite this repository**.
- [CodeMeta](codemeta.json) and [Zenodo deposit metadata](.zenodo.json) expose
  software identity, licensing, authorship, and dependency metadata.
- The published [versioned JSON Schemas](https://abicheck.github.io/abicheck/reference/machine-readable-metadata/)
  describe the machine-readable output contracts. Each schema's canonical `$id`
  is a resolvable HTTPS URL.

---

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, testing, code style, and PR workflow. Project status and roadmap: [development/goals.md](docs/development/goals.md).

## License

Licensed under the Apache License, Version 2.0. See [LICENSE](LICENSE) and [NOTICE](NOTICE).

Copyright 2026 Nikolay Petrov
