Creating a Debian/Ubuntu package

This is provisionary docs, these things are far from stable. You have been warned!

General

This page describes how to create .deb packages usable on Debian based distros like vanilla Debian, Ubuntu, Raspbian, Mint, etc.

Work is done on a Debian or Ubuntu host. Uploading an ubuntu package must be done from an Ubuntu host.

Here are five main tasks:

Here, the term "downstream release" refers to a release based on the same opencpn release but where the packaging has been modified.

There is also some support tasks, see the right panel.

Setting up the environment

  1. Creating releases requires a working gpg secret key including the password is available. Verify using something like gpg --export-secret-keys E2EA41DCE2F8A99AD17A1E463A67D5D966D15C5C. This key must be registered on the PPA about the be used.

  2. Create a file ~/.devscripts with contents like:

    DEBSIGN_KEYID=E2EA41DCE2F8A99AD17A1E463A67D5D966D15C5C
    DEBEMAIL="leamas.alec@gmail.com"
    DEBFULLNAME="Alec Leamas"

    Of course, all values here are personal. DEBSIGN_KEYID is the secret key verified above. This key is only required when uploading source packages to an ubuntu PPA.

  3. Install development tools

    $ sudo apt install devscripts git-buildpackage equivs

Make a fresh OpenCPN clone.

The Debian tools creates things in the parent directory. To handle this, create new, empty directory and put the OpenCPN tree there. Then, get all necessary three branches:

$ mkdir OpenCPN
$ cd OpenCPN
$ git clone --origin upstream  https://github.com/OpenCPN/OpenCPN.git
$ cd OpenCPN
$ git fetch upstream upstream/latest:upstream/latest
$ git fetch upstream pristine-tar:pristine-tar
$ git fetch upstream ubuntu/numbat:ubuntu/numbat
$ git checkout ubuntu/numbat

ubuntu/numbat is the branch to use when building Ubuntu Numbat (24.04) packages. Alternatives includes ubuntu/jammy, ubuntu/focal and debian/master. The latter builds packages for the rolling Sid distribution.

To update an existing clone:

$ git fetch upstream upstream/latest:upstream/latest
$ git fetch upstream pristine-tar:pristine-tar
$ git checkout ubuntu/numbat
$ git pull upstream ubuntu/numbat

Import a new opencpn version into packaging branches.

Initiate the changelog with a new version

debian/changelog is picky about the format. Editing by hand is hard. Instead, use the dch tool. It has a multitude of options.In preparation of importing a new version, first update debian/changelog with a new version, something like dch -v 1:5.9.3-beta3+dfsg

dch throws you in an editor loaded with debian/changelog. Complete the entry as you consider best. The standard message for a new version is "New upstream Release".

Import a release tag into upstream/latest

For now, the debian directory needs to be removed. After that, create a tarball based on HEAD. Using v5.9.3-beta3 as example:

$ git checkout git checkout v5.9.3-beta3
$ git switch -c tmp-build
$ git rm -r debian
$ git commit -m "Remove unused debian/ dir"
$ git archive --prefix opencpn-5.9.3-beta3/ --output ../opencpn.tar.gz HEAD

The --prefix part should be modified to reflect current version, but is not critical. Note the trailing slash!

Next step is to convert the tarball to a formal debian source tarball. This is about renaming and stripping files not used in the Debian build. Do:

$ git checkout ubuntu/numbat.
$ mk-origtargz ../opencpn.tar.gz

Where ../opencpn.tar.gz is the file created by git archive above. This creates something like ../opencpn.5.10.920.orig.tar.gz_. The version in the filename is taken from debian/changelog.

ubuntu/numbat is just an example, see Make a fresh clone above.

Nest step is to import this tarball into upstream/latest. Using the tarball created by git-archive above do:

$ gbp import-orig ../opencpn_5.9.3~beta3+dfsg.orig.tar.xz

Push upstream changes

Final step is to push these changes:

$ gbp push

Create a downstream release

Assuming the new upstream (opencpn) release is available as of above creating a downstream release goes like:

  1. Initiate the environment as described above.

  2. Clone and checkout all branches, see above.

  3. Create a orig.tar.xz tarball in ..

    $ gbp export-orig

This is a one time setup, the results can be used in various branches like ubuntu/jammy and debian/bookworm.

