debhelper(7)
๐ฆ debhelper(7) โ the whole debhelper tool suite ๐ฆ
๐ NAME
So bestie, this is the manual page for debhelper โ manual, section 7 โ and it's literally the debhelper tool suite. That's the whole vibe. The tools, the squad, the girlies. ๐
โจ SYNOPSIS โจ
dh_* [-v] [-a] [-i] [--no-act] [-ppackage] [-Npackage] [-Ptmpdir]
๐ธ DESCRIPTION ๐ธ
Okay so here's the tea: debhelper exists to help you build a Debian package. That's it, that's the job. ๐
The philosophy behind debhelper โ and honestly this is lowkey the most iconic part โ is that it gives you a collection of small, simple, and easily understood tools. You use them inside debian/rules to automate all the common little chores that come up when you're building a package. Which means: less work for you, the packager. ๐ซถ
And there's a glow-up side effect too: because of this, these tools can get changed if Debian policy shifts, and any package using them just needs a rebuild to be in compliance with the new policy. No cap. Slay.
A typical debian/rules file that uses debhelper will call several debhelper commands one after another, or it'll use dh(1) to automate the whole process for you. And if you wanna see what these rules files actually look like, examples of rules files that use debhelper live in:
/usr/share/doc/debhelper/examples/
So to make a brand new Debian package with debhelper, you can literally just copy one of the sample rules files and edit it by hand. โจ Or, if you want a lil assist, you can try the dh-make package โ it contains a dh_make command that partially automates the process for you. ๐
And if you want a more gentle, hold-your-hand introduction, the maint-guide Debian package has a tutorial about making your first package using debhelper. Perfect for baby's first package fr fr. ๐ผ
One big rule, and I need you to internalise this: except where a tool explicitly says otherwise, all the debhelper tools assume they're being run from the root directory of an unpacked source package. That's how they can find files like debian/control when they need them. Run them from the wrong place and they're just gonna be confused, bestie. ๐
๐ DEBHELPER COMMANDS ๐
Here's the full list of debhelper commands you can use. Go read their man pages if you want the full scoop on each one. ๐
dh_assistant(1)โ tool for supporting debhelper tools and provide introspectiondh_auto_build(1)โ automatically builds a packagedh_auto_clean(1)โ automatically cleans up after a builddh_auto_configure(1)โ automatically configure a package prior to buildingdh_auto_install(1)โ automatically runsmake installor similardh_auto_test(1)โ automatically runs a package's test suitesdh_bugfiles(1)โ install bug reporting customization files into package build directoriesdh_builddeb(1)โ build Debian binary packagesdh_clean(1)โ clean up package build directoriesdh_compress(1)โ compress files and fix symlinks in package build directoriesdh_computeautosubstvars(1)โ compute substvars relevant to most packagesdh_dwz(1)โ optimize DWARF debug information in ELF binaries viadwzdh_fixperms(1)โ fix permissions of files in package build directoriesdh_gencontrol(1)โ generate and install control filedh_icons(1)โ Update caches of Freedesktop iconsdh_install(1)โ install files into package build directoriesdh_installalternatives(1)โ install declarative alternative rulesdh_installcatalogs(1)โ install and register SGML Catalogsdh_installchangelogs(1)โ install changelogs into package build directoriesdh_installcron(1)โ install cron scripts intoetc/cron.*dh_installdeb(1)โ install files into theDEBIANdirectorydh_installdebconf(1)โ install files used by debconf in package build directoriesdh_installdirs(1)โ create subdirectories in package build directoriesdh_installdocs(1)โ install documentation into package build directoriesdh_installemacsen(1)โ register an Emacs add on packagedh_installexamples(1)โ install example files into package build directoriesdh_installgsettings(1)โ install GSettings overrides and set dependenciesdh_installifupdown(1)โ installif-upandif-downhooksdh_installinfo(1)โ install info filesdh_installinit(1)โ install service init files into package build directoriesdh_installinitramfs(1)โ install initramfs hooks and setup maintscriptsdh_installlogcheck(1)โ install logcheck rulefiles intoetc/logcheck/dh_installlogrotate(1)โ install logrotate config filesdh_installman(1)โ install man pages into package build directoriesdh_installmenu(1)โ install Debian menu files into package build directoriesdh_installmime(1)โ install mime files into package build directoriesdh_installmodules(1)โ register kernel modulesdh_installpam(1)โ install pam support filesdh_installppp(1)โ install pppip-upandip-downfilesdh_installsystemd(1)โ install systemd unit filesdh_installsystemduser(1)โ install systemd unit filesdh_installsysusers(1)โ install and integrates systemd sysusers filesdh_installtmpfiles(1)โ installtmpfiles.dconfiguration filesdh_installudev(1)โ install udev rules filesdh_installwm(1)โ register a window managerdh_installxfonts(1)โ register X fontsdh_link(1)โ create symlinks in package build directoriesdh_lintian(1)โ install lintian override files into package build directoriesdh_listpackages(1)โ list binary packages debhelper will act ondh_makeshlibs(1)โ automatically create shlibs file and calldpkg-gensymbolsdh_md5sums(1)โ generateDEBIAN/md5sumsfiledh_missing(1)โ check for missing filesdh_movefiles(1)โ move files out ofdebian/tmpinto subpackagesdh_movetousr(1)โ canonicalize location according to merged-/usrdh_perl(1)โ calculates Perl dependencies and cleans up after MakeMakerdh_prep(1)โ perform cleanups in preparation for building a binary packagedh_shlibdeps(1)โ calculate shared library dependenciesdh_strip(1)โ strip executables, shared libraries, and some static librariesdh_systemd_enable(1)โ enable/disable systemd unit filesdh_systemd_start(1)โ start/stop/restart systemd unit filesdh_testdir(1)โ test directory before building Debian packagedh_testroot(1)โ ensure that a package is built with necessary level of root permissionsdh_ucf(1)โ register configuration files with ucfdh_update_autotools_config(1)โ Update autotools config filesdh_usrlocal(1)โ migrateusr/localdirectories to maintainer scripts
๐ Deprecated Commands
A few debhelper commands are deprecated and should not be used. Like, don't. I'm begging. ๐
dh_installmanpages(1)โ old-style man page installer (deprecated)
๐ง Other Commands
Here's the vibe check: if a program's name starts with dh_, and that program is not on the lists above, then it is not part of the debhelper package โ but it should still work like the other programs described on this page. ๐
โจ DEBHELPER CONFIG FILES โจ
bestie okay so here's the tea ๐ซ โ tons of debhelper commands read files out of debian/ to decide what they do. Yeah yeah, debian/changelog and debian/control live in every package, not just the debhelper girlies, but there's a whole extra little stash of files that tweak how specific commands behave. They're usually named debian/package.foo โ and obviously package gets swapped for whichever package is being acted on ๐
Like, dh_installdocs reads debian/package.docs to get the list of doc files it's gonna install. Every command's own man page tells you the names and formats it wants. Generally these files are just "one file per line, go off", though some tools use pairs of file+destination or slightly more extra formats ๐
Heads up: ifdebian/controlonly lists one binary package, debhelper will happily fall back todebian/foowhen there's nodebian/package.foo. In compat levels before compat 15, that fallback also kicked in for the first binary package listed when you've got multiple binaries. But honestly? Keep thepackage.prefix โ it's more explicit and it's straight up required when you upgrade to compat 15. no cap ๐ฅ
There's also some special-case files where debhelper always falls back to the prefixless version โ things like debian/copyright and debian/changelog, because those are used and needed for all binary packages anyway. iconic behaviour honestly ๐
And in rare cases you might want different versions of a file per arch or OS. If debian/package.foo.ARCH or debian/package.foo.OS exist โ where ARCH and OS match the output of dpkg-architecture -qDEB_HOST_ARCH / dpkg-architecture -qDEB_HOST_ARCH_OS โ then those win over the more general files ๐ฆ
Mostly these config files are all about lists: docs to install, examples to install, files to move, that whole vibe. When it makes sense, you can use standard shell wildcards (? and * and [..] character classes) inside them. You can also drop comments โ any line starting with # gets ignored ๐
The syntax is intentionally kept super simple so it's easy to read, understand, and edit. it's giving "low effort, high reward" ๐ธ
๐ซ Substitutions in debhelper config files
So in compatibility level 13 and later, you can do little substitutions inside debhelper config files โ but only for these specific tools:
dh_cleandh_installdh_installcatalogsdh_installdebdh_installdirsdh_installdocsdh_installexamplesdh_installinfodh_installmandh_installwmdh_linkdh_missingdh_ucf
Every substitution variable looks like ${foo} and yes the braces are mandatory, no skipping them bestie. Variable names are case-sensitive and can contain alphanumerics (a-zA-Z0-9), hyphens (-), underscores (_), and colons (:). The first character has to be alphanumeric, periodt.
If you need a literal dollar sign that doesn't trigger a substitution, you can either use the ${Dollar} substitution or the sequence ${} ๐ซถ
Here's what you can expand:
DEB_HOST_*,DEB_BUILD_*,DEB_TARGET_*โ expands to the relevantdpkg-architecture(1)value (basically like runningdpkg-architecture -qVARIABLE_HERE). When in doubt, theDEB_HOST_*variant is the one that works for both native and cross builds. And for performance reasons, debhelper tries to resolve these names from the environment first before askingdpkg-architecture(1)โ mostly mentioning it for completeness, it won't matter in most cases.Dollarโ expands to a single literal$-symbol. This symbol will never be considered part of a substitution variable. So like:
# Triggers an error
${NO_SUCH_TOKEN}
# Expands to the literal value "${NO_SUCH_TOKEN}"
${Dollar}{NO_SUCH_TOKEN}
This variable is equivalent to the sequence ${} and the two can be used interchangeably โจ
Newline,Space,Tabโ expands to a single ASCII newline, space and tab respectively. Super useful when you need a literal whitespace character (like a space) somewhere it'd otherwise get stripped or treated as a separator.env:NAMEโ expands to the environment variableNAME. That env var must be set (it's fine if it's set to the empty string).
Real talk: every variable has to expand to a defined value. So if debhelper sees${env:FOO}, it will insist that the environment variableFOOis set โ empty string is allowed, unset is not ๐ญ
Substitution limits
To dodge infinite loops and resource exhaustion, debhelper bails out with an error if a token contains too many substitution variables (50) or if the total size of the expanded value blows past a certain size (4096 characters or 3x the length of the original input โ whichever is bigger).
And note: the limit is per token. Every helper gets to define its own idea of what a token is. In the common case of files like debian/package.install, each token is a file/path name ๐
Substitution limitations: filtering
The built-in substitution cannot be used to "filter" content out. If you try to create "comments" or "empty lines" via substitution, those variables just end up being considered a token in their own right with the content you gave. ๐
If you actually want filtering, go use an executable debhelper config file with dh-exec as interpreter โ dh-exec supports several features right out of the box. Just keep in mind dh-exec has its own substitution logic that can interact with debhelper's, so don't get it twisted ๐
๐ง Executable debhelper config files
Need more flexibility? Many debhelper tools (like dh_install(1)) support just executing a config file as a script. slay ๐
To use it: mark the config file as executable (e.g. chmod +x debian/package.install) and the tool will try to execute it and use the script's output. In lots of cases you can set dh-exec(1) as the interpreter of the config file to keep most of the original syntax while getting the extra flexibility you need ๐ฆ
When you're using executable debhelper config files, please be aware of this:
- The executable config file must exit with success (i.e. its return code should indicate success).
- In compatibility level 13+, the output will be subject to substitutions (see "Substitutions in debhelper config files") where the tool supports them. Be careful if your generator also provides substitutions, because that's a one-way ticket to unnecessary confusion ๐ตโ๐ซ Notably, the commonly used
dh-exectool has its own substitution support. - Otherwise, the output is used exactly as-is. And notably, debhelper will not expand wildcards or strip comments or strip whitespace in the output it reads. (
dh-exechas an output filter on by default that prunes those things out for you. ๐ )
If you need the package to build on a file system where you can't disable the executable bit, then reach for dh-exec(1) and its strip-output script ๐
๐ฅ SHARED DEBHELPER OPTIONS ๐ฅ
These command line options are supported by all debhelper programs. every single one. periodt ๐
-v,--verboseโ Verbose mode: shows the commands that modify the package build directory. Note that verbose mode may also spit out other "internal" commands that don't directly affect the package build directory.--no-actโ Do not really do anything. If you use it with-v, the result is that the command outputs what it would have done. ghost mode ๐ป-a,--archโ Act on architecture dependent packages that should be built for theDEB_HOST_ARCHarchitecture.-i,--indepโ Act on all architecture independent packages.-ppackage,--package=packageโ Act on the package named package. You can specify this option multiple times to make debhelper operate on a given set of packages.-s,--same-archโ Deprecated alias of-a. This option is removed in compat 12. ๐-Npackage,--no-package=packageโ Do not act on the specified package, even if an-a,-i, or-poption lists that package as one that should be acted on.--remaining-packagesโ Do not act on the packages that have already been acted on by this debhelper command earlier (i.e. if the command is present in the package debhelper log). Like, if you need to call a command with special options for just a couple of binary packages, pass this option to the last call of the command so the rest of the packages get processed with default settings โจ-Ptmpdir,--tmpdir=tmpdirโ Use tmpdir for the package build directory. The default isdebian/package.--mainpackage=packageโ Deprecated: this option has no practical use in compat 15 or later, since the behaviour it affects is removed in compat 15. This little-used option changes which package debhelper considers the "main package" โ that is, the first one listed indebian/control, and the one for whichdebian/foofiles can be used instead of the usualdebian/package.foofiles.-O=option|bundleโ This is used bydh(1)when passing user-specified options to all the commands it runs. If the command supports the specified option or option bundle, it takes effect. If the command doesn't support the option (or any part of an option bundle), it just gets ignored. shrug ๐
๐ธ COMMON DEBHELPER OPTIONS ๐ธ
These command line options are supported by some debhelper programs โ check each program's man page for a full explanation of what each one does, bestie ๐
-nโ Do not modifypostinst,postrm, etc. scripts.-Xitem,--exclude=itemโ Exclude an item from processing. You can use this option multiple times to exclude more than one thing. The item is typically part of a filename, and any file containing the specified text will be excluded ๐ซ-A,--allโ Makes files or other items specified on the command line take effect in ALL packages acted on, not just the first one. glow up for everyone โจ
๐ธ BUILD SYSTEM OPTIONS ๐ธ
okay so every single one of the dh_auto_* debhelper programs takes these command line options. These programs vibe with a whole buffet of build systems, and normally they just heuristically figure out which one to use and how to use it (iconic behavior tbh). But you can totally override the default behavior with these options. Normally you hand them to dh(1), which then passes them along to all the dh_auto_* programs. Chain reaction, bestie. ๐ซ
-Sbuildsystem,--buildsystem=buildsystem โ say it with your chest: force the use of the specified buildsystem, instead of letting it try to auto-select one that might work for the package. And if you passnoneas buildsystem, that disables auto-selection entirely. bye bestie, no build system for you ๐-Ddirectory,--sourcedir=directory,--sourcedirectory=directory โ assume the original package source tree lives at the specified directory, rather than the top level directory of the Debian source package tree.
โ ๏ธ warning bestie โ ๏ธ The--sourcedirvariant matches a similarly named option indh_installanddh_missing(etc.) for historical reasons. Like, they have a similar name but they have very distinct purposes, and in some cases it can cause errors when this variant gets passed todh(whendhthen passes it on to all the tools). iykyk, it's messy. ๐ญ
-B[directory],--builddir[=directory],--builddirectory[=directory] โ turns on out of source building and uses the specified directory as the build directory. If you omit the directory parameter, a default build directory gets chosen for you. โจ
If you don't specify this option, the build happens in source by default โ unless the build system requires or prefers out of source tree building. In that case, the default build directory gets used even if --builddirectory is not specified. Noted. ๐
And if the build system prefers out of source tree building but still allows in source building, you can re-enable the in source one by passing a build directory path that is the same as the source directory path. Sneaky but it works. ๐ซถ
--parallel,--no-parallelโ controls whether parallel builds happen, if the underlying build system supports them. The number of parallel jobs is controlled by theDEB_BUILD_OPTIONSenvironment variable ("Debian Policy, section 4.9.1") at build time. It might also be subject to a build system specific limit, so don't come for me if it caps itself. ๐
If neither option is specified, debhelper currently defaults to --parallel in compat 10 (or later) and --no-parallel otherwise. the way that it just picks for you ๐
As an optimization, dh will try to avoid passing these options to subprocesses, if they are unnecessary and the only options passed. Notably this happens when DEB_BUILD_OPTIONS does not have a parallel parameter (or its value is 1). Efficient queen. ๐
--max-parallel=maximum โ this option implies--paralleland lets you further limit the number of jobs that can be used in a parallel build. If the package build is known to only work with certain levels of concurrency, you can set this to the maximum level that is known to work, or that you wish to support. ๐ฅ
Notably, setting the maximum to 1 is effectively the same as using --no-parallel. Same energy fr fr.
--reload-all-buildenv-variablesโ by default,dh(1)will compute several environment variables (e.g. by usingdpkg-buildflags(1)) and cache them, so it doesn't make all thedh_auto_*tools recompute them. Caching era. ๐
When you pass this option, the concrete dh_auto_* tool will ignore the cache from dh(1) and retrigger a rebuild of these variables. This is useful in the very rare case where the package needs to do multiple builds but with different ...FLAGS options. A concrete example would be needing to change the -O parameter in CFLAGS in the second build:
export DEB_CFLAGS_MAINT_APPEND=-O3
%:
dh $@
override_dh_auto_configure:
dh_auto_configure -Bbuild-deb ...
DEB_CFLAGS_MAINT_APPEND=-Os dh_auto_configure \
--reload-all-buildenv-variables -Bbuild-udeb ...
Without --reload-all-buildenv-variables in the second call to dh_auto_configure(1), the change in DEB_CFLAGS_MAINT_APPEND would be ignored, because dh_auto_configure(1) would use the cached value of CFLAGS set by dh(1). caught in 4k using stale flags ๐
This option is only available with debhelper (>= 12.7~) when the package uses compatibility level 9 or later. So like, check your compat before you try it bestie.
--list,-lโ list all build systems supported by debhelper on this system. The list includes both default and third party build systems (marked as such). It also shows which build system would be automatically selected, or which one is manually specified with the--buildsystemoption. It's giving receipts. ๐งพโจ
โจ COMPATIBILITY LEVELS โจ
so from time to time, major non-backwards-compatible changes need to be made to debhelper, to keep it clean and well-designed as needs change and its author gains more experience. Which, honestly? Respect. ๐
But to prevent those major changes from breaking existing packages, the concept of debhelper compatibility levels was introduced. You must tell debhelper which compatibility level it should use, and it modifies its behavior in various ways. No cap, it's mandatory. ๐จ
In current debhelper, you can specify the compatibility level in debian/control by adding a Build-Depends on the debhelper-compat package. For example, to use v14 mode, ensure debian/control has:
Build-Depends: debhelper-compat (= 14)
This also serves as an appropriate versioned build dependency on a sufficient version of the debhelper package, so you do not need to specify a separate versioned build dependency on the debhelper package โ unless you need a specific point release of debhelper (such as for the introduction of a new feature or bugfix within a compatibility level). two birds, one stone, periodt ๐
Note that debhelper does not provide debhelper-compat for experimental or beta compatibility levels. Packages experimenting with those compatibility levels should put the compat level in the X-DH-Compat field of the Source stanza of the debian/control file (or, if only for selected commands, the DH_COMPAT environment variable). Living on the edge, we love that for you ๐ฆ
Historically, debhelper required specifying the compatibility level in the file debian/compat, and debhelper up to version 14 supports this for backward compatibility. To use this method, the debian/compat file should contain the compatibility level as a single number, and no other content. Like literally nothing else. If you specify the compatibility level by this method, your package will also need a versioned build dependency on a version of the debhelper package equal to (or greater than) the compatibility level your package uses. So, if you specify compatibility level 14 in debian/compat, ensure debian/control has:
Build-Depends: debhelper (>= 14~)
Note that you must use exactly one method for specifying the default debhelper compat level of the package. Whenever possible, the debhelper-compat build-dependency is recommended. do the recommended thing bestie, it's the moment ๐
If needed be, the DH_COMPAT environment variable can be used to override the compat level for a given command. The feature is mostly useful for either temporarily upgrading a few commands to a new compat level, or keeping a few commands on a lower compat level. The feature is best used sparingly, as it effectively introduces special-cases into the debian/rules file that may be surprising to maintainers or reviewers (or, in the long term, to yourself). ๐ญ Setting a global DH_COMPAT environment variable is not recommended. Don't do it. Please. ๐
Unless otherwise indicated, all debhelper documentation assumes that you are using the most recent compatibility level, and in most cases does not indicate if the behavior is different in an earlier compatibility level. So if you are not using the most recent compatibility level, you're advised to read below for notes about what is different in earlier compatibility levels. read the fine print, bestie ๐๐
Supported compatibility levels
The list of supported compatibility levels and the related upgrade check list has moved to debhelper-compat-upgrade-checklist(7). Go go go, it's over there โจ๐
๐ซถ
๐ธ NOTES ๐ธ
okay bestie listen up, these are the lore drops you need before anything else makes sense ๐
๐ซถ Multiple binary package support ๐ซถ
so if ur source package pops out more than one binary package, all the debhelper programs are just gonna default to acting on every single one of them when u run them. which is normally whatever, exceptโฆ if ur source builds one arch-dependent package AND one arch-independent package, that default is lowkey wrong โ๐ญ because the arch-dependent ones need to be built in the binary-arch target of debian/rules, and the arch-independent ones go in the binary-indep target.
so to help u out (and to give u way more control over which packages get touched by debhelper programs), all debhelper programs accept the -a, -i, -p, and -s parameters. and here's the thing โ these parameters are cumulative. if u give none of them, debhelper programs default to acting on all packages listed in the control file, with the exceptions below ๐
first exception: any package whose Architecture field in debian/control doesn't match the DEB_HOST_ARCH architecture gets excluded ("Debian Policy, section 5.6.8").
also, some extra packages might get excluded based on what's in the DEB_BUILD_PROFILES environment variable and the Build-Profiles fields in the binary package stanzas of debian/control, per the draft policy at https://wiki.debian.org/BuildProfileSpec.
๐ซ Interaction between package selections and Build-Profiles ๐ซ
Build-Profiles affect which packages get included by the package selection mechanisms in debhelper. generally speaking, the package selections are described assuming all packages are enabled. this section here tells u how the selections react when a package gets disabled because of the active Build-Profiles (or because there are no active Build-Profiles at all).
-a/--arch,-i/--indep, OR no selection options at all (like a rawdh_Xcall) โ the package that's disabled byBuild-Profilesis just silently excluded from the selection. heads up tho: u will get a warning if all the packages related to these selections end up disabled. and honestly in that case it generally doesn't even make sense to do the build in the first place ๐-Npackage /--no-packagepackage โ the option is accepted and effectively does nothing. iconic, honestly.-ppackage /--packagepackage โ the option is accepted, but debhelper will not act on the package.
and ngl, it does not matter whether a package is enabled or disabled by default. periodt.
๐ Automatic generation of Debian install scripts ๐
some debhelper commands will literally auto-generate parts of Debian maintainer scripts for u. if u want those auto-generated bits to land inside ur existing Debian maintainer scripts, then u gotta add #DEBHELPER# to ur scripts, right in the spot where the code should go. #DEBHELPER# gets replaced by whatever auto-generated code when u run dh_installdeb โจ
and if a script doesn't exist at all and debhelper needs to add something to it, then debhelper will just create the complete script. slay.
when u drop the #DEBHELPER# token into a script, pls pause and think about whether any of ur hand-written code has a compelling reason to show up before the #DEBHELPER# token. #DEBHELPER# will generally contain the code that starts (postinst) or stops (prerm/preinst) any services the package is providing. and often (but not always!) it's better to let the code from #DEBHELPER# run first. the common exceptions are stuff like set -e, initializing debconf (when needed), and special cases like generation or hand-written management of config files. those things should generally happen before the #DEBHELPER# token.
also: all debhelper commands that automatically generate code in this way let u disable it with the -n parameter (see above ๐).
โ ๏ธ important bestie: the inserted code is shell code, so u cannot directly use it in a Perl script. if u wanna embed it into a Perl script, here's one way to do it (and yes, they made sure$1,$2, etc are set with thesetcommand):
my $temp="set -e\nset -- @ARGV\n" . << 'EOF';
#DEBHELPER#
EOF
if (system($temp)) {
my $exit_code = ($? >> 8) & 0xff;
my $signal = $? & 0x7f;
if ($exit_code) {
die("The debhelper script failed with error code: ${exit_code}");
} else {
die("The debhelper script was killed by signal: ${signal}");
}
}
๐ Automatic injection of substvar dependencies ๐
starting with compat 14, dh_gencontrol will automatically apply relationship substvars to the relevant fields ๐ which means a bunch of substvars like ${misc:Depends} and ${shlibs:Depends} no longer need to be explicitly mentioned in debian/control. this applies to any substvar named after a field that the installed version of dpkg considers a relation or dependency-like field. for example: ${*:Pre-Depends}, ${*:Depends}, ${*:Recommends}, ${*:Conflicts}, ${*:Breaks}, ${*:Replaces}, ${*:Provides}, ${*:Built-Using}, ${*:Static-Built-Using}, etc.
๐ง Automatic generation of miscellaneous dependencies ๐ง
some debhelper commands may make the generated package need to depend on some other packages. like, if u use dh_installdebconf(1), ur package will generally need to depend on debconf. or if u use dh_installxfonts(1), ur package will generally need to depend on a particular version of xutils. keeping track of all these miscellaneous dependencies is genuinely so annoying bc they depend on how debhelper does things, so debhelper offers u a way to automate it ๐ซถ
as of compat 14, debhelper will automatically inject the relevant dependencies for u, since the dependency is done via a "relationship substvar" (peep https://lists.debian.org/debian-devel/2024/02/msg00230.html and https://lists.debian.org/debian-devel/2024/03/msg00030.html for the deets).
in earlier compat levels tho, u have to manually specify the relevant substvars in the relevant fields. typically that's ${misc:Depends} for the Depends field and ${misc:Pre-Depends} for the Pre-Depends fields.
the variables listed here are related to miscellaneous dependencies (${misc:*}) and are entirely independent of the standard ${shlibs:Depends} generated by dh_makeshlibs(1), and the ${perl:Depends} generated by dh_perl(1). for compat 13 and earlier, u will also have to add these to the respective fields when relevant ๐๐
๐ฆ Package build directories ๐ฆ
by default, all debhelper programs assume the temporary directory used for assembling the tree of files in a package is debian/package ๐
sometimes tho, u might wanna use some other temporary directory. this is supported by the -P flag! for example, "dh_installdocs -Pdebian/tmp" will use debian/tmp as the temporary directory. just know that if u use -P, the debhelper programs can only be acting on a single package at a time. so if u have a package that builds a bunch of binary packages, u will need to also use the -p flag to specify which binary package the debhelper program will act on.
๐ udebs ๐
debhelper includes support for udebs! to create a udeb with debhelper, add "Package-Type: udeb" to the package's stanza in debian/control. debhelper will try to create udebs that comply with debian-installer policy, by:
- making the generated package files end in
.udeb - not installing any documentation into a udeb
- skipping over
preinst,postrm,prerm, andconfigscripts - etc. โจ
๐ ENVIRONMENT ๐
okay bestie, this bit is all about the env vars โ the little gremlins in your shell that change how debhelper acts, or that debhelper just kinda rubs shoulders with. ๐ซถ
SUPER IMPORTANT: these have to be actual environment variables to do anything to debhelper. Not Makefile variables. Not vibes. Actual env vars. So if you're setting them indebian/rules, you gottaexportthem properly, likeexport DH_VERBOSE. ๐
๐ธ the env vars themselves ๐ธ
DH_VERBOSEโ set it to literally anything non-empty and boom, verbose mode is on. details live in the-v/--verboseoption, go peek at those.DH_QUIETโ set to a non-empty value to turn on quiet mode. debhelper won't print out the commands it's calling on your upstream build system, anddhwon't announce which subcommands it's running โ and depending on the upstream build system it might go even quieter too. it's giving "easier to spot the important stuff" โจ but also it makes the output genuinely useless as a buildd log. ๐ญ- Ignored if
DH_VERBOSEis also set, or if-v/--verbosegot passed.
- Ignored if
DH_COMPATโ temporarily says which compatibility level debhelper should run at, overriding the source package's default compat level. (temporary!! don't get attached ๐)DH_NO_ACTโ set it to1to enable no-act mode.DH_OPTIONSโ every debhelper tool will slurp up the command line arguments listed in this variable before any command option โ basically like they were prepended to the command line args. sadly though, some third-party tools might not support this variable at all and will just ignore those args. ๐- When you're using
dh(1), you can pass it options that get handed down to each debhelper command, and honestly that's generally better than usingDH_OPTIONS.
- When you're using
DH_ALWAYS_EXCLUDEโ if you set it, its value gets added to the-Xoptions of all commands that support-X. and on top of that,dh_builddebwillrm -rfanything matching that value inside your package build tree. ๐ณ- this is lowkey a lifesaver if you're building from a CVS source tree โ setting
DH_ALWAYS_EXCLUDE=CVSstops any CVS directories from sneaking into the package you build. or, if a package has a source tarball that (unwisely!!) ships CVS directories, you might want toexport DH_ALWAYS_EXCLUDE=CVSindebian/rulesso it takes effect wherever your package gets built. - you can exclude multiple things by separating them with colons, like
DH_ALWAYS_EXCLUDE=CVS:.svn
- this is lowkey a lifesaver if you're building from a CVS source tree โ setting
DH_EXTRA_ADDONSโ if set, this adds the dh addons you specify so they run in the appropriate places in the command sequence. same energy as specifying the addon with the--withflag in thedebian/rulesfile. and heads up: any--withoutcalls naming an addon that's in this env var will not run. ๐- it's meant for downstreams or specific local configs that need a debhelper addon running across multiple builds without having to patch a whole pile of rules files. but fr fr, if it's at all possible, avoid this and just use a
--withflag in the rules file instead.
- it's meant for downstreams or specific local configs that need a debhelper addon running across multiple builds without having to patch a whole pile of rules files. but fr fr, if it's at all possible, avoid this and just use a
DH_COLORS,DPKG_COLORSโ these control whether debhelper commands use colors in their text output. can be set to"always","auto"(the default!), or"never". ๐- note that
DPKG_COLORalso affects a number of dpkg related tools, and debhelper uses it assuming you want the same color setting for dpkg and debhelper. in the off-hand chance you want a different color setting for debhelper, useDH_COLORSinstead โ or in addition toDPKG_COLORS.
- note that
NO_COLORโ if no explicit request for color was given (like,DH_COLORSandDPKG_COLORSare both unset), then the mere presence of this environment variable makes the default color setting become"never".- this variable is defined per <https://no-color.org/>. in this project, the environment variables (such as
DH_COLORS) count as an explicit request for color.
- this variable is defined per <https://no-color.org/>. in this project, the environment variables (such as
CFLAGS,CPPFLAGS,CXXFLAGS,OBJCFLAGS,OBJCXXFLAGS,GCJFLAGS,FFLAGS,FCFLAGS,LDFLAGSโ by default (in any non-deprecated compat level), debhelper automatically sets these flags usingdpkg-buildflags(1)when they're unset. if you need to change the default flags, please use the features fromdpkg-buildflags(1)to do that (likeDEB_BUILD_MAINT_OPTIONS=hardening=allorDEB_CPPFLAGS_MAINT_APPEND=-DCUSTOM_MACRO=true) rather than setting the concrete variable directly. ๐HOME,XDG_*โ in compat 13 and later, these get reset before the upstream build system is invoked via thedh_auto_*helpers.HOME(for alldh_auto_*helpers) andXDG_RUNTIME_DIR(dh_auto_testonly) get set to a writable directory. every remaining variable, plusXDG_RUNTIME_DIR(except duringdh_auto_test), gets cleared. ๐งน- the
HOMEdirectory gets created as an empty directory but it's reused between calls todh_auto_*. any content persists until it's explicitly deleted ordh_cleanhappens.
- the
DEB_BUILD_OPTIONSโ go see "Supported flags in DEB_BUILD_OPTIONS" for this one. ๐- also please note: this variable should not be altered by package maintainers inside
debian/rulesto change debhelper's behavior. instead, when the maintainer needs those features, they should look at disabling the relevant feature directly (e.g. by overriding the concrete tools).
- also please note: this variable should not be altered by package maintainers inside
DEB_BUILD_MAINT_OPTIONSโ this is a dpkg specific environment variable (see e.g.dpkg-buildflags(1)). the debhelper tool suite silently ignores it. ๐- it's documented here purely because it has a similar name to
DEB_BUILD_OPTIONS, which makes some people mistakenly assume debhelper will also react to it. it will not. not even a little.
- it's documented here purely because it has a similar name to
๐ฆ Supported flags in DEB_BUILD_OPTIONS ๐ฆ
the debhelper tool suite reacts to these flags in DEB_BUILD_OPTIONS. bestie, here's the whole list:
dherroron=obsolete-compat-levelsโ this is a debhelper specific value. whendherroronis present and set toobsolete-compat-levels, debhelper tools promote deprecation warnings about old, soon-to-be-removed compat levels into full errors. ๐ฅ useful for automated checking of code relying on deprecated compat levels that are scheduled for removal. it's intended for testing purposes โ not production builds.nostripโ this value changes the content of the debs being built. the.debpackages built when it's set are therefore not bit-for-bit reproducible with a regular build in the general case. ๐ญ this value makes the official debhelper tools skip actions and helpers that either remove, detach or deduplicate debugging symbols in ELF binaries. affectsdh_dwz(1)anddh_strip(1).nocheckโ this value makes the official debhelper build systems skip runs of upstream test suites. package maintainers looking to avoid running the upstream tests should not rely on this; instead they can add an empty override target to skipdh_auto_test. affectsdh_auto_test(1).nodocโ this value changes the content of the debs being built. the.debpackages built when it's set are therefore not bit-for-bit reproducible with a regular build in the general case. this value makes several debhelper tools skip installation of documentation such as manpages or upstream provided documentation. additionally, the tools will ignore it if declared documentation is "missing", on the assumption that the documentation hasn't been built. this value effects tools likedh_installdocs(1), which knows it's working with documentation. ๐notrimdchโ this value changes the content of the debs being built. the.debpackages built when it's set are therefore not bit-for-bit reproducible with a regular build in the general case. this value makesdh_installchangelogs(1)act as if it had been passed the--no-trimoption, forcing it to forgo removing older entries from changelogs. โ๏ธ๐ซnoautodbgsym,noddebsโ the official name isnoautodbgsym. thenoddebsvariant is accepted for historical reasons. this value causes debhelper to skip generation of automatically generated debug symbol packages. affectsdh_strip(1).parallel=Nโ this value enables debhelper to use up toNthreads or processes (subject to parameters like--no-paralleland--max-parallel=M). not all debhelper tools work with parallel tasks and may silently ignore the request. this value affects many debhelper tools โ most notablydh_auto_*, which will attempt to run the underlying upstream build system with that number of threads. โกterseโ this value makes the official debhelper build systems configure upstream builds to be terse (i.e. reduce verbosity in their output). this is subject to the upstream and the debhelper build system supporting such features. this value affects mostdh_auto_*tools directly. for commands provided by the debhelper package, it also makes the tools act like theDH_QUIETenvironment variable was non-empty. ๐คซ
Unknown flags are silently ignored.
Note: third-party debhelper-like tools or third-party provided build systems may or may not react to the above flags. this tends to depend on implementation details of the tool.
๐ SEE ALSO ๐
debhelper-compat-upgrade-checklist(7)โ list of supported compat levels and an upgrade checklist for each of them. ๐/usr/share/doc/debhelper/examples/โ a set of exampledebian/rulesfiles that use debhelper. go read them, they're iconic.- <http://joeyh.name/code/debhelper/> โ the debhelper web site. ๐
๐ AUTHOR ๐
Joey Hess <joeyh@debian.org>
and that's a wrap on the whole page, bestie!! ๐โจ this was debhelper(7) from debhelper version 14.5ubuntu1, dated 2026-09-21. go forth and build packages, you absolute main character. ๐
๐๐ฆ
๐ฆ where this page comes from
- ubuntu stonking: debhelper 14.5ubuntu1 ยท GPL-2.0-or-later
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms