Debian package 打包入門
Debian package 打包是把上游原始碼加上 debian/ 目錄,描述如何建置、相依與安裝,再產生 source package(.dsc)與 binary package(.deb)。
這篇以 GNU hello 2.12.1 為例,鎖定 Ubuntu 26.04(resolute)與 amd64,一步步完成:
- 前置設定作業
- 針對程式進行打包設定 (修改
debian/) - 驗證修改 (用
sbuild和lintian確認有沒有問題)
完成後會得到可上傳的 _source.changes,接著請參考 上傳套件到自己的 PPA。
前置設定作業
安裝工具
sudo apt update
sudo apt install build-essential devscripts dh-make debhelper lintian sbuild schroot debootstrap ubuntu-keyring quilt wget
設定環境變數
先設定維護者資訊,請換成自己的姓名與已在 Launchpad 驗證的 Email:
建議將這些資訊放入 ~/.bashrc 或 ~/.zshrc。
針對程式進行打包設定
下載原始碼並產生 debian 目錄
ftp.gnu.org 在部分網路環境可能連線逾時,以下使用 kernel.org 的 GNU 鏡像站下載同一個版本。
mkdir -p ppa-work
cd ppa-work
wget https://mirrors.kernel.org/gnu/hello/hello-2.12.1.tar.gz
tar -xzf hello-2.12.1.tar.gz
cd hello-2.12.1
dh_make --single --copyright gpl3 --file ../hello-2.12.1.tar.gz
確認提示後,dh_make 會產生 debian/ 樣板,以及上層目錄的 hello_2.12.1.orig.tar.gz。
--single 表示先產生單一二進位套件,--copyright gpl3 選擇 GPLv3 授權樣板;其他專案必須依實際授權調整。
修改打包設定
dh_make 產生的 debian/ 是套件的建置與發佈設定。先了解各檔案用途,再修改和這個套件有關的部分:
| 檔案 | 用途 | 這個範例要做的事 |
|---|---|---|
debian/control |
原始碼套件、二進位套件及相依套件的描述 | 填入套件資訊,列出建置所需的 Build-Depends。 |
debian/changelog |
套件版本、目標 Ubuntu 發行版與修改紀錄 | 建立 resolute 版本項目;每次上傳都要使用新版本號。 |
debian/rules |
定義 debhelper 如何清理、設定、建置與測試 | 使用 dh $@,並略過沒有 Makefile 時不適用的清理。 |
debian/source/format |
原始碼套件格式 | 保留 3.0 (quilt),讓 dpkg-source 套用 Debian 補丁。 |
debian/copyright |
上游檔案的版權與授權資訊 | 依 GNU hello 的 COPYING 填妥,不要保留未完成的樣板。 |
debian/patches/series 與補丁檔 |
記錄要套用到上游原始碼的修改及順序 | 用 Quilt 保存 gettext 版本修正。 |
debian/*.ex、debian/*.EX |
可選的範例設定檔 | 不使用的樣板可刪除;要使用則先改成有效設定。 |
debian/control
將 debian/control 調整為以下內容,維護者請換成自己的資訊:
Source: hello
Section: devel
Priority: optional
Maintainer: Your Name <you@example.com>
Build-Depends: debhelper-compat (= 13), texinfo, help2man
Standards-Version: 4.7.3
Homepage: https://www.gnu.org/software/hello/
Rules-Requires-Root: no
Package: hello
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: GNU Hello demonstration program
GNU Hello prints a greeting and demonstrates GNU coding conventions.
Build-Depends 是編譯需要的套件,由 sbuild 安裝到建置環境;Depends 是使用者安裝時需要的執行相依套件。
${shlibs:Depends} 與 ${misc:Depends} 由打包工具計算,不需手動換成套件名稱。
GNU hello 的文件建置與測試會用到 makeinfo,此程式由 texinfo 套件提供;請將它列在 Build-Depends,而不是只安裝在主機上。
help2man 用來產生 man page。
debian/changelog
在原始碼目錄建立目標 Ubuntu 版本的項目:
-b 允許新版號低於 dh_make 產生的初始版本。PPA 不允許以相同版本號覆蓋既有套件,因此每次重新上傳都要增加版本號。
dch 會開啟編輯器,並直接改寫 dh_make 產生的第一個項目。請把樣板中的 Initial release. (Closes: #nnnn) <nnnn is the bug number of your ITP> 改成實際說明,例如 Initial release.,否則 Lintian 會回報 changelog-is-dh_make-template。儲存後,第一行應類似:
Debian 版號格式為 [epoch:]upstream_version-debian_revision:
epoch:可選欄位。上游改版導致新版號排序反而較舊時,用它調整排序,例如10.0-1改成1:2.0-1。upstream_version:上游版本,例如2.12.1。debian_revision:套件維護者的修訂版。Ubuntu 直接打包時常用0ubuntu1;若從 Debian 修訂版1延伸,常見形式是1ubuntu1。~resolute1:可選的 PPA 後綴,用來標示 Resolute 的 PPA 修訂序號;同一 suite 後續上傳可遞增為~resolute2。目標 suite 本身由 changelog 的resolutedistribution 欄位指定。
版號後綴會影響 APT 的版本排序:~ 排在沒有後綴的版號之前,+ 則排在它之後。因此不要直接把 ~resolute1 加到已存在的 0.7.0-1ubuntu2 後面,因為 0.7.0-1ubuntu2~resolute1 會比官方版舊。若 Resolute 官方版是 0.7.0-1ubuntu2,PPA 測試版可用 0.7.0-1ubuntu2+resolute1;或提高 Ubuntu 修訂號後使用 0.7.0-1ubuntu3~resolute1。PPA 後續更新要遞增自己的序號,不能重用已上傳的同版號。
debian/copyright
這個檔案使用 DEP-5 格式,逐組記錄檔案的著作權人與授權。
先從 AUTHORS、COPYING 和各檔案的授權標頭確認資訊,再移除其他檔案內原始的 comment,否則 lintian 會報錯。
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Source: https://ftp.gnu.org/gnu/hello/
Upstream-Name: GNU hello
Files:
*
Copyright: 1992-2022 Free Software Foundation, Inc.
License: GPL-3.0+
Files: debian/*
Copyright: 2026 Your Name <you@example.com>
License: GPL-3.0+
License: GPL-3.0+
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.
.
On Debian systems, the complete text of the GNU General Public
License version 3 can be found in "/usr/share/common-licenses/GPL-3".
debian/rules
GNU hello 使用標準的 configure 與 make 流程。
上游的 GNUmakefile 在 ./configure 尚未產生 Makefile 時也存在,若直接使用預設的 dh_auto_clean,初次清理可能會誤執行 make distclean 而失敗。
因此在 debian/rules 加上條件:
recipe(override_dh_auto_clean: 與 %: 下面的指令)前面必須是 Tab,不是空白;用空白會出現 missing separator 錯誤。
另外可以把既有的 comments 都刪除,不然後續的 lintian 會有 Error 錯誤出現。
最後確認 debian/rules 有執行權限:
修正 gettext 範本版本
GNU hello 2.12.1 的 configure.ac 宣告 gettext 0.18.1,但封存檔內已產生的 configure 與 po/Makefile.in.in 使用 0.20。
Debhelper 執行 dh_autoreconf 時,會依照 configure.ac 重新產生 gettext 檔案,造成版本不一致並在 po/ 建置失敗。
Quilt 用來管理對上游原始碼的修改,會將修改記錄成 debian/patches/ 下的補丁;3.0 (quilt) 格式會在建置時套用這些補丁。
以下建立一個補丁,將版本宣告修正為 0.20:
# 建立存放補丁的目錄。
mkdir -p debian/patches
# 指定 Quilt 使用 Debian 套件慣例的補丁目錄。
export QUILT_PATCHES=debian/patches
# 開始建立新的 gettext 版本修正補丁。
quilt new gettext-macro-version.patch
# 告訴 Quilt 接下來要修改 configure.ac。
quilt add configure.ac
# 將 gettext 版本宣告從 0.18.1 改為 0.20。
sed -i 's/AM_GNU_GETTEXT_VERSION(\[0\.18\.1\])/AM_GNU_GETTEXT_VERSION([0.20])/' configure.ac
# 將檔案變更寫入補丁,並更新補丁清單。
quilt refresh
確認 debian/patches/series 列有 gettext-macro-version.patch,且補丁只把 AM_GNU_GETTEXT_VERSION([0.18.1]) 改成 AM_GNU_GETTEXT_VERSION([0.20])。
其他檔案
debian/ 內還有很多其他範例,例如 *.ex(其中 upstream.ex 是目錄)或是 README.*,如果沒有用到可以先刪除。請在原始碼目錄執行:
驗證修改
設定 sbuild 乾淨環境
以下使用 schroot backend。將使用者加入 sbuild 群組:
登出再登入,讓群組設定生效。接著建立 Resolute 的建置環境,這個步驟只需做一次,會下載套件並使用磁碟空間:
sudo mkdir -p /srv/chroot
# 建立 Resolute amd64 的 sbuild chroot tarball。
sudo sbuild-createchroot --arch=amd64 --components=main,universe \
--keyring=/usr/share/keyrings/ubuntu-archive-keyring.gpg \
--make-sbuild-tarball=/srv/chroot/resolute-amd64-sbuild.tar.gz \
resolute /srv/chroot/resolute-amd64-sbuild http://archive.ubuntu.com/ubuntu
# 列出 schroot 已設定的環境,確認 Resolute chroot 已建立。
schroot --list
確認清單中有 resolute-amd64-sbuild 對應的 chroot。打包與建置操作使用一般使用者,不要執行 sudo sbuild。
此範例不涵蓋跨架構本地建置;ARM 主機需使用適當的架構與 Ubuntu ports mirror,不能只照抄 amd64 設定。
產生原始碼套件並使用 sbuild 測試
重新進入原始碼目錄,先產生尚未簽署的原始碼套件:
cd ppa-work/hello-2.12.1
# 產生未簽署的原始碼套件(副檔名為.dsc),包含上游原始碼封存檔。
dpkg-buildpackage -S -sa -us -uc -d
# 要在原始碼的資料夾外執行 sbuild
cd ..
# 在 Resolute chroot 中安裝建置相依套件並編譯來源套件。
sbuild --chroot-mode=schroot -d resolute hello_2.12.1-0ubuntu1~resolute1.dsc
-S -sa:產生原始碼套件,並包含第一次上傳需要的上游封存檔。-us -uc:先不簽署,等本地測試完成後再簽署。-d:此處略過主機的建置相依檢查;真正的相依安裝與編譯由sbuild在 chroot 中進行。
sbuild 會讀取 .dsc,在乾淨環境中安裝 Build-Depends 並編譯。
以此指令執行時,產物位於目前的 ~/ppa-work/,包含 .deb、_amd64.changes 與 build log。
確認 log 最後顯示 Status: successful;失敗時先修正打包設定,再重新產生原始碼套件與測試。
Lintian 檢查
在 ~/ppa-work/ 執行:
# 檢查 sbuild 產生的二進位套件與套件資訊。
lintian -I -i --pedantic hello_2.12.1-0ubuntu1~resolute1_amd64.changes
# 檢查 source package、debian/ 設定及原始碼檔案。
lintian -I -i --pedantic hello_2.12.1-0ubuntu1~resolute1_source.changes
優先修正 E:(錯誤);逐項檢查 W:(警告),修正問題或確認並記錄合理原因。
I: 是資訊提示,P: 是較嚴格的建議;不一定都要修改,但仍應確認沒有隱藏實際問題。
修改 debian/ 後,重新產生原始碼套件、執行 sbuild 與 Lintian,避免上傳與測試不同的內容。
產生的檔案說明
在執行過程中,你會發現程式碼資料夾外有多種產物,下面解釋各個檔案的意義:
| 檔案 | 產生指令 | 用途 |
|---|---|---|
hello-2.12.1.tar.gz |
wget |
下載的上游原始碼。 |
hello_2.12.1.orig.tar.gz |
dh_make --file |
dpkg source package 使用的上游原始碼封存檔。 |
hello_<version>.debian.tar.xz |
dpkg-buildpackage -S |
Debian 打包設定與補丁。 |
hello_<version>.dsc |
dpkg-buildpackage -S |
Source package 描述檔,列出檔案及校驗資訊;sbuild 以此為輸入。 |
hello_<version>_source.changes |
dpkg-buildpackage -S |
Source package 上傳清單;dput 使用此檔上傳。 |
hello_<version>_source.buildinfo |
dpkg-buildpackage -S |
Source package 的建置環境資訊。 |
hello_<version>_amd64.deb |
sbuild |
本機建出的可安裝套件。 |
hello-dbgsym_<version>_amd64.ddeb |
sbuild |
除錯符號套件,通常只有除錯時才需要。 |
hello_<version>_amd64.changes |
sbuild |
本機 binary build 產物清單;不要用它上傳 PPA。 |
hello_<version>_amd64.buildinfo |
sbuild |
Binary build 的建置環境資訊。 |
hello_<version>_amd64.build |
sbuild |
建置記錄;同名連結通常指向最近一次的 log。 |
清理產物
在原始碼目錄執行以下指令,可清除建置中間檔,但保留 debian/ 設定:
若要清除 ppa-work/ 中某個版本的打包產物,先進入該目錄,再使用精確的版本字串;以下只刪 Resolute 這個版本,會保留上游 tarball 和 hello-2.12.1/ 原始碼目錄: