A Minimum Complete Example of Debian Packaging and Launchpad PPA: hellodeb
There are many sites explaining how to create debian packages, but it seems to me none or only a few of them explains it at the very basic level.
The companion project of this post is hellodeb@github. I will explain how to generate the source package, architecture specific binary packages and an architecture independent binary package. Additionally, I will briefly mention uploading the source package to a launchpad PPA.
This post does not cover everything but it shows a minimum complete example, a hello world for Debian packaging, hellodeb
. It does not use anything other than the basic tools provided in dpkg-dev
package, particularly it neither uses dh_make
nor debuild
.
The main reference for this post is Debian Policy Manual, and the other sources are the manual pages of the tools used.
I am using Ubuntu 20.04 for this post, and as you know, Ubuntu also uses Debian packaging.
hellodeb
My example project hellodeb contains:
- a C source file (hellodeb.c)
- a manual page (hellodeb.1)
It also contains debian
directory which includes the meta-data for packaging.
Additionally, there are a few bash scripts:
build-package.sh
: runsdpkg-buildpackage
with the provided build type (source, binary etc.) and other arguments which are directly passed todpkg-buildpackage
build-source.sh
: runsdpkg-source --build .
clean.sh
: removes all generated files and returns the directory to initial statetest.sh
: used to check the build in a CI, not used in this post
The reason I have these scripts is that before running the package build, they clean the directory, create a new build
directory and copy the debian directory and source files there and runs dpkg-buildpackage
and dpkg-source
under that directory.
The files in hellodeb repository might have a slightly different content than what is shown in this post, because I fix or improve small issues while writing the post.
Debian Packages
There are two types of packages: source and binary.
Source packages are built from the original source code (e.g. of a program). Then the build rules file (a Makefile) is run which is expected to generate binary packages. This process is controlled with some additional (meta-data) files.
By the use of meta data, (maintainer) scripts and tools, Debian packaging handles the installation, removal and dependencies of packages.
There are different source package formats, and in this post 3.0 (quilt)
is used. In this format, a source package contains three files:
- original source,
orig.tar.xz
- debian source (meta-data),
debian.tar.xz
- source control,
dsc
Binary package contains a single file:
- debian binary package,
deb
In addition to these files, there are two more files.
- build record,
buildinfo
- upload control,
changes
My understanding is that both the source and binary packages of a project are supposed to be built. Maybe it is possible and it sounds like it should be possible to build only one, but the tools assume you have the source code and you are going to build source package first and then the binary package(s) -the reason I say this might be more clear later-.
Multiple binary packages do not mean one binary package for each architecture (i386, amd64 etc.). Each binary package can consist of different things from the same source code such as the core or common files, documentation, examples etc. For example, all packages of tomcat9:
$ apt-cache search tomcat9 | cut -f1 -d' '
libtomcat9-embed-java
libtomcat9-java
tomcat9
tomcat9-admin
tomcat9-common
tomcat9-docs
tomcat9-examples
tomcat9-user
are built from the same source package called tomcat9. When you want to get the sources of, for example, tomcat9-admin, it redirects you to the correct source package:
$ apt source tomcat9-admin
Reading package lists... Done
Picking 'tomcat9' as source package instead of 'tomcat9-admin'
...<output continues>...
dpkg
Debian packaging tools, dpkg
suite, are inter-connected. You can use dpkg
with some options, which runs dpkg-deb
to build a binary package. You can also use dpkg-buildpackage
and let it execute various steps, run various tools in dpkg
suite, depending on what you requested. On its manual page, there is a short summary of all the steps dpkg-buildpackage
takes, it is a good reference. Also, dpkg-buildpackage
is a Perl script like other similar tools in dpkg suite. You can look at the source code of these scripts when needed.
If you want to build only a source package, without any other files and without signing them, you can use dpkg-source
directly, however in all other cases dpkg-buildpackage
is the best choice, which also calls dpkg-source
to build the source package.
dpkg
comes with the base installation of Ubuntu, but you need to install dpkg-dev
package to generate packages.
A (package) build triggered by dpkg-buildpackage
can be one of the following (provided with --build
option):
source
: builds only the source packageany
: builds architecture specific binary packages e.g. amd64all
: builds architecture independent binary packages e.g. documentation, pure Java or Pythonbinary
: an alias for any and all, thus all possible binary packagesfull
: an alias for source and binary, thus all possible packages
The options any
and all
have also a meaning for Architecture
(meta-data) of a package. any
is used as a wildcard to mean any architecture the OS is supposed to run (this really means many many architectures), whereas all
is used for documentation and with platform independent code like Java and it means this package is architecture independent (it runs on all architectures without modification). I checked a few packages and it seems to me some packages are using any
as a shortcut when they support a number of architectures (but probably not all). On the other hand, some packages are NOT using any
and explicitly state the supported architectures (e.g. amd64 armhf arm64 i386 mips mips64).
As mentioned before, the process of running dpkg-buildpackage --build=source
and dpkg-source --build .
is not the same. dpkg-source
only builds the source package, whereas dpkg-buildpackage
can run checks and do other things like generating buildinfo and changes and signing the files.
dpkg-source
and dpkg-buildpackage
is run in a directory with source code and debian
folder but they generate the packages in the parent directory. In some versions of source format, the directory should have a particular name, but for 3.0 (quilt)
there is no such constraint, so I am simply using the name build
.
Process
I first assumed source and binary packages are/can be created independently. This is correct to some extent (they are not created simultaneously) but -I think- the implied process is a bit different then what I thought, so it was a little confusing for me.
It seems the assumption is that (being a packager) you first get the original source files and then add debian
directory and meta-data files including the rules file to build packages. The dpkg tools are run in such a way, it generates first the source package and then all other binary packages in a single run.
So the source and the binary package build processes are intermixed. Another proof of this is the debian/control
file, which has to have at least two paragraphs (sections), one for source and other for binary package. This means, a source package always has a binary package and vice versa. So the implied process naturally makes sense.
For the demonstration purpose, I also provide debian
directory in the hellodeb project. However, build scripts build-source.sh
and build-package.sh
create a correctly named and versioned original source tarball and create a directory with the debian directory and copies the source files also there, in effect they imitate the procedure I described above.
Source Package (with dpkg-source)
The meta data for source packages stay under the folder debian
. You must have at least debian/changelog
and debian/control
.
The directory names can be a bit confusing. Source packages use debian
whereas binary packages use DEBIAN
for the meta data directory. You will see this in Debian Policy Manual and other places, it is not a typo.
debian/changelog
describes the changes. However, the more important thing is it sets the name (hellodeb), version (1.0-4) and distribution of the package. When distribution name is UNRELEASED, it means this package build is not targeted for a particular distribution (e.g. focal for Ubuntu 20.04), so it does not need to be signed. This file changelog
has a very rigid structure.
$ cat debian/changelog
hellodeb (1.0-4) UNRELEASED; urgency=low
* Initial release.
-- Mete Balci <metebalci@gmail.com> Tue, 12 Apr 2022 10:21:28 +0000
The version may include both the upstream/original version of the code and also the Debian revision (due to packaging). Above, 1.0
is the upstream version, and 4
is the Debian revision. It is a good idea to have a Debian revision, because you may make a mistake during packaging and you may not be able to upload the exact same version again, so you can just change the Debian revision.
The next file is debian/control
, so called source package control file. This file contains fields (name and value pairs) grouped in paragraphs (sections) separated by an empty line. First paragraph contains information about the source package. The second and other paragraphs are about the binary packages. This file has to have at least two paragraphs.
$ cat debian/control
Source: hellodeb
Maintainer: Mete Balci <metebalci@gmail.com>
Standards-Version: 4.5.0
Priority: optional
Section: utils
Package: hellodeb
Architecture: amd64 arm64 armhf
Description: hello world for Debian packaging
This is an hello program to demonstrate
Debian packaging.
Package: hellodeb-doc
Architecture: all
Description: hellodeb documentation
Other than Priority and Section, all other fields above are mandatory. There is a source package (first), architecture specific binary package for three architectures (second) and an architecture independent package (third) for documentation. As you can see, each package can be named differently. It is OK to have the source and a binary package to have same name but naturally different binary packages should have different names (like hellodeb-doc above).
Priority and Section are recommended, and if not provided, a warning is issued. A detailed explanation about these fields can be found in the Debian Policy Manual. The Standards-Version field indicates the Debian Policy Manual version this file complies.
With only these two files (remove other things under debian
if you want to try this with hellodeb), if you run build-source.sh
which runs dpkg-source --build .
, it generates the source package, but with a warning. The warning is about the format of source package which defaults to 1.0. The latest version of source packages is 3.0 and there are multiple alternatives or subtypes (see man dpkg-source for more information). This should be specified in debian/source/format
file.
$ cat debian/source/format
3.0 (quilt)
If source format is 2.0 or newer, default compression of archive is xz. For 1.0, it is gzip (gz).
I first started using 3.0 (native)
format but I think many packages use 3.0 (quilt)
format so I also switched to that. Although the basics are the same or similar, there are some differences between them. The scripts build-source.sh
and build-package.sh
may not work for other formats.
When you also have the debian/source/format
file, you can run build-source.sh
:
$ ./build-source.sh
hellodeb.c
hellodeb.1
dpkg-source: info: using source format '3.0 (quilt)'
dpkg-source: info: building hellodeb using existing ./hellodeb_1.0.orig.tar.xz
dpkg-source: info: building hellodeb in hellodeb_1.0-7.debian.tar.xz
dpkg-source: info: building hellodeb in hellodeb_1.0-7.dsc
The same result can also be achived with dpkg-buildpackage --build=source
, and this is actually what is done at first when dpkg-buildpackage
is run to build the binary packages. However, you cannot run dpkg-buildpackage
only with these files, because it is checking the files required for building the binary packages as well.
The generated dsc
file is also a control file, which contains information about the packages e.g. packages that can be built, checksums of source.tar.xz file.
$ cat hellodeb_1.0-7.dsc
Format: 3.0 (quilt)
Source: hellodeb
Binary: hellodeb, hellodeb-doc
Architecture: amd64 arm64 armhf all
Version: 1.0-7
Maintainer: Mete Balci <metebalci@gmail.com>
Standards-Version: 4.5.0
Package-List:
hellodeb deb utils optional arch=amd64,arm64,armhf
hellodeb-doc deb utils optional arch=all
Checksums-Sha1:
93a7c60ecd983d6edc4acd6a63d8d3bfa200a70a 432 hellodeb_1.0.orig.tar.xz
cd5594120dcea179b81bc8143c1b2c4391135cc2 1472 hellodeb_1.0-7.debian.tar.xz
Checksums-Sha256:
085592fbda0cf0475242e6a43278e97f9fc491bdb976e794d573fd938cf949af 432 hellodeb_1.0.orig.tar.xz
d9b23f56c1f905b0c55ff1c92aa35cae1d1c811051c7b36f15aabdbe56452ae7 1472 hellodeb_1.0-7.debian.tar.xz
Files:
5bbaabb2e7d782425c5e66830e0bc805 432 hellodeb_1.0.orig.tar.xz
92b587958d619a4c3c880ee61c459b8f 1472 hellodeb_1.0-7.debian.tar.xz
The .orig.tar.xz file contains the source code:
$ tar tvf hellodeb_1.0.orig.tar.xz | awk '{print $NF}'
hellodeb.c
hellodeb.1
and debian.tar.xz file contains only the debian directory with meta-data files.
$ tar tvf hellodeb_1.0-7.debian.tar.xz | awk '{print $NF}'
debian/
debian/changelog
debian/control
debian/copyright
debian/rules
debian/source/
debian/source/format
Copyright
It seems dpkg-source
does not generate any warning, but the copyright information is also a must. This is given in debian/copyright
file. In order to make it machine readable, it also has a simple structure:
$ cat debian/copyright
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: hellodeb
Upstream-Contact: info@metebalci.com
Source: https://github.com/metebalci/hellodeb
Files: *
Copyright: 2022 Mete Balci
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 program 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/>.
It is possible to specify different copyrights for different files, but above all the files (*) have the same GPL-3 copyright.
Signing Key
If you already know about PGP and have a key that you can use, skip this section. If not, you need to have a local PGP key to sign packages. The steps below are enough to have a working example, but probably not good enough for a professional use.
- create a key with
gpg --full-gen-key
, I select RSA and RSA (default), 4096 bits and key does not expire options. - send the key to Ubuntu keyserver with
gpg --keyserver keyserver.ubuntu.com --send-keys <fingerprint>
. You can see the fingerprint withgpg --list-keys
, it is the long hexadecimal string.
If you want to use a Launchpad PPA, you need to add the fingerprint of this key to Launchpad and verify it. You have to wait for some minutes before adding the fingerprint to Launchpad.
- enter the fingerprint of the key to your Launchpad OpenPGP keys section, the same fingerprint format requested (groups of 4 digits, separated by spaces) can be printed with
gpg --fingerprint
. - when the verification e-mail arrives, run
gpg
and paste the PGP MESSAGE part, this will show a URL that you need to open in a browser, and this completes the Launchpad OpenPGP key setup.
Signed Source Package (with dpkg-buildpackage)
Another way to build the source package is using dpkg-buildpackage
with --build=source
option. However, by default, it wants to sign the files unless disturbution name is UNRELEASED, so you need to create the signing key first. If you want to run dpkg-buildpackage
but do not want it to sign the files, you can use --no-sign
option.
Also, although it is not very necessary for a source package, debian/rules
file has to be present for this to work. Either use the one in hellodeb repository, or just create an empty file if you want to try this. You can see on the output below, its clean
target is called before calling dpkg-source
.
At the beginning of the post, I showed debian/changelog
stating distribution name as UNRELEASED. Now, I am using the version in the repository and distribution name is focal (Ubuntu 20.04). If you keep it as UNRELEASED, dpkg-buildpackage
will run and say this package is UNRELEASED so no need to sign the files.
$ ./build-package.sh source
hellodeb.c
hellodeb.1
dpkg-buildpackage: info: source package hellodeb
dpkg-buildpackage: info: source version 1.0-8
dpkg-buildpackage: info: source distribution focal
dpkg-buildpackage: info: source changed by Mete Balci <metebalci@gmail.com>
dpkg-source --before-build .
fakeroot debian/rules clean
rm -f hellodeb
rm -f hellodeb.1.gz
rm -rf debian/tmp
dpkg-source -b .
dpkg-source: info: using source format '3.0 (quilt)'
dpkg-source: info: building hellodeb using existing ./hellodeb_1.0.orig.tar.xz
dpkg-source: info: building hellodeb in hellodeb_1.0-8.debian.tar.xz
dpkg-source: info: building hellodeb in hellodeb_1.0-8.dsc
dpkg-genbuildinfo --build=source
dpkg-genchanges --build=source >../hellodeb_1.0-8_source.changes
dpkg-genchanges: info: not including original source code in upload
dpkg-source --after-build .
dpkg-buildpackage: info: binary and diff upload (original source NOT included)
signfile hellodeb_1.0-8.dsc
signfile hellodeb_1.0-8_source.buildinfo
signfile hellodeb_1.0-8_source.changes
Pay attention to the line with (original source NOT included)
output. By default, if the upstream version of this build (1.0 in 1.0-7) in debian/changelog
is the same as the last change (1.0 in 1.0-6), the source (orig.tar.xz) is not included in this source package build, because the assumption is at least a previous version of the source package has this source.
As you have seen above, buildinfo
and changes
files are also produced in addition to dsc
file. dsc
file is produced by dpkg-source
but buildinfo
and changes
are produced by dpkg-genbuildinfo
and dpkg-genchanges
tools and these are only run when dpkg-buildpackage
is used.
buildinfo
file is just a record of some information like dependencies of the system that has built this package.
changes
file is called upload control file. Basically the files listed in changes
are uploaded for example to Launchpad. So this file decides if the original source (orig.tar.xz) is included or not.
As you can on the last lines of the output above, dsc
, buildinfo
and changes
files are signed.
Because Launchpad requires only the source package, at this point you can upload this signed source package to a Launchpad PPA. However, you probably want to test it first, so you will create the binary packages anyway. So I will explain binary packages first and then upload the source package to my Launchpad PPA.
Binary Packages
Until now, I showed running dpkg-source
and dpkg-buildpackage --build=source
. All other options for --build
involve building one or more binary packages. The only extra file that is required is a proper debian/rules
which is a Makefile and a set of three targets of this Makefile is called depending on the value of --build
option. If the option is:
full
(or if it is omitted): clean, build and binary targets are run.all
: clean, build-indep and binary-indepany
: clean, build-arch and binary-archbinary
: clean, build and binarysource
: as a reminder, only clean target is called for source
The difference between full
and binary
is that full
also builds the source packages, but only the clean target of debian/rules
file is used.
For the sake of completeness, I should mention, even if the source package build is not requested, dpkg-buildpackage
still calls dpkg-source
with --before-build
at the very start of any execution and --after-build
just before signing the files. These call source format (debian/source/format
) specific actions like applying patches.
As you have realized, clean and a different set of 2 targets are run anytime dpkg-buildpackage
is invoked. It is totally up to you, how you write this rules
file, and there are helper utilities to simplify this but I am not going to use any such helper in this post.
In many projects, the project has its own Makefile, so rules
can invoke the actual Makefile. In this post, I am not using any other Makefile, so my rules
file actually builds hellodeb.c
. It is expected the binary executables are stripped from unnecessary information, so it is usually done after the build. The man page hellodeb.1
does not require any compilation, it is simply compressed and copied.
There are two additional tools that are used when building binary packages. These are called from rules
explicitly. First is dpkg-gencontrol
, which generates the binary package control file at DEBIAN/control
. The other is dpkg-deb
, which actually creates the binary package from a directory. By default, the target directory is debian/tmp
, so it is also used in this post.
It is a bit confusing all the directories, so I summarize again:
- The source code is under
hellodeb_1.0
- The source package meta-data directory is
hellodeb_1.0/debian
dpkg-gencontrol
creates binary package control file athellodeb_1.0/debian/tmp/DEBIAN
- The folder
hellodeb_1.0/debian/tmp
is used to build the binary package bydpkg-deb
, so the binary files to be installed/copied to the target system is under thishellodeb_1.0/debian/tmp
folder e.g.hellodeb_1.0/debian/tmp/usr/bin/hellodeb
which is copied to/usr/bin/hellodeb
in the target system. - When building multiple packages (e.g. hellodeb and hellodeb-doc), naturally you need to have a clean
debian/tmp
folder to start with.
Lets build binary (both any and all) packages:
$ ./build-package.sh binary
mete@lemur:~/hellodeb$ ./build-package.sh binary
hellodeb.c
hellodeb.1
dpkg-buildpackage: info: source package hellodeb
dpkg-buildpackage: info: source version 1.0-8
dpkg-buildpackage: info: source distribution focal
dpkg-buildpackage: info: source changed by Mete Balci <metebalci@gmail.com>
dpkg-buildpackage: info: host architecture amd64
dpkg-source --before-build .
fakeroot debian/rules clean
rm -f hellodeb
rm -f hellodeb.1.gz
rm -rf debian/tmp
debian/rules build
x86_64-linux-gnu-gcc `dpkg-buildflags --get CFLAGS` -Wall -o hellodeb hellodeb.c
gzip -c hellodeb.1 > hellodeb.1.gz
fakeroot debian/rules binary
rm -rf debian/tmp
mkdir -p debian/tmp/DEBIAN
dpkg-gencontrol -phellodeb
mkdir -p debian/tmp/usr/bin
cp hellodeb debian/tmp/usr/bin
strip --strip-unneeded --remove-section=.comment --remove-section=.note debian/tmp/usr/bin/hellodeb
dpkg-deb --build debian/tmp ../hellodeb_1.0-8_amd64.deb
dpkg-deb: building package 'hellodeb' in '../hellodeb_1.0-8_amd64.deb'.
rm -rf debian/tmp
mkdir -p debian/tmp/DEBIAN
dpkg-gencontrol -phellodeb-doc
mkdir -p debian/tmp/usr/share/man/man1
cp hellodeb.1.gz debian/tmp/usr/share/man/man1
dpkg-deb --build debian/tmp ../hellodeb-doc_1.0-8_all.deb
dpkg-deb: building package 'hellodeb-doc' in '../hellodeb-doc_1.0-8_all.deb'.
dpkg-genbuildinfo --build=binary
dpkg-genchanges --build=binary >../hellodeb_1.0-8_amd64.changes
dpkg-genchanges: info: binary-only upload (no source code included)
dpkg-source --after-build .
dpkg-buildpackage: info: binary-only upload (no source included)
signfile hellodeb_1.0-8_amd64.buildinfo
signfile hellodeb_1.0-8_amd64.changes
If you follow the output messages carefully, you can see everything I have described above (any a little bit more).
Because I did not ask for the source package, no dsc
file is generated (dpkg-source
is not run). However, buildinfo
and changes
files are generated and signed.
At this point, you can go back to Deconstruction of a Full Package Build, and all should make sense.
Personal Package Archive on Launchpad
Now I have the source and binary packages but how to distribute them. It is possible to store these in a directory like a local repository but it is not very useful. There are two options: one is to use Launchpad to create a Personal package archive and upload the (source) package there (and Launchpad builds the binary packages), and the second is to create a Debian repository that can be accessed with http. PPA does not require any extra effort, but creating a Debian repository requires a web server etc.
For a PPA, Launchpad only accepts source packages, the binary packages are created by the launchpad after uploading the source package. Since there are many PPAs and many packages, and some are more important than others, there is a prioritized build queue, and it might take a while for a package to be available. You can select which architectures to build the architecture specific binary packages (like amd64, arm64) and the architecture independent “all” package is built in one architecture only (I believe at the moment it is always amd64), and copied to other architectures for distribution (since it is architecture independent, it should not matter where it is built).
The architecture of hellodeb
binary package is amd64
, arm64
and armhf
and the architecture of hellodeb-doc
binary package is all. At the moment, Launchpad runs dpkg-buildpackage
with --build
:
any
(meaning architecture specific binary packages) forarm64
andarmhf
binary
(meaning both architecture specific and independent binary packages) foramd64
so arm64
and armhf
architectures build only the hellodeb
package, but amd64
builds also the hellodeb-doc
package. To remind, build type of any
runs clean
, build-arch
and binary-arch
targets of debian/rules
and build type of binary
runs clean
, build
and binary
targets (and not build-arch
and build-indep
separately). This is not very clear and I did not see this information in any documentation yet, so you need to be careful with your debian/rules
file, all targets should do what they are supposed to do.
Before uploading the source package to your PPA, you naturally need to create an account, create a PPA and verify the OpenPGP key, as I briefly mentioned before.
An additional tool, dput
, is needed to upload the source package, from dput
package. I also installed lintian
, which is a tool that checks the package for common errors.
After installing dput
, I created the configuration file ~/.dput.cf
:
$ cat ~/.dput.cf
[hellodeb]
fqdn = ppa.launchpad.net
method = ftp
incoming = ~metebalci/ubuntu/hellodeb/
login = anonymous
allow_unsigned_uploads = 0
run_lintian = 1
After building the source package by ./build_package source
, it can be uploaded with dput
. The second argument hellodeb
in this command refers to the section name [hellodeb]
in the configuration file, that is how it finds the name of the server to upload, method, the name of the PPA etc.
$ dput hellodeb hellodeb_1.0-8_source.changes
Checking signature on .changes
gpg: /home/mete/hellodeb/hellodeb_1.0-8_source.changes: Valid signature from C8DFA32F5BC52C01
Checking signature on .dsc
gpg: /home/mete/hellodeb/hellodeb_1.0-8.dsc: Valid signature from C8DFA32F5BC52C01
Package is now being checked with lintian.
Uploading to hellodeb (via ftp to ppa.launchpad.net):
Uploading hellodeb_1.0-8.dsc: done.
Uploading hellodeb_1.0-8.debian.tar.xz: done.
Uploading hellodeb_1.0-8_source.buildinfo: done.
Uploading hellodeb_1.0-8_source.changes: done.
Successfully uploaded packages.
As mentioned before, original source (orig.tar.xz) is not included in changes so it is not uploaded.
The PPA can be added to the system with sudo add-apt-repository ppa:metebalci/hellodeb
. After a sudo apt update
, hellodeb package can be seen:
$ apt-cache search hellodeb
hellodeb - hello world for Debian packaging
hellodeb-doc - hellodeb documentation
Lets install and try the program:
$ sudo apt install hellodeb hellodeb-doc
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
hellodeb hellodeb-doc
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
Need to get 3,352 B of archives.
After this operation, 4,096 B of additional disk space will be used.
Get:1 http://ppa.launchpad.net/metebalci/hellodeb/ubuntu focal/main amd64 hellodeb amd64 1.0-8 [2,292 B]
Get:2 http://ppa.launchpad.net/metebalci/hellodeb/ubuntu focal/main amd64 hellodeb-doc all 1.0-8 [1,060 B]
Fetched 3,352 B in 0s (39.8 kB/s)
Selecting previously unselected package hellodeb.
(Reading database ... 146030 files and directories currently installed.)
Preparing to unpack .../hellodeb_1.0-8_amd64.deb ...
Unpacking hellodeb (1.0-8) ...
Selecting previously unselected package hellodeb-doc.
Preparing to unpack .../hellodeb-doc_1.0-8_all.deb ...
Unpacking hellodeb-doc (1.0-8) ...
Setting up hellodeb (1.0-8) ...
Setting up hellodeb-doc (1.0-8) ...
Processing triggers for man-db (2.9.1-1) ...
Everything installed and works as expected. You can also see the man page with man hellodeb
.
$ which hellodeb
/usr/bin/hellodeb
$ hellodeb
hello deb
Deconstruction of a Full Package Build
Below is the output of a full package build, where each number step corresponds the number step in the manual page of dpkg-buildpackage
and the first word terminated by :
(if any) is the hook name (e.g. init) called within dpkg-buildpackage
. After this post, almost all of the output should make sense now.
build-package.sh
script prepares the versioned directory and runs dpkg-buildpackage --build=full
.
$ ./build-package.sh full
1- init: prepares the build environment, checks if debian/rules
is present and calls dpkg-source
for --before-build
hellodeb.c
hellodeb.1
dpkg-buildpackage: info: source package hellodeb
dpkg-buildpackage: info: source version 1.0-7
dpkg-buildpackage: info: source distribution focal
dpkg-buildpackage: info: source changed by Mete Balci <metebalci@gmail.com>
dpkg-buildpackage: info: host architecture amd64
dpkg-source --before-build .
2- dependencies are checked here but I dont have any dependencies so there is nothing displayed
3- preclean: calls debian/rules
for clean
fakeroot debian/rules clean
rm -f hellodeb
rm -f hellodeb.1.gz
rm -rf debian/tmp
4- source: calls dpkg-source
to build the source package
dpkg-source -b .
dpkg-source: info: using source format '3.0 (quilt)'
dpkg-source: info: building hellodeb using existing ./hellodeb_1.0.orig.tar.gz
dpkg-source: info: building hellodeb in hellodeb_1.0-7.debian.tar.xz
dpkg-source: info: building hellodeb in hellodeb_1.0-7.dsc
5- build: calls debian/rules
for build
and then binary
debian/rules build
x86_64-linux-gnu-gcc `dpkg-buildflags --get CFLAGS` -Wall -o hellodeb hellodeb.c
gzip -c hellodeb.1 > hellodeb.1.gz
fakeroot debian/rules binary
rm -rf debian/tmp
mkdir -p debian/tmp/DEBIAN
dpkg-gencontrol -phellodeb
mkdir -p debian/tmp/usr/bin
cp hellodeb debian/tmp/usr/bin
strip --strip-unneeded --remove-section=.comment --remove-section=.note debian/tmp/usr/bin/hellodeb
dpkg-deb --build debian/tmp ../hellodeb_1.0-7_amd64.deb
dpkg-deb: building package 'hellodeb' in '../hellodeb_1.0-7_amd64.deb'.
rm -rf debian/tmp
mkdir -p debian/tmp/DEBIAN
dpkg-gencontrol -phellodeb-doc
mkdir -p debian/tmp/usr/share/man/man1
cp hellodeb.1.gz debian/tmp/usr/share/man/man1
dpkg-deb --build debian/tmp ../hellodeb-doc_1.0-7_all.deb
dpkg-deb: building package 'hellodeb-doc' in '../hellodeb-doc_1.0-7_all.deb'.
6- buildinfo: calls dpkg-genbuildinfo
to generate buildinfo
build record file
dpkg-genbuildinfo --build=full
7- changes: calls dpkg-genchanges
to generate changes
upload control file
dpkg-genchanges --build=full >../hellodeb_1.0-7_amd64.changes
dpkg-genchanges: info: not including original source code in upload
8- postclean: since --post-clean
is not specified, nothing is done
9- calls dpkg-source
for --after-build
, and also describes the build
dpkg-source --after-build .
dpkg-buildpackage: info: binary and diff upload (original source NOT included)
10- check: since no check command (DEB_CHECK_COMMAND
) is specified, nothing is done
11- sign: calls gpg
to sign dsc
, buildinfo
and changes
files
signfile hellodeb_1.0-7.dsc
signfile hellodeb_1.0-7_amd64.buildinfo
signfile hellodeb_1.0-7_amd64.changes
12- done:
What is Missing in This Tutorial
- maintainer scripts
- creating a Debian repository
- dh_make, debuild
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.