|

Packaging cmatrix with quilt (Local Build Tutorial)

← Previous Linux PPA Packaging (2/4) Next →

Example Values Used in This Tutorial

This tutorial uses the following fake example values throughout. Replace them with your own real details when following along.

FieldExample Value
Full NameRex Bytes
Email[email protected]
Launchpad Usernamerexbytes
GPG Key IDAABB1122CCDD3344
Packagecmatrix 2.0
PPA Version2.0-1~ppa1~rexbytes
Target Distributionnoble
Working Directory~/packaging/cmatrix-ppa
PPAppa:rexbytes/example-ppa

In this tutorial, you’ll learn how to:

  • Take an upstream tarball (cmatrix 2.0 from GitHub)
  • Create minimal Debian packaging files by hand
  • Use quilt to add a small patch
  • Build a .deb package and test it locally
  • Understand the version string 2.0-1~ppa1~rexbytes

This assumes you’re on an Ubuntu-based system (example: Ubuntu Noble).

We are going to use the Ubuntu package cmatrix as our upstream package.


0. Getting the cmatrix source

You can start from either:

  • The upstream cmatrix tarball from GitHub, or
  • The Ubuntu/Debian source package via apt source (after enabling deb-src).

Both give you a cmatrix-2.0/ source tree to work in. Choose whichever matches what you want to learn.

0.1 Option 1: Upstream tarball (GitHub)

This is the “pure upstream” route we use in the main tutorial.

mkdir -p ~/packaging/cmatrix-ppa
cd ~/packaging/cmatrix-ppa

wget https://github.com/abishekvashok/cmatrix/archive/refs/tags/v2.0.tar.gz \
     -O cmatrix_2.0.orig.tar.gz

tar -xzf cmatrix_2.0.orig.tar.gz
cd cmatrix-2.0


Code language: JavaScript (javascript)

After this:

  • cmatrix_2.0.orig.tar.gz is your upstream tarball.
  • cmatrix-2.0/ is the unpacked source directory where you’ll create debian/.

0.2 Option 2: Source from Ubuntu (apt source)

If you’d rather start from Ubuntu’s existing packaging, you can fetch the source package instead.

0.2.1 Enable deb-src entries

Edit your APT sources:

  • Do this using the GUI for your distro.
  • Turn on the “source code repository” option.

Ubuntu Noble (24.04) and newer use the deb822 format by default. Your sources are in /etc/apt/sources.list.d/ubuntu.sources (not the old /etc/apt/sources.list). To enable source packages, add deb-src to the Types: line:

sudo nano /etc/apt/sources.list.d/ubuntu.sources


Code language: PHP (php)

Change:

Types: deb


Code language: HTTP (http)

to:

Types: deb deb-src


Code language: HTTP (http)