For each release do:

  1. Checkout the actual branch like ubuntu/jammy. Work on ubuntu branches must be done on an ubuntu host

  2. Create a provisional version entry in debian/changelog using dch -R.

  3. Merge upstream changes using gbp import-ref -u5.9.3-beta3. The -u argument is the last part of an upstream tag like upstream/5.9.3-beta3 This command fails in some branch(es), see below.

  4. Do possible changes in the new release. Note that only files in the debian/ directory can be modified; changes in other files are handled using patches in debian/patches. See Modifying Sources below

  5. Commit all changes.

  6. Finalize the changelog entry using dch -r.

  7. Commit the change in debian/changelog

  8. Push the actual branch, for example git push upstream ubuntu/jammy

If gbp import-ref fails, use the tarball created by gbp export-orig instead. For this to work, the corresponding tag should be deleted. Something like

$ git tag -d upstream/5.8.4+dfsg
$ gbp import-orig ../opencpn_5.8.4~beta4+dfsg.orig.tar.xz

Publish existing downstream release to PPA

  1. Initiate the environment as described above.

  2. Clone and checkout all branches, or update existing clone. See above.

  3. Make sure the repo is synchronized: git clean -fxd; git checkout .

  4. Create the upstream source tarball: gbp export-orig

  5. Create the source package: debuild --no-lintian -S

  6. List all available source packages using ls -lt ../*source.changes.

  7. Push the most recent package to a PPA using something like:

      $ dput ppa:leamas-alec/opencpn \
           ../opencpn_5.9.4~beta4+dfsg-1ubuntu1~bpo24.04+1_source.changes

    Or, a more generic oneliner pushing the most recent source.changes file:

      $ dput ppa:leamas-alec/opencpn $(ls -t ../*source.changes | head -1)

Local test build from existing upstream tag.

First step is to setup the environment, see above. However, no gpg key is required.

Then, create a fresh clone as described above.

Install build dependencies:

$ mk-build-deps
$ sudo dpkg -i *deb     # Expect error messages, ignore them
$ sudo apt install -f
$ git clean -fxd

List available upstream tags using git tag -l | grep upstream/. Normally use the most recent one like:

$ git clean -fxd; git checkout .
$ gbp buildpackage --git-upstream-tag=upstream/whatever -us -uc

This builds testable .deb packages in ...

Local test build from master

First step is to setup the environment, see above. However, no gpg key is required.

Make sure the build dependencies are in place, see above

Work is done in a clean clone of the master branch. Make sure the remote "upstream" exists and update it:

$ git config remote.upstream.url > /dev/null || \
     git remote add upstream https://github.com/OpenCPN/OpenCPN.git
$ git remote update upstream

Checkout the debian/ directory from the packaging branch. At the time of writing, this is only possible for Bookworm:

$ git fetch upstream ci/bookworm-backports:ci/bookworm-backports
$ git checkout ci/bookworm-backports debian
$ git commit -m "Add debian/ packaging directory from ci/bookworm-backports"

Create a debian changelog entry. This is an example of building a post 5.10 package for the bookworm release, YMMV:

$ version="1:5.11.0~$(date "+%Y%m%d%H%m").$(git rev-parse --short HEAD)-1"
$ dch --distribution bookworm -v "$version" "Test build from master"
$ git add debian/changelog
$ git commit -m "d/changelog: $version"

Create orig tarball. The name of the orig tarball created by mk-origtargz reflects the changelog version.

$ git archive --prefix opencpn-5.11.0/ --output ../opencpn.tar.gz HEAD
$ mk-origtargz ../opencpn.tar.gz

Extract the orig tarball and work in the sources it provides:

$ cd ..
$ tar xf opencpn-5.11.0*orig*xz
$ cd opencpn-5.11.0*

And build package. -j4 builds in four parallel pipes, depending on processor you might want to use another value (I typically use -j12).

$  debuild -us -uc -j4

Modifying sources in a downstream release.

One cannot change the opencpn sources when creating a release. However, it is possible to add or modify a patch in debian/patches. These patches are applied when building the opencpn package.

The basic workflow starts in a fresh, clean clone and goes like

$ gbp pq import --force
#     All the patches in debian/patches are applied.
#     Edit sources as desired and do:
$ git commit -am "Reason for this change"
$ gbp pq export
$ git add debian/patches/*
$ git commit -m "d/patches: new patch: patch description"

After gbp pq import actually all sorts of changes can be done. As usual, several small changes can and should be committed one by one rather than as a big patch.

It is also possible to edit existing patches using the standard git tools, in particular git rebase -i