Home / Alt manpages / deb-src-rules(5)

  • deb-src-rules(5)
  • File format
  • linux

Write a Valid debian/rules Makefile for a Source Package

Miss one target in debian/rules and your Debian build falls over twenty minutes in, long after you stopped watching. This guide gives you an executable Makefile with every target the package tools expect, unprivileged build work, and a visible privileged boundary. Allow about 20 minutes for a first rules file and 10 more to test it.

You need:

  • Tools. The make command and the dpkg-dev package.
  • A source tree. A Debian source-package directory you can edit.
  • A stand-in name. The examples use a placeholder package called sample-tool. Replace it with your real package.

Before you start

This guide follows the deb-src-rules(5) shipped by dpkg-dev 1.22.6ubuntu6.6 on the system used to write it. The installed manual says debian/rules is an executable Makefile, normally starting with #!/usr/bin/make -f. Check your own installation before relying on version-specific details:

dpkg-query -W -f='${Package} ${Version}\n' dpkg-dev
man deb-src-rules

The required target names are clean, build-indep, build-arch, build, binary-indep, binary-arch and binary. The manual describes the interface and privilege expectations. It does not prescribe the commands inside each target.

1. Create the executable file

From the top of the source tree, create debian/rules with a shebang and a minimal dependency graph. The example is deliberately conservative: the build targets create a harmless marker, and the binary targets show the required relationships without pretending to build a real package.

cd /path/to/sample-tool
mkdir -p debian
touch debian/rules
chmod 0755 debian/rules
#!/usr/bin/make -f

build-indep build-arch: build-stamp

build: build-indep build-arch

build-stamp:
\tprintf '%s\n' 'build completed' > $@

binary-indep: build-indep

binary-arch: build-arch

binary: binary-indep binary-arch

clean:
\trm -f build-stamp

Tip

The tab before each command is significant. A run that reports "missing separator" usually has spaces where Make needs a tab.

A real package replaces the marker recipe with its compiler, generator and packaging commands. If it uses debhelper, its rules file may delegate unknown targets to debhelper. That needs the package's declared build dependencies, so do not copy it into an unrelated project.

2. Keep build and binary work separate

  • build-indep covers files needed by architecture-independent packages.
  • build-arch covers files needed by architecture-dependent packages.

Both must exist even when that package type does not, so an empty target is valid when there is nothing to do in that branch.

build must cover both kinds of build work, either by depending on those targets or by doing equivalent work itself. The example uses dependencies, so a caller selecting one branch does not accidentally run unrelated work.

The binary targets produce packages. binary-indep must reach build-indep or build. binary-arch must reach build-arch or build. binary must reach the binary branches. These are Make dependencies, not comments: they are what lets tools request one package class safely.

Warning

Do not make a build target require root. The manual says clean, binary-indep, binary-arch and binary are called with root privileges, but a clean implementation should still work for an ordinary user wherever possible. Root can hide ownership mistakes and make the next build harder to reproduce.

3. Verify the graph as an ordinary user

Run the non-privileged targets first. These commands change files inside your source tree, so inspect the directory before running them if it holds uncommitted work.

make -f debian/rules build-indep
make -f debian/rules build-arch
make -f debian/rules build
test -f build-stamp && printf '%s\n' 'build-stamp exists'

Expected output ends with:

build-stamp exists

Make may say a target is already up to date on later runs. That is normal. Verify the dependency structure directly with a dry run:

make -n -f debian/rules binary

Checkpoint

The dry run shows the commands for both build branches before the binary work. Because -n executes nothing, it is a safe check when a real binary target would invoke compilers, generators or installers.

4. Test cleanup deliberately

Warning

clean may remove build products, and package tooling calls it with root privileges. Read the recipe before running it, and never use a broad removal command that could reach outside the source tree.

make -f debian/rules clean
test ! -e build-stamp && printf '%s\n' 'clean removed the marker'

Expected output is:

clean removed the marker

Recovery

If cleanup fails part-way, restore tracked files from version control with your normal project workflow, then remove only the generated paths you have identified. Do not run the binary targets with sudo just to get past a permissions error. Find which recipe created the wrong ownership and fix that recipe.

5. Connect it to a real package build

Once the rules file holds real package commands, run the package builder from the parent of the source tree:

cd /path/to
dpkg-buildpackage -us -uc

The -us and -uc options skip signing the source and changes files during a local test. They do not make a build safe if the rules file itself does something unsafe. A successful build writes package artefacts beside the source directory, not inside debian/. Check the result without installing it:

ls -l ../sample-tool_*.deb ../sample-tool_*.changes 2>/dev/null

If you only want to test the file's interface, go back to make -f debian/rules build and the dry-run check. Package creation can invoke maintainer scripts or other tooling, so treat an actual install as a separate, deliberate test. Nothing in deb-src-rules(5) says a package should be installed as part of its build.

Common traps

  • Missing no-op target. A target left out because the package has no architecture-independent or architecture-dependent output still breaks the interface. Keep it and make it do nothing.
  • Missing dependency. A binary-arch target that does not depend on build-arch can produce a package from stale or missing files. Say so in Make.
  • Root during build. Commands that need root in build make reproducible builds difficult and can leave root-owned files in a user's checkout.
  • sudo make clean. It conceals the ownership problem and makes later cleanup need more privileges.
  • Copy-paste damage. Changing the shebang, target names or tabs while copying an example can turn a valid Makefile into one that fails before any package command runs.

Done means

  • Executable. debian/rules is executable and begins with a Make shebang.
  • Complete. All seven required targets exist, including no-op branches where necessary.
  • Build reaches both branches. build covers the architecture-specific and architecture-independent work.
  • Binary targets link back. Each one reaches its matching build target.
  • No root needed. Build targets work unprivileged, and cleanup has been tested with its destructive scope understood.
  • Dry run passes. It shows the intended dependency order before any real package build.