swirlbuild(5) File Formats Manual swirlbuild(5)

swirlbuildthe swirlbuild packager manual

TABLE OF CONTENTS

This manual includes all informations to create and maintain a swirl, as well as details about swirlbuild. It tries to be exhaustive, but cannot replace practice and analysis of already existing swirls.

Looking at swirls/oksh is a good point to get started. USUAL WORKFLOW describes a typical workflow when creating a swirl, with a real-life example.

If you want to build a swirl as a simple user, please read buildswirl(1).

The general idea of swirlbuild is to give you a lot of freedom to turn around its limitations. It will not stop you from doing stupid things, not many checks are done.

$SWIRLBUILD is used in this documentation to represent the root directory of swirlbuild, where the buildswirl(1) script can be found.

Buildfiles, known as swirls/<swirlname>/build are simple shell scripts sourced by swirlbuild. As such, standard shell conventions apply when it comes to quoting, and all our usual shell utilities can be used inside of it. dash(1) as /bin/sh is implied. Note that using utilities out of the Debian base utilities and packages pulled during the deployment of swirlbuild should be avoided, and otherwise safeguards should be added to tell the user to install said utilities.

It's recommended to use the same ordering used in $SWIRLBUILD/build.template.

Presented in alphabetical order.

(readonly) The current architecture swirlbuild is being run on, according to dpkg-architecture(1). You can use it in your buildfile if you need particular things for a given architecture.

(facultative) If your swirl breaks another package(s), put the package(s) here. It is here for convenience but should be used as a last resort. See BUILD_DEPENDS about the format used, and deb-control(5) for more informations.

(facultative) The build and test dependencies. This is a multiline shell string, with one dependency per line. Blank lines are ignored. The versioning scheme is described in deb-src-control(5), and a full example can be found in infrastructure/templates/build.template.

Note that dh_make(1) tends to add the configure/build system as a BUILD_DEPENDS out of the box. There is no TEST_DEPENDS in swirlbuild, you must specify them in BUILD_DEPENDS.

If your swirl depends on another swirl, see SWIRL_DEPENDS.

(facultative) If your swirl conflicts with an official Debian package, put the Debian package here and it will be added as a conflict. It is here for convenience but should be used as a last resort. See BUILD_DEPENDS about the format used.

(mandatory) A description for your package. This string should be 1 line long at least, but can span on several lines. The first non-empty line will be the description that will appear in dpkg -l. It should not be longer than 60 characters.

(facultative) The following lines are the long description that are shown when using apt show <PKGNAME>. When in doubt, look at infrastructure/templates/build.template.

(facultative) Epoch number of the swirl. Its value is 0 by default and is implied if not added to the buildfile. If it appears that the upstream versioning scheme changed and dpkg(1) does not see the new version as newer than the old version, you need to increment EPOCH by one. See also VERSION.

(facultative) a list of extra sources to download. This is a multiline shell string, with one URL per line. Blank lines are ignored. An example of that can be found in infrastructure/templates/build.template.

They are not extracted, just downloaded by curl(1) in $SWIRLDIR/distfiles/{PKGNAME}-{VERSION} and eventually checked against a checksum as described in THE CHECKSUM FILE. You can work with them later thanks to a prebuild hook. See also SOURCE, and comments in the download hook if these extra sources cannot be extracted by bsdtar(1), which should be used as the default extractor.

(mandatory for golang modules) The import path of the go module. This must match the "module" line that can you find in the source's go.mod. See unmaintained-swirls/golang-helloworld for an example.

(mandatory) The upstream www homepage. If there is none, leave this empty, but not undefined.

(mandatory) The license file(s) that can be found in upstream tarball. These are relative to the root of the sources or absolute, separated by space(s). If files have spaces or special characters, you should quote them. They are concatenated with one blank line between each others in debian/copyright. If the files mentioned in LICENSE are non-existant buildswirl(1) will immediatly exit with a failure. There are more informations about this in Providing a license in the package is mandatory.

(facultative) By default, swirlbuild will use a number of build jobs that is equal to the nproc(1) output. Sometimes this is not adequate, for example if the software you are building does not support parallel processing or takes too much memory. MAKE_JOBS defines the number of parallel jobs during different steps of the build. By convention, if some software needs 4GB of RAM or more by job consistently put MAKE_JOBS=1.

