Skip to content

Creating and Comparing a Baseline

The practical mechanics of producing an ABI baseline and comparing against one. For what a baseline is and why most projects need two of them, see Baseline Management; for where to keep the file once you've created it, see Storing Baselines.

Creating a Baseline

# Basic: write to stdout
abicheck dump libfoo.so -H include/foo.h --version 2.0.0

# Write to a specific file
abicheck dump libfoo.so -H include/foo.h --version 2.0.0 -o baseline.json

# Conventionally named (see naming convention below)
abicheck dump libfoo.so -H include/foo.h --version 2.0.0 -o libfoo-2.0.0.abicheck.json

Provenance Metadata

Snapshots include provenance metadata that tracks where and when they were created:

abicheck dump libfoo.so -H include/foo.h \
  --version 2.0.0 \
  --provenance git-tag=v2.0.0 \
  --provenance build-id="$CI_RUN_ID" \
  -o libfoo-2.0.0.abicheck.json

This embeds in the snapshot JSON:

Field Source Example
git_commit Auto-detected from git rev-parse HEAD abc1234def5678
git_tag --provenance git-tag=... v2.0.0
created_at Auto-set (ISO 8601 UTC) 2026-03-24T12:00:00+00:00
build_id --provenance build-id=... gh-actions-1234

Use --provenance git=off to skip automatic git commit detection (e.g., in non-git environments).

The .abicheck.json Naming Convention

Name baselines <library>-<version>.abicheck.json (via -o):

Library Version Output File
libfoo.so.1 2.0.0 libfoo-2.0.0.abicheck.json
bar.dll 3.1 bar-3.1.abicheck.json
libqux.dylib 1.0 libqux-1.0.abicheck.json

This convention makes CI scripts predictable: upload with *.abicheck.json, download with --pattern '*.abicheck.json'. The GitHub Action's abi-baseline input looks for *.abicheck.json assets on releases.

See Storing Baselines for where to put the file once you've created it, including the baseline Action for multi-library releases.

Comparing Against a Baseline

Once you have a baseline, comparison is the same regardless of storage:

# JSON snapshot vs new binary
abicheck compare baseline.json build/libfoo.so --header new=include/foo.h

# Two snapshots (no headers or tools needed)
abicheck compare old-baseline.json new-baseline.json

Snapshots are self-contained — they include all type, function, variable, and enum information. Comparing two snapshots requires no headers, compilers, or debug info.

You can also pass packages (RPM, Deb, tar, conda, or wheel) straight to compare — it compares all shared libraries inside them without manual extraction:

abicheck compare libfoo-1.0.rpm libfoo-1.1.rpm

See Multi-Binary Releases for the bundle/package flags and the GitHub Action guide for CI examples with packages.

A one-off comparison with side-scoped headers

abicheck compare OLD NEW doesn't require a stored baseline at all — OLD can be a previous native library or a saved ABI dump directly (a single file, not a directory or package -- for those, compare takes the two package roots the same way). compare always runs its always-on pattern/cross-source audit checks alongside the comparison itself, in one pass:

abicheck compare old/libfoo.so new/libfoo.so --header new/include

-H/--header and -I/--include are side-aware: a bare value applies to both sides, and an old=/new= prefix scopes to one side. When OLD is a native library (not a snapshot) and its public headers differ from the new version, parse the old side with its own headers using the old= prefix:

abicheck compare old/libfoo.so new/libfoo.so \
  --header new=new/include --header old=old/include
  • Without an old=-scoped header, a native OLD library is parsed with the same headers as NEW (correct only when the headers didn't change).
  • A JSON-snapshot OLD operand already has its headers baked in, so side-scoped headers are unnecessary there. Prefer a pre-dumped snapshot baseline when you can — it's unambiguous and needs no toolchain at compare time.

(scan ARTIFACT --against OLD was this workflow's spelling before scan was deleted outright in 0.6 — no alias, no deprecation window; compare OLD NEW is the direct replacement, with OLD/ARTIFACT swapping argument order to match compare's own OLD NEW convention.)

See Evidence Depth for the full --depth reference.