How to build packages locally

Note

This is about building an existing package locally. If you want to build a new package, please refer to How to create a new package.

In Ubuntu, packages can be built in several ways, depending on the intended artifacts. The standard and recommended way to build packages for Ubuntu is with dpkg-buildpackage and sbuild. This ensures that the build dependencies are properly declared and that the resulting package is reproducible.

dpkg-buildpackage is used to build source-only packages.

sbuild is used to build binary-only and source + binary packages.

PPAs and the Archive permit exclusively source-only package uploads, however it is best practice to first perform a local binary build and fix any potential issues before uploading.

To let the Launchpad infrastructure build packages for you, see How to build packages in a PPA.

Prerequisites

Complete the following sections from How to set up for Ubuntu development:

Fetching the package source

See How to get the source of a package for instructions on how to fetch the source of a package. You need the source to build it locally.

Building packages

Issue sbuild build commands from the source package directory that contains debian/:

$ cd <package>/debian/

sbuild allows for targeting builds towards specific releases of Ubuntu. This is useful for testing builds in the same environment as the intended upload target.

Specify the release using the --dist= (-d) option:

$ sbuild --dist=<RELEASE>

where <RELEASE> is the name of the Ubuntu release (e.g. resolute).

Tip

If you have set a default distribution in ~/.config/sbuild/config.pl, you can omit the -d option to build for the default release.

Building binary-only packages

By default, sbuild builds a binary-only package. Run the following command to build a binary package for a specific release:

$ sbuild --dist=<RELEASE>

This produces architecture-specific binary packages without generating a source package and is mostly useful for packages you need to test locally.

Building source-only packages

To build a source-only package for a specific release, the current recommended practice is to use dpkg-buildpackage instead of sbuild:

$ dpkg-buildpackage --build=source --no-check-builddeps --no-pre-clean

The flags used have the following meaning:

  • --build=source (-S): source-only build

  • --no-check-builddeps (-d): do not check build dependencies

  • --no-pre-clean (-nc): do not clean the source tree before build

Building both source and binary packages

To build both source and binary packages for a specific release, use the --source (-s) option:

$ sbuild --source --dist=<RELEASE>

Note

Launchpad rejects uploads that contain both binaries and sources.

Useful sbuild options

Parallel building:

To speed up the build, set the parallel option through the DEB_BUILD_OPTIONS environment variable. For example:

$ DEB_BUILD_OPTIONS="parallel=3" sbuild --chroot <RELEASE>-<ARCH>[-shm]
Run lintian after the build:
--run-lintian [--lintian-opts="-vIiL +pedantic"]
Large package linting:

Some large packages take a long time to lint. To avoid lintian after the build:

--no-run-lintian

Signing the changes file

For a source package to be accepted by Launchpad, it must be signed. If you specify key_id in your sbuild configuration, this is used. Otherwise, sign the source package manually with the debsign tool:

$ debsign ../<filename>_source.changes

Tip

To automatically find the changes file, create a script that extracts the info from debian/changelog:

$ source_package=$(dpkg-parsechangelog -n1 --show-field Source)
$ version=$(dpkg-parsechangelog -n1 --show-field Version)
$ debsign "../${source_package}_${version}_source.changes

Advanced usage

In some cases, builds may be more complex and require additional configuration. For example, you may need to build for a different architecture or use locally built dependencies.

Building for a different architecture (cross-building)

Note

Cross-building requires the schroot backend. The unshare backend does not currently support cross-building. See the Debian sbuild wiki for details.

Without unshare (additional setup required)

Building for a different architecture without unshare requires using an emulated schroot.

Make sure you have followed the schroot setup for sbuild in How to set up for Ubuntu development before proceeding.

To setup an emulated schroot, use the mk-sbuild command from the ubuntu-dev-tools package.

Install ubuntu-dev-tools:

$ sudo apt install ubuntu-dev-tools

Then, create the schroot with the mk-sbuild command:

$ mk-sbuild --arch=<ARCH> <RELEASE>

where <ARCH> is the target architecture (e.g. arm64).

When building with sbuild, specify the target architecture with the --arch= option:

$ sbuild --arch=<ARCH> --dist=<RELEASE>

Building for architecture variants

Some architectures have variants (e.g. amd64 has amd64v3). To build for an architecture variant, specify the variant as an argument to --host=:

$ sbuild --host=<ARCH_VARIANT> --dist=<RELEASE>

where <ARCH_VARIANT> is the architecture variant (e.g. amd64v3).

Using locally built dependencies

To use a locally built a dependency in your build, specify the path to the dependency or a directory of dependencies with the --extra-package option:

$ sbuild --extra-package=/path/to/dependency.deb -d <RELEASE>

To specify extra packages in your sbuild configuration file:

$extra_packages = [
  # '/path/to/dependency.deb',
];

This way, it is possible to quickly toggle between using the locally built dependency by commenting/uncommenting the path in the configuration file.

Other build tools

While sbuild is the recommended tool for building packages locally, there are other tools that can be used for building packages. These include:

  • pbuilder(8) - a tool that builds packages in a clean chroot environment, similar to sbuild. It is less commonly used than sbuild but can be useful in certain situations.

  • cowbuilder(8) - a wrapper for pbuilder that builds packages in a clean chroot environment using copy-on-write filesystems. It is similar to pbuilder but can be faster for subsequent builds.