Adding a comment about why MAKE_JOBS is used is considered good practice.

(facultative) The extracted SOURCE tarball directory is supposed to be in the {PKGNAME}-{VERSION} format. If it is not (github for example), you can override the source directory by defining that variable.

The generated Debian package name. It is discouraged to clash your package name with Debian, if needed add a suffix, for example vim -> vim-swirl. Most often you want to use the official tools for customising an official package, using swirlbuild for that is discouraged. The Debian wiki has a tutorial for this.

(facultative) If your swirl provides a virtual package, put the package(s) here. See BUILD_DEPENDS about the format used, and deb-control(5) for more informations.

(facultative) If your swirl overwrites another package's files, put the filenames here. This one is supposed to be used with CONFLICTS. and should be used as a last resort. See BUILD_DEPENDS about the format used, and deb-control(5) for more informations.

(mandatory) There are swirl revisions, not Debian ones. They start at 1, and should be incremented if you need to modify a package without changing VERSION. If VERSION is changed, REVISION should be brought back to 1.

Debian revisions are not supported because swirlbuild ´s simplicity is leading us to not use the 3.0/quilt format but the native one, and we should not mess with Debian proper mechanics. For more informations about Debian package formats, see dpkg-source(1).

(facultative) Runtime dependencies, in the same format and restrictions than BUILD_DEPENDS. There is no LIB_DEPENDS in swirlbuild, there are generated during the Debian package creation if binaries are produced AND libraries linked. If not, like dh_python(1) managed builds, library dependencies should be mentioned in RUN_DEPENDS.

If your swirl depends on another swirl, see SWIRL_DEPENDS.

(facultative) The source tarball download location. It supports all protocols supported by curl(1), and it will be extracted by bsdtar(1) that supports the following archive formats (or use "apt show" on your version of libarchiveNN).

Only one source is allowed by dh_make(1). If you need more files to download, see EXTRA_SOURCES. OVERRIDE_SRCDIR explains the expected directory format of the extracted archive and how to cope when it is not compliant.

SOURCE can be checked against a checksum, see THE CHECKSUM FILE.

(facultative) Unused for now. If your swirl depends on other swirls, just add them to this variable in the format explained in BUILD_DEPENDS, with dependencies by order of precedence. Note that you still need to mention said depends packages name in BUILD_DEPENDS and RUN_DEPENDS. The paths must be relative to $SWIRLBUILD. For an example of this, see infrastructure/templates/build.template.

(mandatory) The upstream version of the package. The local package version will be: [{EPOCH}:]{VERSION}+swirl{REVISION}.

Debian versioning scheme is explained at deb-version(7). You can compare versions with the dpkg(1) --compare-versions flag. If it appears that the upstream versioning scheme changed and dpkg(1) does not see the new version as newer than the old version, see EPOCH.

Hooks are a fairly advanced topic, and should be used only as a last resort, unless you just want to package some local files.

They are simple shell functions that can be used for various intents. You could override internal (starting with an underscore) functions, but this is a recipe for disaster. Internal variables not detailed here should not be used as well.

The following shell variables from buildswirl(1) can be used in your hooks:

$tmpdir

The temporary directory where the upstream source and the generated dh_make(1) files are present.

$srcdir

The directory where the upstream source is. The debian/ directory is a subdirectory of it, see also THE DEBIAN SUBDIRECTORY .

$swirldir

The directory where the current buildfile being used is located.

$distdir

The directory where the files downloaded by SOURCE and EXTRA_SOURCES can be found. Useful in a prebuild hook.

Here are the available hooks:

()

Avoid using it for publicly distributed swirls, because we cannot get any checksum.

Substitute the usual source download and extraction by your own. This can be useful to create a package from local files, or use alternative download methods. At this stage, $swirldir, $distdir and $tmpdir are defined, but not $srcdir.

Everything is up to you, but the good practice is to create the ${tmpdir}/${PKGNAME}-${VERSION} directory and put files into it. Downloads should be made with curl(1). If you need a "fetcher" other than curl(1), you will need to put a safeguard asking the user to install "fetcher" on their build machine. Same for the extractor used. A simple example of this hook can be found in $SWIRLBUILD/unmaintained-swirls/justsomefiles/build.

()

Run some custom actions before the source package build. This is useful to inject files from your buildfile's files/ directory, notably a Makefile.

