本教程文件已被重寫為另外的 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-1
debian/
等臨時目錄用以創建
package-2
和
package-1
_*.deb
等二進制軟件包。
package-2
_*.deb
[25] 這只是一個演示 Makefile
正常形態的例子。如果
Makefile
是通過 ./configure
命令生成的,那麼修復該類 Makefile
的方法是通過
dh_auto_configure 來執行
./configure,並帶上包括 --prefix=/usr
的默認選項。
[26] 如果從 foo
庫切換到 foo2
庫時要更改應用程序接口(API),這就要求我們修改源代碼來符合新的 API。