Note: Older Ubuntu releases and derivatives (like Linux Mint) may still use the traditional one-line format in /etc/apt/sources.list or files under /etc/apt/sources.list.d/*.list. In that case, ensure you have matching deb and deb-src lines:

deb http://archive.ubuntu.com/ubuntu noble main restricted universe multiverse
deb-src http://archive.ubuntu.com/ubuntu noble main restricted universe multiverse


Code language: JavaScript (javascript)

Save and exit, then update:

sudo apt update


If you’re using a PPA and want its source too:

sudo add-apt-repository -s ppa:rexbytes/example-ppa
sudo apt update


Important: You do need to manually run the above command for PPAs. It adds a deb-src line for the PPA as well.

0.2.2 Fetch the cmatrix source

mkdir -p ~/packaging/cmatrix-ppa
cd ~/packaging/cmatrix-ppa

apt source cmatrix


Code language: JavaScript (javascript)

This will download and unpack the source, giving you something like:

  • cmatrix-2.0/ — source tree (already contains a debian/ directory)
  • cmatrix_2.0.orig.tar.gz
  • cmatrix_2.0-<rev>.debian.tar.xz
  • cmatrix_2.0-<rev>.dsc

Then:

cd cmatrix-2.0


Code language: CSS (css)

Important: Using apt source means there may already be an existing debian/ directory created by Ubuntu packagers. Delete (or rename) the existing debian/ directory — you’ll recreate it from scratch in this tutorial. Renaming it (e.g. mv debian debian.orig) lets you refer back to the original packaging if needed.

mv debian debian.orig


Code language: CSS (css)

1. Install required tools

Install the packaging tools (including quilt) and build dependencies:

sudo apt update
sudo apt install devscripts build-essential debhelper quilt \
                 autoconf automake libncurses-dev \
                 dput gnupg


Note: On Ubuntu Noble and newer, the old libncurses5-dev and libncursesw5-dev packages have been replaced by libncurses-dev, which covers both narrow and wide character support. gnupg is usually pre-installed on Ubuntu but is listed here for completeness — you’ll need it for signing in tutorial 03.


2. Prepare a working directory and download cmatrix

If you already followed Section 0 above, you should have ~/packaging/cmatrix-ppa/cmatrix-2.0 ready. Skip to Section 3.

If you skipped Section 0 and want the quick path, use the upstream GitHub tarball:

mkdir -p ~/packaging/cmatrix-ppa
cd ~/packaging/cmatrix-ppa

wget https://github.com/abishekvashok/cmatrix/archive/refs/tags/v2.0.tar.gz \
     -O cmatrix_2.0.orig.tar.gz

tar -xzf cmatrix_2.0.orig.tar.gz
cd cmatrix-2.0


Code language: JavaScript (javascript)

Note: The underscore in cmatrix_2.0.orig.tar.gz is important for Debian naming conventions (<package>_<upstream-version>.orig.tar.gz).


3. Create the debian/ directory

All packaging files live in a directory called debian inside the source tree.

mkdir debian


We’ll now create several files manually:

  • debian/control
  • debian/rules
  • debian/changelog
  • debian/copyright
  • debian/patches/* (for quilt)

4. Create debian/control

This file declares metadata about the package and build dependencies.

nano debian/control


Insert:

Source: cmatrix
Section: misc
Priority: optional
Maintainer: Rex Bytes <[email protected]>
Build-Depends: debhelper-compat (= 13), autoconf, automake, libncurses-dev
Standards-Version: 4.7.0
Homepage: https://github.com/abishekvashok/cmatrix

Package: cmatrix
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Terminal-based "The Matrix" effect
 CMatrix simulates the digital rain from "The Matrix" inside your terminal.


Code language: HTTP (http)
  • Source: name of the source package.
  • Build-Depends: tools and libraries needed to build. The debhelper-compat (= 13) entry is a virtual package that tells debhelper which compatibility level to use — level 13 is the current recommended default. This replaces the older debian/compat file.
  • Package: the binary package name (the .deb).
  • Depends: ${shlibs:Depends}, ${misc:Depends} — automatically generated deps.

Save and exit.


5. Create debian/rules

This is a makefile that tells debhelper how to build and install the package.

nano debian/rules


Insert:

#!/usr/bin/make -f
%:
	dh $@

override_dh_auto_configure:
	autoreconf -i
	./configure --prefix=/usr

override_dh_auto_install:
	make DESTDIR=$(CURDIR)/debian/cmatrix install


Code language: PHP (php)
  • dh $@ calls the appropriate debhelper command for each step (build, install, clean, etc.).
  • override_dh_auto_configure runs autoreconf and ./configure with /usr as the prefix.
  • override_dh_auto_install installs into a temporary tree under debian/cmatrix, not your real filesystem.

Make it executable:

chmod +x debian/rules


Important: debian/rules is a Makefile. Indented lines must use a real tab character, not spaces. If you copy-paste from a web page, your editor may convert tabs to spaces — this will cause build failures with missing separator. In nano, press Tab to insert a literal tab. In vim, tabs are the default.


6. Create debian/changelog

We’ll write a minimal changelog entry by hand (no dch).

nano debian/changelog


Insert:

cmatrix (2.0-1~ppa1~rexbytes) noble; urgency=medium

  * Initial PPA build with custom Debian packaging.

 -- Rex Bytes <[email protected]>  Wed, 26 Nov 2025 12:00:00 +0000


Code language: HTML, XML (xml)
  • 2.0-1~ppa1~rexbytes is the package version. We’ll explain it in detail near the end.
  • noble is the target distribution (e.g. Ubuntu Noble).
  • The last line is your signature line: name, email, date, and time.

Important: The trailing line format is strict: one space, two dashes, one space, Name <email>, then two spaces before the RFC 2822 date. Getting the spacing wrong will cause dpkg-source to reject the changelog. This is the most common gotcha when writing the changelog by hand — using dch (covered in section 14) avoids this entirely.


7. Create debian/copyright

This tells Debian/Ubuntu about licensing and copyright terms.

nano debian/copyright


Insert (based on the Debian copyright file for cmatrix):

Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: CMatrix
Source: https://github.com/abishekvashok/cmatrix

Files: *
Copyright: 1999-2017 Chris Allegretta
           2017-2019 Abishek V Ashok <[email protected]>
License: GPL-3+

Files: debian/*
Copyright: 2025 Rex Bytes <rexbytes@example.com>
License: GPL-3+

License: GPL-3+
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
 .
 This package is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 .
 You should have received a copy of the GNU General Public License
 along with this program. If not, see <https://www.gnu.org/licenses/>.
Comment:
 On Debian systems, the complete text of the GNU General
 Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".


Code language: PHP (php)

8. Create debian/source/format

This file tells dpkg-source which source package format to use. Without it, dpkg-source defaults to the legacy format 1.0 and emits a warning.

mkdir -p debian/source
echo '3.0 (quilt)' > debian/source/format


Code language: PHP (php)

Format 3.0 (quilt) is the modern standard. It stores the upstream tarball separately from your Debian changes and uses quilt to manage patches.


9. Prepare quilt for patches

Create the patches directory and an (initially empty) series file:

mkdir -p debian/patches
touch debian/patches/series


For this shell session, set quilt environment variables (so it uses debian/patches):

export QUILT_PATCHES=debian/patches
export QUILT_SERIES=series


Code language: JavaScript (javascript)

10. Create a quilt patch

We’ll add a small patch that modifies the version output, for example to add a “Packaged By” line.

10.1 Start a new patch

quilt new add-debian-tag-to-version-output.patch


Code language: JavaScript (javascript)

This creates a new patch entry and marks it as “current” for quilt.

10.2 Tell quilt which file you’re editing

quilt add cmatrix.c


Code language: CSS (css)

This tells quilt to track changes in cmatrix.c for this patch.

10.3 Edit the source

Open cmatrix.c and modify the version() function to print your tag:

nano cmatrix.c


Code language: CSS (css)

Find the version(void) function and add a line:

void version(void) {
    printf("CMatrix version %s (compiled %s, %s)\n",
        VERSION, __TIME__, __DATE__);
    printf("Email: [email protected]\n");
    printf("Web: https://github.com/abishekvashok/cmatrix\n");
    printf(" Packaged By: Rex Bytes - As part of a packaging tutorial.\n");
}


Code language: JavaScript (javascript)

Save and exit.

10.4 Refresh the patch

Tell quilt to record the differences into the patch file:

quilt refresh


You can inspect the generated patch:

cat debian/patches/add-debian-tag-to-version-output.patch


It should look similar to:

Index: cmatrix-2.0/cmatrix.c
===================================================================
--- cmatrix-2.0.orig/cmatrix.c
+++ cmatrix-2.0/cmatrix.c
@@ -152,6 +152,7 @@ void version(void) {
         VERSION, __TIME__, __DATE__);
     printf("Email: [email protected]\n");
     printf("Web: https://github.com/abishekvashok/cmatrix\n");
+    printf(" Packaged By: Rex Bytes - As part of a packaging tutorial.\n");
 }


Code language: JavaScript (javascript)

At this point, your debian/patches/series file should contain the patch name:

cat debian/patches/series


Expected content:

add-debian-tag-to-version-output.patch


Code language: CSS (css)

11. Build the package

Go back to the top of the source tree (if you’re not already there):

cd ~/packaging/cmatrix-ppa/cmatrix-2.0


Code language: JavaScript (javascript)

First, unapply any quilt patches. With 3.0 (quilt) format, dpkg-source will re-apply patches during the build — if they’re still applied, the build can fail or produce warnings:

quilt pop -a


Build the package (no signing, local build):

dpkg-buildpackage -us -uc


  • -us = do not sign source.
  • -uc = do not sign the .changes file.

Note: dpkg-buildpackage does not run lintian automatically (that is a feature of debuild). After the build finishes, run lintian yourself to check for packaging issues:

lintian ../cmatrix_2.0-1~ppa1~rexbytes_amd64.changes


You may see warnings about missing man pages or other minor policy issues — these don’t block the build and are normal for tutorial packages. To see detailed explanations of any warnings, add the --info flag.

If everything succeeds, you’ll have .deb and related files in ~/packaging/cmatrix-ppa.

Troubleshooting common build failures

SymptomLikely causeFix
missing separator in debian/rulesSpaces instead of tabsRe-indent with real tab characters
cannot find -lncurses or missing curses.hMissing build dependencysudo apt install libncurses-dev
autoreconf: command not foundMissing autotoolssudo apt install autoconf automake
patch ... does not applyQuilt patches still applied or modified sourceRun quilt pop -a before building, or check your patch matches the source
dpkg-source: error: aborting due to unexpected upstream changesYou edited source files directly instead of through quiltUndo direct edits, use quilt push, quilt add, edit, quilt refresh

12. Install and test the package

Go up one directory and install the freshly built .deb:

cd ..
sudo dpkg -i cmatrix_2.0-1~ppa1~rexbytes_amd64.deb


Code language: CSS (css)

Note: The .deb filename includes your system’s architecture (e.g. amd64, arm64). Adjust the filename to match what dpkg-buildpackage actually produced — you can check with ls *.deb.

Now test the version output:

cmatrix -V


Expected output (similar to):

CMatrix version 2.0 (compiled 12:00:00, Nov 26 2025)
Email: abishekvashok@gmail.com
Web: https://github.com/abishekvashok/cmatrix
 Packaged By: Rex Bytes - As part of a packaging tutorial.


Code language: CSS (css)

13. Understanding the version: 2.0-1~ppa1~rexbytes

Debian version format:

[epoch:]upstream-version[-debian-revision]


Code language: CSS (css)

For your package:

  • Upstream version: 2.0
  • Debian revision: 1~ppa1~rexbytes

Breakdown:

PartMeaning
2.0The upstream project version (cmatrix 2.0).
-1The first Debian packaging revision for this upstream version. If someone changes the packaging, they’d bump this to -2, -3, etc.
~ppa1ppa1 = “first PPA build”. The leading ~ makes this version sort older than 2.0-1. So 2.0-1~ppa1 < 2.0-1. If Ubuntu later publishes 2.0-1 officially, apt will upgrade users from your PPA package to the official one.
~rexbytesA label indicating which PPA/repo this build is from. Keeps the overall version below 2.0-1, but distinguishes it from other PPA builds.

In short:

2.0-1~ppa1~rexbytes = cmatrix 2.0, first Debian-style packaging revision, first PPA build, from “rexbytes”, always considered older than the official 2.0-1 package.


14. Bonus: Using dch to manage the changelog

In this tutorial, we wrote debian/changelog by hand to understand the format. In real packaging work, you’ll usually use the dch tool (from devscripts) to edit it safely.

dch can:

  • Create a new debian/changelog
  • Bump the Debian revision (-1-2, etc.)
  • Set the version explicitly
  • Add new changelog entries with your name, email, and the current date

14.1 Tell dch who you are

dch gets your name and email from environment variables (preferred) or, if those aren’t set, from git config / other fallbacks.

For packaging, set explicit Debian identity variables:

export DEBFULLNAME="Rex Bytes"
export DEBEMAIL="[email protected]"


Code language: JavaScript (javascript)

You can put these in ~/.bashrc (or ~/.zshrc, etc.) so they’re always set:

echo 'export DEBFULLNAME="Rex Bytes"' >> ~/.bashrc
echo 'export DEBEMAIL="[email protected]"' >> ~/.bashrc
source ~/.bashrc


Code language: PHP (php)

From now on, dch will create changelog trailer lines like:

 -- Rex Bytes <[email protected]>  Fri, 05 Dec 2025 12:34:56 +0000


Code language: HTML, XML (xml)

14.2 Creating a changelog with dch

If debian/changelog doesn’t exist yet, you can create it with:

dch --create -v 2.0-1~ppa1~rexbytes --package cmatrix -D noble


Code language: CSS (css)

dch will:

  • Open an editor with a template entry
  • Use your DEBFULLNAME/DEBEMAIL
  • Fill in the version and date

Edit the bullet points, save, and quit. dch will write a proper changelog stanza for you.

Important: Without -D noble, dch defaults the distribution to UNRELEASED. Launchpad rejects uploads with UNRELEASED — you must set it to an active Ubuntu series like noble.

14.3 Bumping the version for a new PPA build

Suppose you’ve already uploaded 2.0-1~ppa1~rexbytes and now want a second PPA build, e.g. 2.0-1~ppa2~rexbytes:

dch -v 2.0-1~ppa2~rexbytes "Second PPA build: tweak packaging."


Code language: JavaScript (javascript)

This will:

  • Add a new changelog entry at the top
  • Set the new version to 2.0-1~ppa2~rexbytes
  • Use your configured name and email
  • Update the date automatically

14.4 Auto-incrementing Debian revisions

If you’re doing classic Debian-style revisions (2.0-1, 2.0-2, 2.0-3, …), you can let dch increment the revision for you:

dch -i "Bump Debian revision after packaging changes."


Code language: JavaScript (javascript)

-i tells dch to:

  • Look at the current version (e.g. 2.0-1)
  • Bump the Debian revision (-1-2)
  • Add a new changelog entry with that incremented version

Similar Posts

Leave a Reply