本教程文件已被重寫為另外的 Debian 維護者指導 文件,其中包含了更新的內容與更多實際例子。請使用新的教程作為主要的教程文件。
請注意這裏沒有足夠的篇幅來描述修改上游原始碼的 全部 細節,但是這裏介紹了基本的步驟和常見的問題。
quilt 程序爲 Debian
打包工作提供了記錄上游源碼修改的基本方法。對默認配置加以少許修改往往非常有用,所以我們來創建一個別名
dquilt,以用於打包: 添加以下幾行內容到 ~/.bashrc
文件中。其中第二行可以給 dquilt 命令提供與 quilt 命令相同的
shell 補全特性:
alias dquilt="quilt --quiltrc=${HOME}/.quiltrc-dpkg"
. /usr/share/bash-completion/completions/quilt
complete -F _quilt_completion -o filenames dquilt
現在按下面的方法來創建 ~/.quiltrc-dpkg 文件:
d=. ; while [ ! -d $d/debian -a $(readlink -e $d) != / ]; do d=$d/..; done
if [ -d $d/debian ] && [ -z $QUILT_PATCHES ]; then
# if in Debian packaging tree with unset $QUILT_PATCHES
QUILT_PATCHES="debian/patches"
QUILT_PATCH_OPTS="--reject-format=unified"
QUILT_DIFF_ARGS="-p ab --no-timestamps --no-index --color=auto"
QUILT_REFRESH_ARGS="-p ab --no-timestamps --no-index"
QUILT_COLORS="diff_hdr=1;32:diff_add=1;34:diff_rem=1;31:diff_hunk=1;33:diff_ctx=35:diff_cctx=33"
if ! [ -d $d/debian/patches ]; then mkdir $d/debian/patches; fi
fi
參見 quilt(1) 以及 /usr/share/doc/quilt/quilt.pdf.gz
來獲取有關 quilt 命令用法的信息。
假設你在上游的 Makefile 檔案中找到了一個錯誤,其中的 install:
gentoo 應該修正為 install: gentoo-target 。
install: gentoo
install ./gentoo $(BIN)
install icons/* $(ICONS)
install gentoorc-example $(HOME)/.gentoorc
讓我們使用 dquilt 修復這個問題,並把補丁命名爲
fix-gentoo-target.patch。[22]
$ mkdir debian/patches $ dquilt new fix-gentoo-target.patch $ dquilt add Makefile
現在將 Makefile 修改爲如下的樣子:
install: gentoo-target
install ./gentoo $(BIN)
install icons/* $(ICONS)
install gentoorc-example $(HOME)/.gentoorc
使用 dquilt 將補丁生成到
debian/patches/fix-gentoo-targe.patch 並根據 DEP-3: Patch Tagging Guidelines 添加描述:
$ dquilt refresh $ dquilt header -e ... 描述補丁
大多數第三方程序將其本身安裝在 /usr/local 目錄下。在 Debian
中,這是保留給系統管理員的私有位置,因此 Debian 軟件包不可以使用比如/usr/local/bin
這樣的目錄,而應當使用系統目錄比如 /usr/bin, 以遵循文件系統層級結構標準: Filesystem Hierarchy Standard (FHS)。
通常在自動編譯程序時使用 make(1) 程序,接着執行 make
install 就可以把程序直接按照 Makefile 文件中的
install target 安裝到指定的位置。爲了使 Debian
能夠提供編譯好的二進制軟件包,編譯系統將文件安裝到一個臨時目錄中創建的文件系統樹的鏡像中,而非直接安裝到實際的目標位置。
普通程序安裝過程和 Debian 打包安裝過程二者的區別可以由 debhelper 軟件包中的
dh_auto_configure 和 dh_auto_install
透明地處理。但必須滿足以下條件:
Makefile 文件應當遵循 GNU 的規定支持 $(DESTDIR)
變量[23]
源代碼必須遵循文件系統層級標準(FHS)。
使用 GNU autoconf 的程序自動遵守了GNU
的規定,這多少有利於打包過程的自動化。通過這項特點和其他啓發式處理,估計 debhelper 軟件可以直接打包約 90%
的軟件包而不需對編譯系統做出大的改變。所以打包也不是看起來那樣複雜。
如果你需要修改 Makefile 文件,就要確保其支持
$(DESTDIR) 變量。雖然默認情況下 $(DESTDIR)
變量沒有設置並且在程序安裝時會前置到每個文件的路徑中。打包腳本會將 $(DESTDIR) 設置爲臨時目錄。
對於從源碼包生成單個二進制包, dh_auto_install 將臨時目錄設置爲
debian/。[24] 臨時目錄中的全部文件都將在安裝軟件包時被安裝到用戶系統,唯一的區別是
dpkg 會把文件安裝到真實的根目錄樹中,而不是你的工作目錄。
package
請記住,即使你的程序正確安裝到了debian/,仍然要考慮將
package.deb 軟件包文件安裝到根目錄下的情形。所以絕對不允許構建系統將諸如
/home/me/deb/
這種詭異的內容硬編碼到軟件包文件中。
package-version/usr/share/package
以下是 gentoo 軟件包的
Makefile 文件中的相關部分[25]:
# Where to put executable commands on 'make install'? BIN = /usr/local/bin # Where to put icons on 'make install'? ICONS = /usr/local/share/gentoo
可以看到檔案被放到了 /usr/local 下。按照上邊的解釋,該目錄被 Debian
保留作本地用途,所以請把它們按如下方式修改:
# Where to put executable commands on 'make install'? BIN = $(DESTDIR)/usr/bin # Where to put icons on 'make install'? ICONS = $(DESTDIR)/usr/share/gentoo
二進制文件、圖標和文檔等的更確切位置均已在文件層級標準(FHS)中作出了詳盡描述。本教程建議你快速瀏覽相關章節以獲取你打包需要用到的內容。
因此,我們應當把可執行二進制文件安裝到 /usr/bin 而非
/usr/local/bin,而 man 手冊頁則應放在
/usr/share/man/man1 而非
/usr/local/man/man1,依此類推。注意,gentoo 的 Makefile
裏沒有提及手冊頁,而按照 Debian Policy 的要求,每個程序都應當有一個手冊頁,我們將在稍後製作一個並安裝到
/usr/share/man/man1。
有些程式不使用 Makefile 變量定義路徑,這意味着你可能需要去編輯 C
程式原始碼來使他們使用正確的路徑。但是到哪裏去搜索,哪些纔是呢?你可以通過以下的方法找到它們:
$ grep -nr --include='*.[c|h]' -e 'usr/local/lib' .
grep 會遞歸搜索整個原始碼樹並告訴你所有匹配項的檔案名和行號。
編輯那些文件,在那些行中用 usr/lib 替換
usr/local/lib。這個過程可以用如下方法自動化完成:
$ sed -i -e 's#usr/local/lib#usr/lib#g' \
$(find . -type f -name '*.[c|h]')
如果你想要確認每一個替換操作,那麼下邊的方法可以讓你交互式地達成:
$ vim '+argdo %s#usr/local/lib#usr/lib#gce|update' +q \
$(find . -type f -name '*.[c|h]')
緊接着你應該找到 install target (通常搜索以
install: 開頭的行即可),並把除 Makefile
頂部定義變量之外的目錄引用妥當修改。
原始的 gentoo 的
install target 是這樣:
install: gentoo-target
install ./gentoo $(BIN)
install icons/* $(ICONS)
install gentoorc-example $(HOME)/.gentoorc
讓我們來修復這個上游BUG,並把修改使用 dquilt
命令記錄到debian/patches/install.patch。
$ dquilt new install.patch $ dquilt add Makefile
使用你喜歡的編輯器按照以下內容爲 Debian 軟件包作修改:
install: gentoo-target
install -d $(BIN) $(ICONS) $(DESTDIR)/etc
install ./gentoo $(BIN)
install -m644 icons/* $(ICONS)
install -m644 gentoorc-example $(DESTDIR)/etc/gentoorc
你一定會注意到規則裏在其他命令前有了一個 install -d 命令。原始的
Makefile 文件中沒有它,因爲通常情況下當你執行 make
install 命令時, /usr/local/bin
和用到的其他目錄早已存在於系統中。然而當我們要向新建的私有目錄樹中安裝時,我們必須創建其中的每一個目錄。
我們還可以在末尾添加上其他的內容,比如上游作者有時會省略的附加文件:
install -d $(DESTDIR)/usr/share/doc/gentoo/html
cp -a docs/* $(DESTDIR)/usr/share/doc/gentoo/html
仔細檢查後如果沒有問題,使用 dquilt 創建
debian/patches/install.patch 補丁文件並添加對它的描述:
$ dquilt refresh $ dquilt header -e ... 描述補丁
現在你有了一格系列的補丁。
修復上游 Bug:debian/patches/fix-gentoo-target.patch
Debian 特有的打包修改:debian/patches/install.patch
當進行任何非 Debian 特有的修改時,比如
debian/patches/fix-gentoo-target.patch,一定要向上遊作者進行反饋,以便上游作者方便在下一版本中以使更多人受益。同時請記住不要做出特別針對
Debian 或 Linux (甚至是 Unix!)的修改,要使其可以移植,這會使你的修改更容易被接受。
注意你不一定要把 debian/* 都提交到上游。
還有另外一個常見的問題:不同平臺之間的庫名稱常常因平臺而異。例如一個 Makefile 中可能引了用一個
Debian 系統中不存在的庫。這種情況下我們需要將其修改為 Debian 中存在的、提供完全相同功能的庫。
如果你手中程序的 Makefile(或
Makefile.in)中有如下的行。
LIBS = -lfoo -lbar
如果你的程序由於 foo 庫不存在,而 Debian 系統中的 foo2
庫提供了其等效,那麼你可以修復這個構建問題並將修改記錄到 debian/patches/foo2.patch
中,只需要將 foo 切換到 foo2:[26]
$ dquilt new foo2.patch $ dquilt add Makefile $ sed -i -e 's/-lfoo/-lfoo2/g' Makefile $ quilt refresh $ quilt header -e ... 描述補丁
[22] debian/patches 目錄應當是在你按照前面所述的步驟運行
dh_make 時生成的。而在這個例子中我們新創建它,因爲假設的是在更新一個已存在的軟件包。
[24] 對於單個源碼包生成多個二進制包,dh_auto_install
將臨時目錄設置爲debian/tmp,而 dh_install
命令則將文件按照
debian/ 和
package-1.installdebian/
等文件的描述將 package-2.installdebian/tmp 中的文件分別裝入
debian/ 和
package-1debian/ 等臨時目錄用以創建
package-2 和
package-1_*.deb 等二進制軟件包。
package-2_*.deb
[25] 這只是一個演示 Makefile 正常形態的例子。如果
Makefile 是通過 ./configure
命令生成的,那麼修復該類 Makefile 的方法是通過
dh_auto_configure 來執行
./configure,並帶上包括 --prefix=/usr 的默認選項。
[26] 如果從 foo 庫切換到 foo2
庫時要更改應用程序接口(API),這就要求我們修改源代碼來符合新的 API。