Maintain Debian Library ABI Checks with dpkg-gensymbols
dpkg-gensymbols compares the shared libraries in a Debian package build tree with a maintainer's symbols template. It produces the package's symbols file, reports changes, and can fail when an ABI change crosses a check threshold. This guide uses the dpkg-dev 1.22.6 command installed on this machine.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about 20 minutes for a first run if the package already has a working build. You need a Debian source package tree, a successful library build, and the dpkg-dev package. The examples use example-lib and 1.4.0-1 as placeholders. Replace them with values from your package.
1. Check the package and build layout
Run this from the root of the source package. The normal scan directory is debian/tmp. A package build normally creates the library there before the packaging helper runs.
dpkg-gensymbols --version
find debian/tmp -type f \( -name '*.so' -o -name '*.so.*' \) -print
On the installed system, the first command reports Debian dpkg-gensymbols version 1.22.6. If the second command finds nothing, stop and fix the build or choose the actual build directory. Running the helper against an empty tree cannot produce useful ABI information.
2. Add or locate the symbols template
The helper chooses the first matching reference in this order:
debian/<package>.symbols.<arch>debian/symbols.<arch>debian/<package>.symbolsdebian/symbols
For a single binary package, debian/example-lib.symbols is usually the clearest location. The template records the minimum package version that provides each public symbol. That version is an ABI promise: do not copy a generated diff into the template until you have checked the library change and the version that really introduced it.
If debian/control lists more than one binary package, tell the command which package you mean. The same is required when working outside a source package tree.
dpkg-gensymbols -p example-lib -v1.4.0-1
Checkpoint
The package name must match the binary package whose library is being scanned, and the version must describe the package being built. By default, the version comes from debian/changelog; -v is required outside that context.
3. Generate a reviewable diff
Run the helper after the library has been built. The default output is installed as debian/tmp/DEBIAN/symbols, or in the equivalent DEBIAN directory selected with -P.
dpkg-gensymbols -p example-lib -v1.4.0-1
When the generated file differs from the template, the command prints a diff. New symbols commonly indicate an API extension. A missing symbol is more serious: public symbols are normally expected to remain available unless the library's ABI and SONAME policy deliberately changed.
Review the diff as an ABI change, not as a generated text file. Check upstream release notes and the library's exported symbols. In particular, do not assume that an unchanged diff proves compatibility. A symbol can keep its name while changing behaviour or its ABI, and dpkg-gensymbols cannot detect every such change.
4. Select the failure threshold
The default check level is 1. Levels include the checks below:
| Level | Fails when |
|---|---|
| 0 | No comparison change causes failure. |
| 1 | Symbols disappear. |
| 2 | New symbols appear. |
| 3 | Libraries disappear. |
| 4 | Libraries appear. |
Use a stricter level when your package policy requires it:
dpkg-gensymbols -p example-lib -v1.4.0-1 -c4
Level 0 is useful for inspecting output while investigating a known transition, but it should not silently weaken the package's normal build checks. The environment variable DPKG_GENSYMBOLS_CHECK_LEVEL overrides the command-line setting, even when -c is present. Check it before debugging an unexpected result:
printf '%s\n' "${DPKG_GENSYMBOLS_CHECK_LEVEL:-unset}"
Checkpoint
If a build passes with a lower level than expected, inspect the environment first. Clear an accidental override for the current shell with unset DPKG_GENSYMBOLS_CHECK_LEVEL; this changes only the shell environment.
5. Limit the scan when the package has several libraries
Use -e when only particular libraries should contribute to the file. It accepts pathname-expansion patterns, and you can repeat it for more than one library.
dpkg-gensymbols -p example-lib -v1.4.0-1 \
-e 'debian/tmp/usr/lib/*/libexample.so.*'
Quote the pattern so the shell does not expand it before dpkg-gensymbols receives it. Confirm the resulting diff names the intended library. If private shared libraries live outside the usual search locations, use -l instead of setting LD_LIBRARY_PATH:
dpkg-gensymbols -p example-lib -v1.4.0-1 \
-l debian/tmp/opt/example/lib
This distinction matters during cross-compilation: LD_LIBRARY_PATH affects the run-time linker, while -l adds a build-time private-library search directory.
6. Write a template or inspect an alternate output
Use -t when you need a source-package template rather than the processed deb-symbols format. Use -O to print the generated file or write it elsewhere. A pre-existing -O file is used as the starting reference.
dpkg-gensymbols -p example-lib -v1.4.0-1 -t -O /tmp/example-lib.symbols.new
sed -n '1,80p' /tmp/example-lib.symbols.new
The temporary file is safe to remove after review. Do not replace the maintained template until the diff has been checked. If you use -O without a filename, the generated symbols file goes to standard output, which is useful for a comparison command but easy to lose if redirected carelessly.
Common failure points
- No package version: add
-vwhen there is no usabledebian/changelog. - Wrong package: add
-pfor multi-binary source packages and verify the selected template name. - Missing libraries: inspect
debian/tmpand use-Pif the build uses another package directory. - Unexpected warnings: omit
-qwhile investigating. It suppresses diffs and informational warnings, but it does not disable checks. - Architecture mismatch: use
-aonly when the binaries for the requested host architecture are already available.
The command does not need elevated privileges for an ordinary package build. Do not run it with sudo to repair a failed check. Fix the build tree or template as the package owner, then rebuild. The command can write under the selected build directory, so review -P and -O paths before running it.
Done means
- The intended libraries were found in the package build tree.
- The package name and version are explicit or correctly derived.
- Every generated diff was reviewed as an ABI change.
- The check level matches the package's policy and is not being overridden accidentally.
- The maintained symbols template has been updated only after verification.