Junichi Uekawa: Trying to send email.

git-buildpackage
commands, with all package-specific options in gbp.conf
.Files-Excluded
in the debian/copyright
file to filter out unwanted files in Debian.dh_make
to create the initial Debian packaging.mkdir debian-entr
cd debian-entr
git clone --origin upstreamvcs --branch master \
--single-branch https://github.com/eradman/entr.git
git clone
lay the foundation for the Debian packaging git repository structure where the upstream git remote name is upstreamvcs
. Only the upstream main branch is tracked to avoid cluttering git history with upstream development branches that are irrelevant for packaging in Debian.
Next, enter the git repository directory and list the git tags. Pick the latest upstream release tag as the commit to start the branch upstream/latest
. This latest refers to the upstream release, not the upstream development branch. Immediately after, branch off the debian/latest
branch, which will have the actual Debian packaging files in the debian/
subdirectory.
cd entr
git tag # shows the latest upstream release tag was '5.6'
git checkout -b upstream/latest 5.6
git checkout -b debian/latest
%% init: 'gitGraph': 'mainBranchName': 'master' %% gitGraph: checkout master commit id: "Upstream 5.6 release" tag: "5.6" branch upstream/latest checkout upstream/latest commit id: "New upstream version 5.6" tag: "upstream/5.6" branch debian/latest checkout debian/latest commit id: "Initial Debian packaging" commit id: "Additional change 1" commit id: "Additional change 2" commit id: "Additional change 3"At this point, the repository is structured according to DEP-14 conventions, ensuring a clear separation between upstream and Debian packaging changes, but there are no Debian changes yet. Next, add the Salsa repository as a new remote which called
origin
, the same as the default remote name in git.
git remote add origin git@salsa.debian.org:otto/entr-demo.git
git push --set-upstream origin debian/latest
debian/latest
branch, which does not yet have any debian/
directory.
cd ..
podman run --interactive --tty --rm --shm-size=1G --cap-add SYS_PTRACE \
--env='DEB*' --volume=$PWD:/tmp/test --workdir=/tmp/test debian:sid bash
--volume
parameter will loop-mount the current directory inside the container. Thus all files created and modified are on the host system, and will persist after the container shuts down.
Once inside the container, install the basic dependencies:
apt update -q && apt install -q --yes git-buildpackage dpkg-dev dh-make
debian/
files with dh-make
To create the files needed for the actual Debian packaging, use dh_make
:
# dh_make --packagename entr_5.6 --single --createorig
Maintainer Name : Otto Kek l inen
Email-Address : otto@debian.org
Date : Sat, 15 Feb 2025 01:17:51 +0000
Package Name : entr
Version : 5.6
License : blank
Package Type : single
Are the details correct? [Y/n/q]
Done. Please edit the files in the debian/ subdirectory now.
dh_make
works, the package name and version need to be written as a single underscore separated string. In this case, you should choose --single
to specify that the package type is a single binary package. Other options would be --library
for library packages (see libgda5 sources as an example) or --indep
(see dns-root-data sources as an example). The --createorig
will create a mock upstream release tarball (entr_5.6.orig.tar.xz
) from the current release directory, which is necessary due to historical reasons and how dh_make
worked before git repositories became common and Debian source packages were based off upstream release tarballs (e.g. *.tar.gz
).
At this stage, a debian/
directory has been created with template files, and you can start modifying the files and iterating towards actual working packaging.
git add debian/
git commit -a -m "Initial Debian packaging"
dh_make
would be:
-- entr
-- LICENSE
-- Makefile.bsd
-- Makefile.linux
-- Makefile.linux-compat
-- Makefile.macos
-- NEWS
-- README.md
-- configure
-- data.h
-- debian
-- README.Debian
-- README.source
-- changelog
-- control
-- copyright
-- gbp.conf
-- entr-docs.docs
-- entr.cron.d.ex
-- entr.doc-base.ex
-- manpage.1.ex
-- manpage.md.ex
-- manpage.sgml.ex
-- manpage.xml.ex
-- postinst.ex
-- postrm.ex
-- preinst.ex
-- prerm.ex
-- rules
-- salsa-ci.yml.ex
-- source
-- format
-- upstream
-- metadata.ex
-- watch.ex
-- entr.1
-- entr.c
-- missing
-- compat.h
-- kqueue_inotify.c
-- strlcpy.c
-- sys
-- event.h
-- status.c
-- status.h
-- system_test.sh
-- entr_5.6.orig.tar.xz
debian/
directory are:
changelog
,control
,copyright
,rules
..ex
are example files that won t have any effect until their content is adjusted and the suffix removed.
For detailed explanations of the purpose of each file in the debian/
subdirectory, see the following resources:
wrap-and-sort -vast
or debputy reformat --style=black
.
pcre2posix.h cannot be found
or that libcre2-posix.so
is missing, you can use these commands:
$ apt install -q --yes apt-file && apt-file update
$ apt-file search pcre2posix.h
libpcre2-dev: /usr/include/pcre2posix.h
$ apt-file search libpcre2-posix.so
libpcre2-dev: /usr/lib/x86_64-linux-gnu/libpcre2-posix.so
libpcre2-posix3: /usr/lib/x86_64-linux-gnu/libpcre2-posix.so.3
libpcre2-posix3: /usr/lib/x86_64-linux-gnu/libpcre2-posix.so.3.0.6
debian/control
should be extended to define a Build-Depends: libpcre2-dev
relationship.
There is also dpkg-depcheck that uses strace to trace the files the build process tries to access, and lists what Debian packages those files belong to. Example usage:
dpkg-depcheck -b debian/rules build
debian/
, test the build by running dpkg-buildpackage inside the container:
dpkg-buildpackage -uc -us -b
-uc -us
will skip signing the resulting Debian source package and other build artifacts. The -b
option will skip creating a source package and only build the (binary) *.deb
packages.
The output is very verbose and gives a large amount of context about what is happening during the build to make debugging build failures easier. In the build log of entr
you will see for example the line dh binary --buildsystem=makefile
. This and other dh
commands can also be run manually if there is a need to quickly repeat only a part of the build while debugging build failures.
To see what files were generated or modified by the build simply run git status --ignored
:
$ git status --ignored
On branch debian/latest
Untracked files:
(use "git add <file>..." to include in what will be committed)
debian/debhelper-build-stamp
debian/entr.debhelper.log
debian/entr.substvars
debian/files
Ignored files:
(use "git add -f <file>..." to include in what will be committed)
Makefile
compat.c
compat.o
debian/.debhelper/
debian/entr/
entr
entr.o
status.o
dpkg-buildpackage
will include running the command dh clean
, which assuming it is configured correctly in the debian/rules
file will reset the source directory to the original pristine state. The same can of course also be done with regular git commands git reset --hard; git clean -fdx
. To avoid accidentally committing unnecessary build artifacts in git, a debian/.gitignore
can be useful and it would typically include all four files listed as untracked above.
After a successful build you would have the following files:
-- entr
-- LICENSE
-- Makefile -> Makefile.linux
-- Makefile.bsd
-- Makefile.linux
-- Makefile.linux-compat
-- Makefile.macos
-- NEWS
-- README.md
-- compat.c
-- compat.o
-- configure
-- data.h
-- debian
-- README.source.md
-- changelog
-- control
-- copyright
-- debhelper-build-stamp
-- docs
-- entr
-- DEBIAN
-- control
-- md5sums
-- usr
-- bin
-- entr
-- share
-- doc
-- entr
-- NEWS.gz
-- README.md
-- changelog.Debian.gz
-- copyright
-- man
-- man1
-- entr.1.gz
-- entr.debhelper.log
-- entr.substvars
-- files
-- gbp.conf
-- patches
-- PR149-expand-aliases-in-system-test-script.patch
-- series
-- system-test-skip-no-tty.patch
-- system-test-with-system-binary.patch
-- rules
-- salsa-ci.yml
-- source
-- format
-- tests
-- control
-- upstream
-- metadata
-- signing-key.asc
-- watch
-- entr
-- entr.1
-- entr.c
-- entr.o
-- missing
-- compat.h
-- kqueue_inotify.c
-- strlcpy.c
-- sys
-- event.h
-- status.c
-- status.h
-- status.o
-- system_test.sh
-- entr-dbgsym_5.6-1_amd64.deb
-- entr_5.6-1.debian.tar.xz
-- entr_5.6-1.dsc
-- entr_5.6-1_amd64.buildinfo
-- entr_5.6-1_amd64.changes
-- entr_5.6-1_amd64.deb
-- entr_5.6.orig.tar.xz
debian/entr
are essentially what goes into the resulting entr_5.6-1_amd64.deb
package. Familiarizing yourself with the majority of the files in the original upstream source as well as all the resulting build artifacts is time consuming, but it is a necessary investment to get high-quality Debian packages.
There are also tools such as Debcraft that automate generating the build artifacts in separate output directories for each build, thus making it easy to compare the changes to correlate what change in the Debian packaging led to what change in the resulting build artifacts.
debian/watch
, debian/upstream/signing-key.asc
, and debian/gbp.conf
need to be present with the correct options. In the gbp.conf
file, ensure you have the correct options based on:
pristine-tar = True
.upstream-signatures = on
.upstream-vcs-tag = %(version%~%.)s
.gbp import-orig
with the current version explicitly defined:
$ gbp import-orig --uscan --upstream-version 5.6
gbp:info: Launching uscan...
gpgv: Signature made 7. Aug 2024 07.43.27 PDT
gpgv: using RSA key 519151D83E83D40A232B4D615C418B8631BC7C26
gpgv: Good signature from "Eric Radman <ericshane@eradman.com>"
gbp:info: Using uscan downloaded tarball ../entr_5.6.orig.tar.gz
gbp:info: Importing '../entr_5.6.orig.tar.gz' to branch 'upstream/latest'...
gbp:info: Source package is entr
gbp:info: Upstream version is 5.6
gbp:info: Replacing upstream source on 'debian/latest'
gbp:info: Running Postimport hook
gbp:info: Successfully imported version 5.6 of ../entr_5.6.orig.tar.gz
pristine-tar
branch, and store the tarball delta on it. This command will also attempt to create the tag upstream/5.6
on the upstream/latest
branch.
git fetch upstreamvcs; gbp import-orig --uscan
, which fetches the upstream git tags, checks for new upstream tarballs, and automatically downloads, verifies, and imports the new version. See the galera-4-demo
example in the Debian source packages in git explained post as a demo you can try running yourself and examine in detail.
You can also try running gbp import-orig --uscan
without specifying a version. It would fetch it, as it will notice there is now Entr version 5.7 available, and import it.
gbp buildpackage
, which will do a more comprehensive build.
gbp buildpackage -uc -us
git-buildpackage
build also includes running Lintian to find potential Debian policy violations in the sources or in the resulting .deb
binary packages. Many Debian Developers run lintian -EviIL +pedantic
after every build to check that there are no new nags, and to validate that changes intended to previous Lintian nags were correct.
debian/latest
branch to another name, for example next/debian/latest
, and open a Merge Request that targets the debian/latest
branch on your Salsa fork, which still has only the unmodified upstream files.
If you have followed the workflow in this post so far, you can simply run:
git checkout -b next/debian/latest
git push --set-upstream origin next/debian/latest
next/debian/latest
, rebase, force push, and request re-review as many times as you want.
While at it, make sure the Settings > CI/CD page has under CI/CD configuration file the value debian/salsa-ci.yml
so that the CI can run and give you immediate automated feedback.
For an example of an initial packaging Merge Request, see https://salsa.debian.org/otto/entr-demo/-/merge_requests/1.
debian/patches
), and can also easily be submitted upstream as any regular git commit (and rebased and resubmitted many times over).
First, decide if you want to work out of the upstream development branch and later cherry-pick to the Debian packaging branch, or work out of the Debian packaging branch and cherry-pick to an upstream branch.
The example below starts from the upstream development branch and then cherry-picks the commit into the git-buildpackage patch queue:
git checkout -b bugfix-branch master
nano entr.c
make
./entr # verify change works as expected
git commit -a -m "Commit title" -m "Commit body"
git push # submit upstream
gbp pq import --force --time-machine=10
git cherry-pick <commit id>
git commit --amend # extend commit message with DEP-3 metadata
gbp buildpackage -uc -us -b
./entr # verify change works as expected
gbp pq export --drop --commit
git commit --amend # Write commit message along lines "Add patch to .."
gbp pq import --force --time-machine=10
nano entr.c
git commit -a -m "Commit title" -m "Commit body"
gbp buildpackage -uc -us -b
./entr # verify change works as expected
gbp pq export --drop --commit
git commit --amend # Write commit message along lines "Add patch to .."
git checkout -b bugfix-branch master
git cherry-pick <commit id>
git commit --amend # prepare commit message for upstream submission
git push # submit upstream
gbp pq import --force --time-machine=10
gbp pq export --drop --commit
%% init: 'gitGraph': 'mainBranchName': 'debian/latest' %% gitGraph checkout debian/latest commit id: "Initial packaging" branch patch-queue/debian/latest checkout patch-queue/debian/latest commit id: "Delete debian/patches/..." commit id: "Patch 1 title" commit id: "Patch 2 title" commit id: "Patch 3 title"These can be run at any time, regardless if any
debian/patches
existed prior, or if existing patches applied cleanly or not, or if there were old patch queue branches around. Note that the extra -b
in gbp buildpackage -uc -us -b
instructs to build only binary packages, avoiding any nags from dpkg-source
that there are modifications in the upstream sources while building in the patches-applied mode.
dh_make --python
option for Python support directly in dh_make itself. The list is not complete and many more tools exist. For some languages, there are even competing options, such as for Go there is in addition to dh-make-golang
also Gophian.
When learning Debian packaging, there is no need to learn these tools upfront. Being aware that they exist is enough, and one can learn them only if and when one starts to package a project in a new programming language.
gbp buildpackage
on the Entr packaging repository above will result in several files:
entr_5.6-1_amd64.changes
entr_5.6-1_amd64.deb
entr_5.6-1.debian.tar.xz
entr_5.6-1.dsc
entr_5.6.orig.tar.gz
entr_5.6.orig.tar.gz.asc
entr_5.6-1_amd64.deb
is the binary package, which can be installed on a Debian/Ubuntu system. The rest of the files constitute the source package. To do a source-only build, run gbp buildpackage -S
and note the files produced:
entr_5.6-1_source.changes
entr_5.6-1.debian.tar.xz
entr_5.6-1.dsc
entr_5.6.orig.tar.gz
entr_5.6.orig.tar.gz.asc
.deb
for amd64, or any architecture that the package supports. It is important to grasp that the Debian source package is the preferred form to be able to build the binary packages on various Debian build systems, and the Debian source package is not the same thing as the Debian packaging git repository contents.
flowchart LR git[Git repository<br>branch debian/latest] --> gbp buildpackage -S src[Source Package<br>.dsc + .tar.xz] src --> dpkg-buildpackage bin[Binary Packages<br>.deb]If the package is large and complex, the build could result in multiple binary packages. One set of package definition files in
debian/
will however only ever result in a single source package.
Files-Excluded
lists in the debian/copyright
file
Some upstream projects may include binary files in their release, or other undesirable content that needs to be omitted from the source package in Debian. The easiest way to filter them out is by adding to the debian/copyright
file a Files-Excluded
field listing the undesired files. The debian/copyright
file is read by uscan
, which will repackage the upstream sources on-the-fly when importing new upstream releases.
For a real-life example, see the debian/copyright
files in the Godot package that lists:
Files-Excluded: platform/android/java/gradle/wrapper/gradle-wrapper.jar
+ds
to signify that it is not the true original upstream source but has been modified by Debian:
godot_4.3+ds.orig.tar.xz
godot_4.3+ds-1_amd64.deb
debian/latest
branch on a clone of the upstream git repository as the starting point for the Debian packaging, but one must revert the traditional way of starting from an upstream release tarball with gbp import-orig package-1.0.tar.gz
.
.deb
packaging format and the tooling to work with it have evolved several generations. In the past 10 years, more and more Debian Developers have converged on certain core practices evidenced by https://trends.debian.net/, but there is still a lot of variance in workflows even for identical tasks. Hopefully, you find this post useful in giving practical guidance on how exactly to do the most common things when packaging software for Debian.
Happy packaging!
+
/-
on the keyboard, mouse wheel,
gesture) works.
End-to-end, the major development for this release was done over
around two weeks, which is pretty short: I extensively used Claude
Sonnet and Grok to unblock myself. Not to write code per se - although
there is code written 1:1 by LLMs, but most of the code is weirdly
wrong, and I have to either correct it or just use it as a starter and
rewrite most of it. But to discuss and unblock, and learn about new
things, the current LLMs are very good at.
And yet, sometimes even what they re good at, fails hard. I asked for
ideas to simplify a piece of code, and it went nowhere, even if there
were significant rewrite possibilities. I spent the brain cycles on
it, reverse engineered my own code, then simplified. I ll have to
write a separate blog post on this
In any case, this (zooming) was the last major feature I was
missing. There are image viewer libraries, but most of them slow,
compared to the bare-bones (well, now not so much anymore) viewer that
I use as main viewer. From now on, it will me minor incremental
features, mostly around Exif management/handling, etc. Or, well,
internal cleanups: extend test coverage, remove use of JQuery in the
frontend, etc., there are tons of things to do.
Fun fact: I managed to discover a Safari iOS bug. Or at least I think
it s a bug, so reported
it and curious
what ll come out of it.
Finally, I still couldn t fix the GitHub actions bug where the git
describe doesn t see the just pushed tag, sigh, so the demo site still
lists Corydalis v2024.12.0-133-g00edf63
as the version .
git-buildpackage
commands, with all package-specific options in gbp.conf
.Files-Excluded
in the debian/copyright
file to filter out unwanted files in Debian.dh_make
to create the initial Debian packaging.mkdir debian-entr
cd debian-entr
git clone --origin upstreamvcs --branch master \
--single-branch https://github.com/eradman/entr.git
git clone
lay the foundation for the Debian packaging git repository structure where the upstream git remote name is upstreamvcs
. Only the upstream main branch is tracked to avoid cluttering git history with upstream development branches that are irrelevant for packaging in Debian.
Next, enter the git repository directory and list the git tags. Pick the latest upstream release tag as the commit to start the branch upstream/latest
. This latest refers to the upstream release, not the upstream development branch. Immediately after, branch off the debian/latest
branch, which will have the actual Debian packaging files in the debian/
subdirectory.
cd entr
git tag # shows the latest upstream release tag was '5.6'
git checkout -b upstream/latest 5.6
git checkout -b debian/latest
%% init: 'gitGraph': 'mainBranchName': 'master' %% gitGraph: checkout master commit id: "Upstream 5.6 release" tag: "5.6" branch upstream/latest checkout upstream/latest commit id: "New upstream version 5.6" tag: "upstream/5.6" branch debian/latest checkout debian/latest commit id: "Initial Debian packaging" commit id: "Additional change 1" commit id: "Additional change 2" commit id: "Additional change 3"At this point, the repository is structured according to DEP-14 conventions, ensuring a clear separation between upstream and Debian packaging changes, but there are no Debian changes yet. Next, add the Salsa repository as a new remote which called
origin
, the same as the default remote name in git.
git remote add origin git@salsa.debian.org:otto/entr-demo.git
git push --set-upstream origin debian/latest
debian/latest
branch, which does not yet have any debian/
directory.
cd ..
podman run --interactive --tty --rm --shm-size=1G --cap-add SYS_PTRACE \
--env='DEB*' --volume=$PWD:/tmp/test --workdir=/tmp/test debian:sid bash
--volume
parameter will loop-mount the current directory inside the container. Thus all files created and modified are on the host system, and will persist after the container shuts down.
Once inside the container, install the basic dependencies:
apt update -q && apt install -q --yes git-buildpackage dpkg-dev dh-make
debian/
files with dh-make
To create the files needed for the actual Debian packaging, use dh_make
:
# dh_make --packagename entr_5.6 --single --createorig
Maintainer Name : Otto Kek l inen
Email-Address : otto@debian.org
Date : Sat, 15 Feb 2025 01:17:51 +0000
Package Name : entr
Version : 5.6
License : blank
Package Type : single
Are the details correct? [Y/n/q]
Done. Please edit the files in the debian/ subdirectory now.
dh_make
works, the package name and version need to be written as a single underscore separated string. In this case, you should choose --single
to specify that the package type is a single binary package. Other options would be --library
for library packages (see libgda5 sources as an example) or --indep
(see dns-root-data sources as an example). The --createorig
will create a mock upstream release tarball (entr_5.6.orig.tar.xz
) from the current release directory, which is necessary due to historical reasons and how dh_make
worked before git repositories became common and Debian source packages were based off upstream release tarballs (e.g. *.tar.gz
).
At this stage, a debian/
directory has been created with template files, and you can start modifying the files and iterating towards actual working packaging.
git add debian/
git commit -a -m "Initial Debian packaging"
dh_make
would be:
-- entr
-- LICENSE
-- Makefile.bsd
-- Makefile.linux
-- Makefile.linux-compat
-- Makefile.macos
-- NEWS
-- README.md
-- configure
-- data.h
-- debian
-- README.Debian
-- README.source
-- changelog
-- control
-- copyright
-- gbp.conf
-- entr-docs.docs
-- entr.cron.d.ex
-- entr.doc-base.ex
-- manpage.1.ex
-- manpage.md.ex
-- manpage.sgml.ex
-- manpage.xml.ex
-- postinst.ex
-- postrm.ex
-- preinst.ex
-- prerm.ex
-- rules
-- salsa-ci.yml.ex
-- source
-- format
-- upstream
-- metadata.ex
-- watch.ex
-- entr.1
-- entr.c
-- missing
-- compat.h
-- kqueue_inotify.c
-- strlcpy.c
-- sys
-- event.h
-- status.c
-- status.h
-- system_test.sh
-- entr_5.6.orig.tar.xz
debian/
directory are:
changelog
,control
,copyright
,rules
..ex
are example files that won t have any effect until their content is adjusted and the suffix removed.
For detailed explanations of the purpose of each file in the debian/
subdirectory, see the following resources:
wrap-and-sort -vast
or debputy reformat --style=black
.
pcre2posix.h cannot be found
or that libcre2-posix.so
is missing, you can use these commands:
$ apt install -q --yes apt-file && apt-file update
$ apt-file search pcre2posix.h
libpcre2-dev: /usr/include/pcre2posix.h
$ apt-file search libpcre2-posix.so
libpcre2-dev: /usr/lib/x86_64-linux-gnu/libpcre2-posix.so
libpcre2-posix3: /usr/lib/x86_64-linux-gnu/libpcre2-posix.so.3
libpcre2-posix3: /usr/lib/x86_64-linux-gnu/libpcre2-posix.so.3.0.6
debian/control
should be extended to define a Build-Depends: libpcre2-dev
relationship.
There is also dpkg-depcheck that uses strace to trace the files the build process tries to access, and lists what Debian packages those files belong to. Example usage:
dpkg-depcheck -b debian/rules build
debian/
, test the build by running dpkg-buildpackage inside the container:
dpkg-buildpackage -uc -us -b
-uc -us
will skip signing the resulting Debian source package and other build artifacts. The -b
option will skip creating a source package and only build the (binary) *.deb
packages.
The output is very verbose and gives a large amount of context about what is happening during the build to make debugging build failures easier. In the build log of entr
you will see for example the line dh binary --buildsystem=makefile
. This and other dh
commands can also be run manually if there is a need to quickly repeat only a part of the build while debugging build failures.
To see what files were generated or modified by the build simply run git status --ignored
:
$ git status --ignored
On branch debian/latest
Untracked files:
(use "git add <file>..." to include in what will be committed)
debian/debhelper-build-stamp
debian/entr.debhelper.log
debian/entr.substvars
debian/files
Ignored files:
(use "git add -f <file>..." to include in what will be committed)
Makefile
compat.c
compat.o
debian/.debhelper/
debian/entr/
entr
entr.o
status.o
dpkg-buildpackage
will include running the command dh clean
, which assuming it is configured correctly in the debian/rules
file will reset the source directory to the original pristine state. The same can of course also be done with regular git commands git reset --hard; git clean -fdx
. To avoid accidentally committing unnecessary build artifacts in git, a debian/.gitignore
can be useful and it would typically include all four files listed as untracked above.
After a successful build you would have the following files:
-- entr
-- LICENSE
-- Makefile -> Makefile.linux
-- Makefile.bsd
-- Makefile.linux
-- Makefile.linux-compat
-- Makefile.macos
-- NEWS
-- README.md
-- compat.c
-- compat.o
-- configure
-- data.h
-- debian
-- README.source.md
-- changelog
-- control
-- copyright
-- debhelper-build-stamp
-- docs
-- entr
-- DEBIAN
-- control
-- md5sums
-- usr
-- bin
-- entr
-- share
-- doc
-- entr
-- NEWS.gz
-- README.md
-- changelog.Debian.gz
-- copyright
-- man
-- man1
-- entr.1.gz
-- entr.debhelper.log
-- entr.substvars
-- files
-- gbp.conf
-- patches
-- PR149-expand-aliases-in-system-test-script.patch
-- series
-- system-test-skip-no-tty.patch
-- system-test-with-system-binary.patch
-- rules
-- salsa-ci.yml
-- source
-- format
-- tests
-- control
-- upstream
-- metadata
-- signing-key.asc
-- watch
-- entr
-- entr.1
-- entr.c
-- entr.o
-- missing
-- compat.h
-- kqueue_inotify.c
-- strlcpy.c
-- sys
-- event.h
-- status.c
-- status.h
-- status.o
-- system_test.sh
-- entr-dbgsym_5.6-1_amd64.deb
-- entr_5.6-1.debian.tar.xz
-- entr_5.6-1.dsc
-- entr_5.6-1_amd64.buildinfo
-- entr_5.6-1_amd64.changes
-- entr_5.6-1_amd64.deb
-- entr_5.6.orig.tar.xz
debian/entr
are essentially what goes into the resulting entr_5.6-1_amd64.deb
package. Familiarizing yourself with the majority of the files in the original upstream source as well as all the resulting build artifacts is time consuming, but it is a necessary investment to get high-quality Debian packages.
There are also tools such as Debcraft that automate generating the build artifacts in separate output directories for each build, thus making it easy to compare the changes to correlate what change in the Debian packaging led to what change in the resulting build artifacts.
debian/watch
, debian/upstream/signing-key.asc
, and debian/gbp.conf
need to be present with the correct options. In the gbp.conf
file, ensure you have the correct options based on:
pristine-tar = True
.upstream-signatures = on
.upstream-vcs-tag = %(version%~%.)s
.gbp import-orig
with the current version explicitly defined:
$ gbp import-orig --uscan --upstream-version 5.6
gbp:info: Launching uscan...
gpgv: Signature made 7. Aug 2024 07.43.27 PDT
gpgv: using RSA key 519151D83E83D40A232B4D615C418B8631BC7C26
gpgv: Good signature from "Eric Radman <ericshane@eradman.com>"
gbp:info: Using uscan downloaded tarball ../entr_5.6.orig.tar.gz
gbp:info: Importing '../entr_5.6.orig.tar.gz' to branch 'upstream/latest'...
gbp:info: Source package is entr
gbp:info: Upstream version is 5.6
gbp:info: Replacing upstream source on 'debian/latest'
gbp:info: Running Postimport hook
gbp:info: Successfully imported version 5.6 of ../entr_5.6.orig.tar.gz
pristine-tar
branch, and store the tarball delta on it. This command will also attempt to create the tag upstream/5.6
on the upstream/latest
branch.
git fetch upstreamvcs; gbp import-orig --uscan
, which fetches the upstream git tags, checks for new upstream tarballs, and automatically downloads, verifies, and imports the new version. See the galera-4-demo
example in the Debian source packages in git explained post as a demo you can try running yourself and examine in detail.
You can also try running gbp import-orig --uscan
without specifying a version. It would fetch it, as it will notice there is now Entr version 5.7 available, and import it.
gbp buildpackage
, which will do a more comprehensive build.
gbp buildpackage -uc -us
git-buildpackage
build also includes running Lintian to find potential Debian policy violations in the sources or in the resulting .deb
binary packages. Many Debian Developers run lintian -EviIL +pedantic
after every build to check that there are no new nags, and to validate that changes intended to previous Lintian nags were correct.
debian/latest
branch to another name, for example next/debian/latest
, and open a Merge Request that targets the debian/latest
branch on your Salsa fork, which still has only the unmodified upstream files.
If you have followed the workflow in this post so far, you can simply run:
git checkout -b next/debian/latest
git push --set-upstream origin next/debian/latest
next/debian/latest
, rebase, force push, and request re-review as many times as you want.
While at it, make sure the Settings > CI/CD page has under CI/CD configuration file the value debian/salsa-ci.yml
so that the CI can run and give you immediate automated feedback.
For an example of an initial packaging Merge Request, see https://salsa.debian.org/otto/entr-demo/-/merge_requests/1.
debian/patches
), and can also easily be submitted upstream as any regular git commit (and rebased and resubmitted many times over).
First, decide if you want to work out of the upstream development branch and later cherry-pick to the Debian packaging branch, or work out of the Debian packaging branch and cherry-pick to an upstream branch.
The example below starts from the upstream development branch and then cherry-picks the commit into the git-buildpackage patch queue:
git checkout -b bugfix-branch master
nano entr.c
make
./entr # verify change works as expected
git commit -a -m "Commit title" -m "Commit body"
git push # submit upstream
gbp pq import --force --time-machine=10
git cherry-pick <commit id>
git commit --amend # extend commit message with DEP-3 metadata
gbp buildpackage -uc -us -b
./entr # verify change works as expected
gbp pq export --drop --commit
git commit --amend # Write commit message along lines "Add patch to .."
gbp pq import --force --time-machine=10
nano entr.c
git commit -a -m "Commit title" -m "Commit body"
gbp buildpackage -uc -us -b
./entr # verify change works as expected
gbp pq export --drop --commit
git commit --amend # Write commit message along lines "Add patch to .."
git checkout -b bugfix-branch master
git cherry-pick <commit id>
git commit --amend # prepare commit message for upstream submission
git push # submit upstream
gbp pq import --force --time-machine=10
gbp pq export --drop --commit
%% init: 'gitGraph': 'mainBranchName': 'debian/latest' %% gitGraph checkout debian/latest commit id: "Initial packaging" branch patch-queue/debian/latest checkout patch-queue/debian/latest commit id: "Delete debian/patches/..." commit id: "Patch 1 title" commit id: "Patch 2 title" commit id: "Patch 3 title"These can be run at any time, regardless if any
debian/patches
existed prior, or if existing patches applied cleanly or not, or if there were old patch queue branches around. Note that the extra -b
in gbp buildpackage -uc -us -b
instructs to build only binary packages, avoiding any nags from dpkg-source
that there are modifications in the upstream sources while building in the patches-applied mode.
dh_make --python
option for Python support directly in dh_make itself. The list is not complete and many more tools exist. For some languages, there are even competing options, such as for Go there is in addition to dh-make-golang
also Gophian.
When learning Debian packaging, there is no need to learn these tools upfront. Being aware that they exist is enough, and one can learn them only if and when one starts to package a project in a new programming language.
gbp buildpackage
on the Entr packaging repository above will result in several files:
entr_5.6-1_amd64.changes
entr_5.6-1_amd64.deb
entr_5.6-1.debian.tar.xz
entr_5.6-1.dsc
entr_5.6.orig.tar.gz
entr_5.6.orig.tar.gz.asc
entr_5.6-1_amd64.deb
is the binary package, which can be installed on a Debian/Ubuntu system. The rest of the files constitute the source package. To do a source-only build, run gbp buildpackage -S
and note the files produced:
entr_5.6-1_source.changes
entr_5.6-1.debian.tar.xz
entr_5.6-1.dsc
entr_5.6.orig.tar.gz
entr_5.6.orig.tar.gz.asc
.deb
for amd64, or any architecture that the package supports. It is important to grasp that the Debian source package is the preferred form to be able to build the binary packages on various Debian build systems, and the Debian source package is not the same thing as the Debian packaging git repository contents.
flowchart LR git[Git repository<br>branch debian/latest] --> gbp buildpackage -S src[Source Package<br>.dsc + .tar.xz] src --> dpkg-buildpackage bin[Binary Packages<br>.deb]If the package is large and complex, the build could result in multiple binary packages. One set of package definition files in
debian/
will however only ever result in a single source package.
Files-Excluded
lists in the debian/copyright
file
Some upstream projects may include binary files in their release, or other undesirable content that needs to be omitted from the source package in Debian. The easiest way to filter them out is by adding to the debian/copyright
file a Files-Excluded
field listing the undesired files. The debian/copyright
file is read by uscan
, which will repackage the upstream sources on-the-fly when importing new upstream releases.
For a real-life example, see the debian/copyright
files in the Godot package that lists:
Files-Excluded: platform/android/java/gradle/wrapper/gradle-wrapper.jar
+ds
to signify that it is not the true original upstream source but has been modified by Debian:
godot_4.3+ds.orig.tar.xz
godot_4.3+ds-1_amd64.deb
debian/latest
branch on a clone of the upstream git repository as the starting point for the Debian packaging, but one must revert the traditional way of starting from an upstream release tarball with gbp import-orig package-1.0.tar.gz
.
.deb
packaging format and the tooling to work with it have evolved several generations. In the past 10 years, more and more Debian Developers have converged on certain core practices evidenced by https://trends.debian.net/, but there is still a lot of variance in workflows even for identical tasks. Hopefully, you find this post useful in giving practical guidance on how exactly to do the most common things when packaging software for Debian.
Happy packaging!
A # install request for A
B # manually installed, keep it
A depends on: conflicts-B C
Installing A
on a system with B
installed installed C
, as it was not allowed to
install the conflicts-B
package since B
is installed.
However, I also introduced a mode to allow removing manually installed packages, and that s
where it broke down, now instead of B
being a fact, our clauses looked like:
A # install request for A
A depends on: conflicts-B C
Optional: B # try to keep B installed
As a result, we installed conflicts-B
and removed B
; the steps the solver takes are:
A
is a fact, mark itA depends on: conflicts-B C
is the strongest clause, try to install conflicts-B
conflicts-B
conflicts with B
, so we mark not B
Optional: B
is reached, but not satisfiable, ignore it because it s optional.for fact in facts:
enqueue(fact)
if not propagate():
return False
for optionalLiteral in optionalLiterals:
registerClause(SoftClause([optionalLiteral]))
if assume(optionalLiteral) and not propagate():
undo()
while True:
if not propagate():
if not backtrack():
return False
elif <all clauses are satisfied>:
return True
elif it := find("best unassigned literal satisfying a hard clause"):
assume(it)
elif it := find("best literal satisfying a soft clause"):
assume(it)
A,B,C
and B
is not possible, we will have also undone C
. But since
C
is also enqueued as a soft clause, we will then later find it again:
A
: State=[Assume(A)]
, Clauses=[SoftClause([A])]
B
: State=[Assume(A),Assume(B)]
, Clauses=[SoftClause([A]),SoftClause([B])]
C
: State=[Assume(A),Assume(B),Assume(C)]
, Clauses=[SoftClause([A]),SoftClause([B]),SoftClause([C])]
not C
: State=[Assume(A),Assume(B),not(C)]
not B
: State=[Assume(A),not(B)]
C is no longer assumed eitherC
as it satisfies SoftClause([C])
as next best literal: State=[Assume(A),not(B),Assume(C)]
A
, not B
, and C
.Optional: A
Optional: B
Optional: C
B Conflicts with A
C Conflicts with A
There are two possible results here:
A
If we assume A
first, we are unable to satisfy B
or C
. B,C
If we assume either B
or C
first, A
is unsat.2**n
times for n
soft clauses, whereas our heuristic only needs n
runs.
For dependency solving, it seems we do not seem have a strong need for a global maximum:
There are various other preferences between our literals, say priorities;
and empirically, from evaluating hundreds of regressions without the initial assumptions,
I can say that the assumptions do fix those cases and the result is correct.
Further improvements exist, though, and we can look into them if they are needed, such as:
pflogsumm
from /usr/sbin
to /usr/bin
!
There was not really a good reason to ever have it in sbin
. It's neither a system binary,
nor statically linked (like in the very old days), or something that really only makes sense
to be used as root. Some out there likely have custom scripts which do not rely on an
adjusted PATH
variable, those scripts require an update.
middle
emulation enabled
, but the buttons are separated it requires clicking
with both thumbs, which is unelegant, to say the least.
I remapped some of the spare keys to be mouse buttons 1 5, and it worked
for middle click, but not for scroll events. Maybe I could tweak it a bit
more but I didn t in the end.
Courtesy of my CRANberries, there is a diffstat report relative to previous release. More detailed information is on the RcppArmadillo page. Questions, comments etc should go to the rcpp-devel mailing list off the Rcpp R-Forge page.Changes in RcppArmadillo version 14.4.3-1 (2025-05-21)
- Upgraded to Armadillo release 14.4.3 (Filtered Espresso)
- Fix for several corner cases involving handling of non-finite elements by sparse matrices
This post by Dirk Eddelbuettel originated on his Thinking inside the box blog. If you like this or other open-source work I do, you can sponsor me at GitHub.
Hey folks! Ope, you might need the Midwest Voice Translator on this one. Read this one in a heavy Midwest accent, and tell your folks I
Next.