Check Debian Build Dependencies Before You Build
Kicking off a twenty-minute build only to have it die on a missing library ten minutes in is exactly what dpkg-checkbuilddeps exists to prevent. It runs a pre-flight check against a control file, tells you plainly whether the dependencies are met, and lets you pick the dependency fields that match the package you actually intend to build. The examples use dpkg-checkbuilddeps 1.22.6 from the locally installed dpkg-dev package, version 1.22.6ubuntu6.6.
The route
Jump straight to the step you need, or tick off Done means at the end.
- 1. Check the installed command
- 2. Run the default check from the source tree
- 3. Read an unmet dependency failure
- 4. Check conflicts as well as dependencies
- 5. Use an alternate control file safely
- 6. Match the check to the package being built
- 7. Apply build profiles deliberately
- 8. Override strings only for diagnosis
Allow about fifteen minutes. You need a shell, a Debian-style debian/control file or another control file, and the dpkg-dev package. The checks read the dpkg database and the control file; they never install, remove or upgrade packages, so the normal workflow needs no elevated privileges.
1. Check the installed command
Confirm which executable you are using and record its version. This is ordinary and read-only:
$ command -v dpkg-checkbuilddeps
/usr/bin/dpkg-checkbuilddeps
$ dpkg-checkbuilddeps --version
Debian dpkg-checkbuilddeps version 1.22.6
$ dpkg-query -W -f='${Package} ${Version}\n' dpkg-dev
dpkg-dev 1.22.6ubuntu6.6
Option details and output can vary between dpkg releases. If you are diagnosing a build on another machine, check that machine's version rather than assuming this guide's output travels everywhere unchanged.
2. Run the default check from the source tree
Change to the root of the source package, then run the command with no filename:
$ cd /path/to/source-package
$ dpkg-checkbuilddeps
With no control-file argument, the command reads debian/control. A successful run prints nothing and exits with status 0. Capture that status immediately if a script or build wrapper needs it:
$ dpkg-checkbuilddeps
$ status=$?
$ printf 'dependency check status: %s\n' "$status"
dependency check status: 0
Checkpoint
Silence here is good news, not a problem. No output plus status 0 means the installed packages satisfy the dependencies and do not match the listed build conflicts for the selected build context.
3. Read an unmet dependency failure
A non-zero result means the check found something that does not fit the installed package state. To see the failure path without touching the real system, create a small control file in /tmp and ask for a package name that is deliberately unlikely to be installed anywhere:
$ control_file=/tmp/example-control
$ printf '%s\n' \
'Source: example' \
'Build-Depends: package-that-is-not-installed-anywhere (>= 1)' \
> "$control_file"
$ dpkg-checkbuilddeps "$control_file"
dpkg-checkbuilddeps: error: Unmet build dependencies: package-that-is-not-installed-anywhere (>= 1)
$ printf 'exit status: %s\n' "$?"
exit status: 1
That package name is only a test value; replace it with the real dependency from your project. A non-zero status should stop a build or at least make its failure visible, not send you off installing random packages. Resolve the dependency through the project's documented package source, then run the check again.
The command checks package relationships against the local dpkg database. It does not consult a repository, and it does not prove that a later build step will succeed. A package can be installed and still fail a versioned requirement, an architecture requirement, or some other relationship.
4. Check conflicts as well as dependencies
Build conflicts are constraints on packages that must not be installed for the selected build. Test them independently with -c, which replaces the control file's build-conflict string for this one invocation:
$ dpkg-checkbuilddeps -c 'dpkg-dev' "$control_file"
dpkg-checkbuilddeps: error: Build conflicts: dpkg-dev
$ printf 'exit status: %s\n' "$?"
exit status: 1
That fails on the example machine because dpkg-dev happens to be installed. The option neither removes the package nor edits the control file; it is useful for investigating a generated dependency string, but the normal package check should read the project's declared fields rather than replacing them during a real build.
Warning
Do not remove a package just to make this check pass. Removing build tools can disrupt other work and is not an undoable diagnostic step. Work out why the conflict exists, use the project's supported build environment, or stop and ask the package maintainer.
5. Use an alternate control file safely
The final positional argument names the control file, which lets you inspect a file outside the current directory, useful for a packaging review or a generated control file:
$ dpkg-checkbuilddeps /path/to/review/debian/control
$ printf 'exit status: %s\n' "$?"
exit status: 0
Keep the path quoted if it can contain spaces. The command reads the file; it never writes it. If the path is wrong, fix the path or the source package layout first. Do not create a second control file beside the real one and assume the build will use it: the build tool and this checker can end up pointed at different inputs.
6. Match the check to the package being built
Debian control files can separate dependencies for architecture-dependent and architecture-independent work, and the default check considers the relevant fields together. Use these switches only when they describe the build you are actually about to run:
-AignoresBuild-Depends-ArchandBuild-Conflicts-Arch. The manual describes this for an architecture-independent-only build, or together with-Bfor a source-only build.-BignoresBuild-Depends-IndepandBuild-Conflicts-Indepfor an architecture-dependent-only build.-A -Bignores both specialised groups. It does not make ordinaryBuild-DependsorBuild-Conflictsdisappear.-Iignores dpkg's built-in build dependencies and conflicts. Use this only when the build environment intentionally provides and checks those requirements elsewhere.
For a package whose host architecture differs from the current system, pass -a with the intended architecture:
$ dpkg-checkbuilddeps -a arm64 /path/to/source-package/debian/control
This changes the assumption used for dependency resolution. It does not turn the current machine into an arm64 build environment.
7. Apply build profiles deliberately
Profile-qualified relationships are selected with -P. Its value is a comma-separated list, such as stage1 or stage1,nocheck:
$ dpkg-checkbuilddeps -P stage1 /path/to/source-package/debian/control
$ printf 'exit status: %s\n' "$?"
exit status: 0
The profile names must match the profiles used by the build. Do not add a profile just because it makes an error disappear; that can leave you with a check that no longer describes the build you will actually run. The environment variable DEB_BUILD_PROFILES supplies space-separated active profiles when set, and -P overrides it for this command.
When a control file includes profile restrictions, check the exact command line the build system uses. The architecture option, the profile option and the package database all affect the answer, so record all three in reproducible build logs.
8. Override strings only for diagnosis
-d supplies a replacement build-dependency string and -c supplies a replacement build-conflict string. The control file is still required even when one of these strings is supplied:
$ dpkg-checkbuilddeps -d 'dpkg-dev (>= 1.22.6)' "$control_file"
$ printf 'exit status: %s\n' "$?"
exit status: 0
Use these to isolate a suspected dependency expression or to reproduce a build tool's input. They do not edit debian/control, and they are easy to misuse in a script because they replace the corresponding fields rather than adding to them. Prefer the plain command for the final pre-flight check.
Done means
- Versions confirmed. You checked the installed dpkg-checkbuilddeps and dpkg-dev versions.
- Right file checked. You ran the check against the intended
debian/controlfile. - Both outcomes understood. Status 0 and a non-zero unmet-dependency result both mean what you expect.
- Conflicts respected. Build conflicts were treated as constraints, never as a reason to remove packages.
- Flags matched to reality.
-A,-B,-I,-aand-Pmatch the build you will really perform. - Overrides kept to diagnosis. Any
-dor-coverride never replaced the project's normal check.