Home / Alt manpages / dpkg-shlibdeps(1)

  • dpkg-shlibdeps(1)
  • User command
  • linux

Generate Library Dependencies with dpkg-shlibdeps

dpkg-shlibdeps reads your built ELF executable and works out which shared libraries it needs. It writes a dependency such as libc6 (>= 2.34) into a substvars file, so you never track linked libraries by hand. The examples match dpkg 1.22.6 from dpkg-dev 1.22.6ubuntu6.6, installed on this machine.

Allow about fifteen minutes. You need a Debian source tree with debian/control, an already-built executable, and the dpkg-dev package. These commands run as your build user, need no sudo, and should not be run as root merely to make dependency discovery work.

1. Check the installed tool

Run the version check from an ordinary shell:

$ dpkg-shlibdeps --version
Debian dpkg-shlibdeps version 1.22.6.

The command takes one or more executable paths, reads the ELF binaries, maps their shared libraries to Debian packages, and uses package-provided symbols or shlibs data to pick the dependency. It expects to run inside a package source tree, because the default output file is debian/substvars and it reads package metadata straight from debian/control.

Checkpoint

From the root of your source tree, confirm the package metadata and binary both exist:

$ test -f debian/control && echo 'control file: present'
$ test -x debian/example/usr/bin/example && echo 'binary: present'

Swap in the real binary package and executable path for your build. A successful test prints both confirmation lines; a missing one is a packaging-order problem, fix it before calling dpkg-shlibdeps at all.

2. Preview the dependency without touching substvars

Use -O while checking a new build. It prints the generated substitution variables instead of updating debian/substvars:

$ dpkg-shlibdeps -O debian/example/usr/bin/example
shlibs:Depends=libc6 (>= 2.34)

Your output depends on the binary and the installed package database, so expect the shape shlibs:Depends=... rather than a fixed list of libraries. In the local probe behind this guide, /bin/true produced that exact libc6 (>= 2.34) line when run from a source tree with debian/control present.

Tip

-O needs no shell redirection or a normal invocation, which is exactly why it makes a good review checkpoint. Attach a filename directly to the option, for example -Odebian/dependency-preview, or leave it off to use standard output.

3. Write the result to the intended substvars file

Once the preview looks right, write to an explicit file so the destination is visible in the build recipe:

$ dpkg-shlibdeps -Tdebian/substvars debian/example/usr/bin/example
$ grep '^shlibs:' debian/substvars
shlibs:Depends=libc6 (>= 2.34)

The -T form takes the substvars path directly after the option. Omit it and the default destination, also debian/substvars, gets selected anyway. The command removes existing variables under the selected prefix before writing new values, handy in a clean build, surprising in a hand-maintained file.

Warning

Never overwrite a file holding unrelated local substitutions without checking it first. Preview with -O, or route to a separate generated path the packaging step consumes deliberately. Wrote an unwanted generated file anyway? Restore it from version control, or remove only that file once you have confirmed no later build step needs it. Do not delete the whole debian directory.

4. Supply dependencies to the right control field

The default dependency field is Depends. Use -d before an executable when another field is genuinely needed, and remember it applies to every following executable until the next -d:

$ dpkg-shlibdeps -O \
    -dPre-Depends debian/example/usr/sbin/example
shlibs:Pre-Depends=libc6 (>= 2.34)

Do not pick Pre-Depends just to make a dependency look more serious; it changes unpacking order and should reflect a real requirement. The same dependency turning up in several recognised fields gets its weaker duplicates dropped, keeping only the more important one.

Building several binaries from one package? Pass them together, or repeat -e, to keep one generated dependency set for the whole thing:

$ dpkg-shlibdeps -O \
    debian/example/usr/bin/example \
    debian/example/usr/lib/example/plugin.so

Only include files that are actually part of the package being built. Analysing an arbitrary host executable produces a plausible-looking dependency that says nothing useful about your own package.

5. Add private library paths with -l

Link to a private library inside your build tree, and add its directory with -l:

$ dpkg-shlibdeps -O \
    -l"$PWD/debian/example/usr/lib/example" \
    debian/example/usr/bin/example

That prepends the directory to dpkg-shlibdeps' own private-library search list. Use it instead of setting LD_LIBRARY_PATH for this build-time lookup: LD_LIBRARY_PATH also changes the run-time linker's behaviour and can mask a cross-compilation or packaging mistake you actually want to see.

If the library lives in another binary package, make sure that package's DEBIAN/shlibs or DEBIAN/symbols data exists before analysing the consumer. Use -S to search a particular package build directory first when several packages ship similarly named library variants, and -xpackage to exclude a package when a binary or plugin would otherwise create a self-dependency.

6. Read a shlibs file when dependency lookup fails

Symbols files give finer-grained minimum versions. A shlibs file is the simpler fallback, or override: it maps a library name and SONAME version to a package dependency, one line per library:

# comment lines are allowed
libcrunch 1 libcrunch1 (>= 1.2-1)

Blank lines are not allowed. The first two fields are whitespace-delimited, and the dependency field runs to the end of the line. For libcrunch.so.1, the library field is libcrunch and the SONAME version is 1. The dependency should name whichever package version supplied the newest symbols the consumers actually need.

For package-local overrides, dpkg-shlibdeps checks debian/shlibs.local first, unless -L names something else, then generated package-tree data, installed package data, and finally the system default file. A local override can hide a genuinely bad library package, so treat it as a deliberate decision and record the reason in your source tree.

7. Diagnose errors before weakening the check

A missing library produces a message like couldn't find library ... needed by .... Check the binary's RPATH, the private directory passed with -l, the build order, and whether the library carries the expected SONAME. Run with -v to see every directory and dependency file under consideration:

$ dpkg-shlibdeps -v -O debian/example/usr/bin/example
$ printf 'exit status: %s\n' "$?"
exit status: 0

A no dependency information found error means the library was located but no usable symbols or shlibs record backed it up. Fix the library package or the build order. --ignore-missing-info exists, but the manual actively discourages it: suppress that error and you can ship a package that installs cleanly today, then fails later when a required library simply is not there.

Tip

A warning about an unused linked library is a separate quality signal, not an error. Remove the unnecessary linker flag where practical, and never silence a warning by changing dependency fields instead, that edits package metadata without touching the actual binary.

Done means

  • Version matches your target. dpkg-shlibdeps --version against the dpkg-dev you are building for.
  • Run from a valid source tree, with debian/control present and the binary already built.
  • Previewed with -O before anything got written.
  • Wrote to the intended substvars file, only after reviewing that preview.
  • Private libraries used -l, never a build-time LD_LIBRARY_PATH workaround.
  • Missing symbols or shlibs data got fixed or understood, never hidden with --ignore-missing-info.