This is also where you can work on your EXTRA_SOURCES files that are placed in ${distdir}.

Example of this hook can be found in unmaintained-swirls/findfiles.

()

Run a custom action after the package build and repository update. Unused, but it is meant to be used to display some message to users after the build if needed.

There are meant to be used not only when you create a swirl. Final users can also make use of them as environment variables. It is recommended to keep them around in the build file until you have finished your work.

Here is the list of available debug variables:

If you define DEBUG_SOURCE, the build will stop before building the binary package and open a shell, where you can debug issues in your patches, debian/ files and so on. As soon as the shell is exited, the temporary directory is removed. That is necessary if you need to add a patch to your swirl.

At this stage the source tarball than pbuilder(8) will use is already generated as you can see if you enter the debug source shell. The SWIRLDIR environment variable is set and points to the current swirl directory.

Build a package even though it is already built. You should not use it if said package version and revision has been installed somewhere. It is here in case it appears that your built package has some issues like misplaced files.

Actually it is lowercase. Whatever is present in this directory will override what dh_make(1) did.

The Debian Maintainer Guide contains a lot of informations about what can be used to make your building process easier, simply by defining some files, like adding users, services, documentations etc.

The whole swirlbuild tree has many examples for these files.

Try your best to use the "facilities" provided by this directory. Using them is more future proof than injecting a Makefile through prebuild.

It is mandatory to include the software license, and/or the end user license agreement (EULA), and potentially other files required by upstream into the produced package if you intend to make your swirl public, and as such being used by third parties.

As mentioned in the documentation for LICENSE this variable must point to valid license file(s). swirlbuild does not include license markers to avoid misinterpretation of upstream licensing terms. Here are some special cases when upstream does not provide some valid license file(s). That list may grow over time.

  • The swirl is not distributed to the public: use simply /dev/null in LICENSE.
  • In any other case, ask upstream to add a LICENSE file. This rationale may convince them. Until a LICENSE file is provided, the swirl should stay private.

This matters for users, in case they inavertendly distribute generated Debian packages to the general public, given that the full license text and the SOURCE URL are provided in /usr/share/doc/<PKGNAME>/copyright, it respects said license conditions in many, but not all, cases.

This matters for swirls creators, in case upstream's licensing file layout is not clear and the license is misrepresented in your swirl, then contested by upstream. Upstream got to do their homework and provide either a single license file or location including all the possible licences used in their software source code. Veracrypt and PPSSPP are good examples of that.

See also LEGAL in swirlbuild(7).

This is where you can drop various files needed to the build. Note that these files are not automatically added to the build. Using the prebuild hook is recommended to do so. A good example is unmaintained-swirls/findfiles.

This is lowercase as well.

swirlbuild has a very basic patching system. Every file ending with the patch extension in the patches directory of the swirl is considered a patch to be applied. Patches management is fully manual.

Patches from VCS like git(1) cannot be pushed as is. Creating patches for swirls is shown in USUAL WORKFLOW.

Lowercase as well, this file should be present if you distribute your swirl. This contains the checksum of the downloadable SOURCE and EXTRA_SOURCES.

If SOURCE is not defined, that file is totally ignored.

While you can generate it manually with sha512sum(1), buildswirl(1) includes an option to generate it, and its usage is detailed there.

Here is the list of everything included in $SWIRLBUILD.

buildswirl

Present in that list for exhaustivity

infrastructure/

Contains mostly documentations and helper scripts.

infrastructure/bin/deploy

This script is a small helper that installs necessary packages for swirlbuild operation.

infrastructure/bin/masstest

Build all the swirls in swirls/. Used for development tests, do not try this at home.

infrastructure/bin/repoupdate

Update your repository if some packages have been removed from there. Usage is detailed in buildswirl(1).

It is also used internally by buildswirl to update the repository indices after a successful build.

infrastructure/docs/man

All the manpages for swirlbuild.

infrastructure/docs/html

All the manpages for swirlbuild in HTML format. They're up to date with the manpages, since i use them a lot, thanks to infrastructure/docs/Makefile.

infrastructure/pbuilder/hooks

Some pbuilder(8) hooks, whose names clearly indicates the intent. See its manpage for the format used.

infrastructure/templates/

Templates that you may need when creating a swirl.

logs/

swirlbuild generates logs for every build thanks to pbuilder(8).

myswirls/

