Wipe dpkg Build Leftovers with dpkg-buildtree
A stale debian/substvars from last week's build is a sneaky way to get a package that looks fine locally and fails somewhere else. dpkg-buildtree gives you a small, repeatable fix: run your own build-system cleanup first, then let dpkg-buildtree clean remove the dpkg-generated state and staging directory that would otherwise leak between builds. The installed command here is from dpkg-dev 1.22.6ubuntu6.6, which provides the clean action but not newer actions such as is-rootless.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about ten minutes for a first test, longer if you are editing an existing debian/rules. You need a Debian source tree with debian/control, the dpkg-dev package, and permission to modify the tree. This workflow needs no sudo. Do not run the cleanup in a directory you have not confirmed is the intended source tree.
1. Check the installed command
Start with read-only checks. They confirm which executable is on your path and whose behaviour you are about to rely on:
$ command -v dpkg-buildtree
/usr/bin/dpkg-buildtree
$ dpkg-query -W -f='${Package} ${Version}\n' dpkg-dev
dpkg-dev 1.22.6ubuntu6.6
$ dpkg-buildtree --version
Debian dpkg-buildtree version 1.22.6.
The help output for this installed version lists one operational command, clean, plus --help and --version. The syntax is deliberately short:
$ dpkg-buildtree --help
Usage: dpkg-buildtree [<command>]
Commands:
clean clean dpkg generated artifacts from the build tree.
--help show this help message.
--version show the version.
Checkpoint
If your help output lists a different set of commands, read that installed manual before copying examples from elsewhere. dpkg-buildtree has gained features across dpkg releases.
2. Identify the source tree before cleaning
Change into the package's top-level directory and verify the control file. The check itself changes nothing:
$ cd /path/to/source-package
$ test -f debian/control && echo "Debian source tree found"
Debian source tree found
$ pwd
/path/to/source-package
The installed implementation only treats a directory as a build tree when debian/control exists. If that file is missing, dpkg-buildtree clean exits quietly without removing anything. That is a useful guard, but it is not a substitute for checking pwd: a wrong directory can still have its own Debian metadata sitting in it.
Before the next step, look at what could be removed:
$ find debian -maxdepth 2 -path 'debian/control' -o -path 'debian/files*' -o -path 'debian/substvars*' -o -path 'debian/tmp*' -print
debian/control
debian/files
debian/substvars
debian/tmp
Your list may differ. Treat debian/tmp as disposable package staging, not a copy of your source: if you put hand-created files there, move them out first.
3. Understand what clean removes
- Removes
debian/filesanddebian/files.new, which are produced bydpkg-distaddfile. - Removes
debian/substvarsanddebian/substvars.new, which are produced bydpkg-shlibdeps. - Removes the entire
debian/tmpstaging directory used while assembling package contents.
It does not clean up for your compiler or build system. A generated Makefile, object files or a CMake build directory are all outside this command's documented scope; keep removing those in your existing build-system cleanup, and run that cleanup before the dpkg step.
Warning
This is a destructive operation for those paths. It is normally safe because they are only generated package-build state, but recovery means recreating them by running the relevant build steps again. Do not treat it as a general-purpose rm replacement.
4. Add the command to debian/rules
For an autoconf-style package, put the dpkg cleanup after the package's own distclean action in the clean target:
clean:
[ ! -f Makefile ] || $(MAKE) distclean
dpkg-buildtree clean
The shell test avoids invoking make distclean when no Makefile exists. The second line is an ordinary command: do not prefix it with sudo. Package builds and clean targets should normally run as an unprivileged user; running them as root can leave root-owned files that your normal account cannot remove later.
If your rules file already has a clean target, add the command there rather than creating a second one, and keep any project-specific cleanup that comes before it. A Makefile target defined twice can behave unpredictably, and replacing existing cleanup can leave stale compiler or generated files behind.
5. Run and verify the cleanup
After saving debian/rules, invoke the target from the source-tree root. This may remove generated state, so check the path again first:
$ pwd
/path/to/source-package
$ make clean
$ printf 'clean exit status: %s\n' "$?"
clean exit status: 0
A quiet command and exit status zero are normal. Confirm the dpkg-managed paths are actually gone:
$ for path in debian/files debian/files.new debian/substvars debian/substvars.new debian/tmp; do
> test ! -e "$path" || printf 'still present: %s\n' "$path"
> done
No output from the loop means those paths are gone. If your build system deliberately recreates one of them during its own cleanup, inspect the target and run the checks again. Do not assume make clean succeeding means every generated file in the tree has vanished.
6. Diagnose the common failures
Run dpkg-buildtree with no command and it reports missing action, exiting with status 2. Use dpkg-buildtree clean, not just the bare program name:
$ dpkg-buildtree
dpkg-buildtree: error: missing action
Use --help for program usage information.
$ printf 'exit status: %s\n' "$?"
exit status: 2
If the command reports an unknown action, check dpkg-buildtree --help and the local manpage: current upstream documentation describes is-rootless from dpkg 1.22.12, but this machine's dpkg 1.22.6 does not support it. Do not infer feature support from a newer web page.
If a file remains, first check you are in the intended source tree and that debian/control exists, then inspect the leftover path. This command only removes the documented dpkg paths; it will not touch a similarly named custom directory or your compiler's output. Recovery is usually to rerun the package's normal build or dependency-generation step. There is no separate undo command.
Done means
- Version checked. You confirmed the installed
dpkg-buildtreeversion and its supported command list. - Tree confirmed. You checked the source-tree path and the presence of
debian/control. - Order preserved. Your existing build-system cleanup still runs before the dpkg cleanup.
- Scope respected.
dpkg-buildtree cleanremoved only the documented dpkg-generated files anddebian/tmp. - Result verified. You checked the outcome and kept the whole operation unprivileged.