Files included in this directory are not tracked by git(1). If you want to put personal swirls inside your copy of the swirlbuild repository, you can put them there.

swirls/

All the officially maintained swirls. They are demo for the project.

unmaintained-swirls/

These swirls are probably out-of-date, finally officially packaged, or kept as examples to show x or y feature. And also probably broken.

unmaintained-swirls/README.md

The status of every unmaintained swirls, and what they are featuring that can be interesting for your own swirls.

See also BUILDFILES DEBUG VARIABLES.

Used by dh_make(1) and pbuilder(8). This defines the maintainer email address present in the package.

Used by dh_make(1) and pbuilder(8). This defines the maintainer firstname, lastname present in the package. By default, it tries to fetch that from your account infos.

MAKE_JOBS
This variable can be used if it is not specified in the buildfile, and will define the numbers of parallel jobs during various steps of the build.

buildswirl(1) details basic informations on how to build a swirl and several maintenance tips. swirlbuild(7) is an intro to swirlbuild and details its deployment, scope, motivations and caveats.

The Debian Maintainer Guide is a good basic reference, as well as the debhelper(7) manpage.

pbuilder(8) maintains its own apt(8) cache. swirlbuild does not clean the /var/cache/pbuilder/result directory as well. You can clean up by using:

sudo pbuilder clean
sudo rm /var/cache/pbuilder/result/*

By default pbuilder(8) cannot access to any network when starting to build a package. This is not the case in the swirlbuild system. This avoids packaging dozen of crates or go modules simply by using cargo and "go build" in a Makefile.

The ca-certificates package should added as a BUILD_DEPENDS if you encounter TLS certificate errors during the build.

If the build fails a shell will be opened in the pbuilder(8) chroot, and will get you to the source directory of the package. vi(1) will be installed. That can help you see the reason for a failure. Quitting that shell will destroy the chroot. It is a hook than can be found at infrastructure/pbuilder/hooks/C99build_open_debug_shell.

You can trigger the pbuilder(8) failure shell for any dh_*(1) command, with a specially crafted debian/rules file, allowing you to debug the build. An example can be found at $SWIRLBUILD/infrastructure/templates/rules.template.

I will go with a non trivial yet easy real world example that can you find at $SWIRLBUILD/swirls/badwolf. This is lengthy because i wanted to showcase a lot of things swirlbuild can propose.

cd your_swirlbuild_root_directory
mkdir swirls/badwolf && cd swirls/badwolf
cp ../../infrastructure/templates/build.template build

# modify the buildfile to something that looks sensible
# and uncomment DEBUG_SOURCE=1 in the build file. While
# here add the checksum file.

../../buildswirl $PWD checksum
../../buildswirl $PWD
exit

# This looked okayish out of the box. Comment DEBUG_SOURCE=1 and try the build.

../../buildswirl $PWD

# dh_auto_clean
#	make -j12 distclean
# Failed with Error: You need to execute ./configure before running make
# I'll need to override dh_auto_clean

mkdir debian
cp ../../infrastructure/templates/rules.template debian/rules

# I edit debian/rules and try again

../../buildswirl $PWD

# Missing dependencies, so editing the buildfile again

../../buildswirl $PWD

# dh_usrlocal: error: debian/badwolf/usr/local/bin/badwolf is not a directory
# I will need to change PREFIX in debian/rules, also the configure script
# asked for more changes, to specify some extra environment options

../../buildswirl $PWD

# It builds! But I have found out by inspecting the built package with
# xarchiver that BadWolf installs its documentation where it should not. I
# should override that destination directory with an environment variable in
# debian/rules, but for the sake of the demonstration, I will make a patch.
# Also I set up DEBUG_RMPKG=1 in the buildfile.

env DEBUG_SOURCE=1 ../../buildswirl $PWD
cd badwolf-1.2.2
cp configure{,.orig}

# I change the DOCDIR variable to what we need in configure,
# then check the result:

diff -u configure{.orig,}

# Looks good, time to add it as a patch and exit:

mkdir $SWIRLDIR/patches
diff -u configure{.orig,} > $SWIRLDIR/patches/fix_documentation_path.patch
exit

# This should be our final build!

../../buildswirl $PWD

# After inspection it is fine. I remove all the unnecessary comment stuff in
# build. Time to test the runtime and have fun!

sudo apt update
sudo apt install badwolf
May 13, 2025 Debian stable