Debian 打包介紹
本文是一個關於如何制作 Debian 包的介紹性教程,它不會對 Debian 打包系統中的復雜概念深入介紹,但它介紹了能夠為簡單軟件制作 Debian 包的方法。
出於這個目的,我們只使用來自於 debhelper 9
的 dh
命令。
需求
這個教程假設您已:
- 理解二進制包的安裝過程;
- 了解命令行的使用,並且使用您偏愛的文本編輯器編輯文本文件;
技術要求:
- build-essential
- devscripts
- debhelper version 9 或更高版本
三個核心概念
三個最核心的概念為:
- 上游原始代碼包(upstream tarball):
通常,人們為上游開發者(通常為第三方)編寫的軟件打包。
上游開發者會使用源代碼歸檔軟件或原始代碼包的方式發放他們的軟件。
原始代碼包一般是上游制作的 .tar.gz 或 .tgz 文件,它也可能被壓縮成 .tar.bz2,.tb2 或 .tar.xz 格式。原始代碼包就是 Debian 構建包時使用的原材料。 - 源碼包:
當您擁有了上游制作的原始代碼包,下一步就可以制作 Debian 源碼包了。 - 二進制包:
從源碼包您可以構建 Debian 二進制包,它才是是實際上會被安裝的包。
最簡單的源碼包由3個文件組成:
- 上游原始代碼包,需要被重命名來符合一個特定的模式。
- 一個 debian 目錄,帶有所有上游源代碼的更改記錄,外加所有為 Debian 打包系統生成的所有文件。這種包擁有 .debian.tar.gz 的文件名。
- 一個描述文件(以 .dsc 結尾),羅列了其他兩個文件。
聽起來有些過於復雜,人們的第一印象是:所有東西都放在一個文件里會更簡單。然而,保持上游代碼包與 Debian 特定更改分離可以節省大量磁盤空間和帶寬。對 Debian 來說,追蹤必要的修改也更加簡單。
打包工作流
打包工作流通常如下表所示:
- 重命名上游代碼包
- 解壓縮上游代碼包
- 添加 Debian 打包文件
- 構建這個包
- 安裝這個包
之后您就可以在您的電腦上測試它了。
源碼包和二進制包都可以被上傳到 Debian。
為了這個教程,我們使用這個代碼包:hithere
第一步:更改上游代碼包名稱
Debian 打包系統假定上游代碼包擁有一個十分特殊的名字,必須遵守一個特定的模式。它的名字由源代碼包名、一個下划線、上游版本號組成,最后以.orig.tar.gz 組成。源代碼包應當全部使用小寫字母,並且包含字母、數字、符號,一些其他的字符也可以出現。
如果上游開發者使用了一個很好的 Debian 源代碼包名,您可以直接使用。否則,請盡可能小的對名稱進行改動以適應 Debian。在我們的情況下,上游開發者已經選取了一個很好的名字:“hithere”了,所以我們無需擔心。我們應當最終使用 hithere_1.0.orig.tar.gz 作為上游代碼包的名稱。請注意,這里我們使用了一個下划線,而不是“-”,因為打包工具極其吹毛求疵。
mv hithere-1.0.tar.gz hithere_1.0.orig.tar.gz
第二步:解壓縮上游代碼包
通常情況下,源代碼會進入一個以包名和上游版本號命名的目錄中(使用連接符連接,而不是下划線),因此理想狀況下我們使用的上游代碼包會被解壓縮到一個叫做hithere-1.0 的目錄中。打包工具仍舊挑剔,因此我們必須這樣做。
tar xf hithere_1.0.orig.tar.gz
第三步:添加 Debian 打包文件
以下所有文件都在源碼樹的 debian/ 子目錄中。
cd hithere-1.0
mkdir debian
我們需要提供不少文件,讓我們按順序來看。
debian/changelog
第一個文件是 debian/changelog,這個是記錄 Debian 包變化的日志文件。它無需羅列出上游代碼的每一個改變,只要它能幫助用戶總結這些變化即可。我們在制作第一個版本,所以這里應當什么都沒有。然而,我們仍需制作一個變化日志的入口,因為打包工具會從日志里讀取特定信息。最重要的是它會讀取包的版本。
debian/changelog 擁有一個十分特殊的格式。最簡單的創建方式就是使用 dch 工具。
dch --create -v 1.0-1 --package hithere
會在文件中產生以下內容:
hithere (1.0-1) UNRELEASED; urgency=low
* Initial release. (Closes: #XXXXXX)
-- Lars Wirzenius <liw@liw.fi> Thu, 18 Nov 2010 17:25:32 +0000
這里有很多注意點:
hithere 部分必須與源代碼包的名字相同。1.0-1 是版本號,1.0 部分是上游版本號。-1 部分是 Debian 的版本:它是第一個上游版本為 1.0 的 Debian 包。如果這個 Debian 包有錯誤,並且被修復了,那么上游版本號仍保持相同,下一個版本應當被叫做 1.0-2,接下來是 1.0-3,依此類推。
UNRELEASED 被稱作上傳目標。它會告訴上傳工具這個二進制包應當被上傳到哪里。UNRELEASED 意味着這個包還沒有做好上傳的准備。保持 UNRELEASED 是一個好主意,以避免您錯誤上傳它。
目前請先忽略 urgency=low。
(Closes:#XXXXXX) 作用在於上傳包時關閉錯誤。這是在 Debian 中關閉錯誤的常用方法:當上傳修復錯誤的包時,錯誤跟蹤器會注意到這一點,並將錯誤標記為已關閉。我們可以刪除 (Closes...) 位。或者不管它,現在它不重要。
更改日志中的最后一行指出是誰在何時制作了這個版本的軟件包。dch 工具會嘗試猜測名稱和電子郵件地址,但您應當使用正確的詳細信息對其進行配置。詳細信息,請參閱 dch(1) 手冊頁。
debian/compat
debian/compat 明確 debhelper 工具的兼容等級。我們目前不需要知道它意味着什么。
10
debian/control
控制文件描述代碼和二進制包,並給出他們的詳細信息,比如名稱、包的維護者是誰,等等。下面是一個示例:
Source: hithere
Maintainer: Lars Wirzenius <liw@liw.fi>
Section: misc
Priority: optional
Standards-Version: 3.9.2
Build-Depends: debhelper (>= 9)
Package: hithere
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: greet user
hithere greets the user, or the world.
在這個文件里有許多需求的字段,但是現在您可以像對待魔法一樣對待它。那么,在 debian/control 中有兩段文字。
第一段文字描述了源代碼包,使用以下字段:
Source
源代碼包名。
Maintainer
維護者的姓名和電子郵箱。
Priority
包的重要性(‘required 可選的’, ‘important 重要的’, ‘standard 標准’ 或 ‘optional’ 其中之一)。通常,包是“可選”的,除非它對於標准系統功能是“必不可少的”,即啟動或網絡功能。 如果包與另一個“可選”包沖突,或者它不打算用於標准桌面安裝,則應該是“額外”的而不是“可選”的。 “額外”包的顯着例子是調試包。 (由Sebastian Tennant添加)。
Build-Depends
需要安裝以構建程序包的程序包列表。實際使用包時有可能需要它們。
第一個之后的所有段落都描述了從此源構建的二進制包。 可以有許多從同一來源構建的二進制包; 但對於我們的例子只有一個。 我們使用這些字段:
Package
二進制包的名稱。 名稱可能與源包名稱不同。
Architecture
指定二進制包預期使用的計算機體系結構:用於32位Intel CPU的i386,用於64位的amd64,用於ARM處理器的armel等等。 Debian總共可以處理大約十幾種計算機體系結構,因此這種體系結構支持至關重要。 “Architecture”字段可以包含特定體系結構的名稱,但通常它包含兩個特殊值中的一個。
any
(我們在示例中看到)意味着可以為任何體系結構構建包。 換句話說,代碼是可移植的,因此它不會對硬件做太多假設。 但是,仍然需要為每個體系結構單獨構建二進制包。
all
意味着相同的二進制包將適用於所有體系結構,而無需為每個體系結構單獨構建。 例如,僅包含shell腳本的包將是“all”。 Shell腳本在任何地方都可以工作,不需要編譯。
Depends
為了讓二進制包中程序能夠正常運行,需要安裝的包列表。手動列出這些依賴項是繁瑣且容易出錯的工作。為了能夠讓其工作,我們需要一個神奇的小東西 ${shlibs:Depends}。另一個神奇的東西是給 debhelper 的,它是 ${misc:Depends}。shlibs 是為了動態鏈接庫,而 misc 是為了 debherlper 的一些工作。對於別的依賴,您可以將其手動加入到 Depends 或 Build-Depends 中。但請注意,${...} 僅在 Depends 中有效。
Description
二進制包的完整描述。它希望對用戶有所幫助。第一行用作簡要概要(摘要)描述,其余部分是包的更長的描述。
命令 cme edit dpkg 提供了一個GUI能夠用來編輯大多數打包文件,包括 debian/control。 請參閱使用 cme 頁面管理 Debian 軟件包。cme命令在 Debian 中的 cme 包中提供。您也可以使用 cme edit dpkg-control 命令僅編輯 debian/control 文件。
debian/copyright
這是一個非常重要的文件,但是現在我們將先使用一個空文件。
對於 Debian ,此文件用於跟蹤有關包的合法性、版權相關信息。但是,從技術角度來看,這並不重要。目前,我們將專注於技術方面。如果有興趣,我們可以稍后再回到 debian/copyright。
debian/rules
它應當長這個樣:
#!/usr/bin/make -f
%:
dh $@
注意: 最后一行應當使用一個 Tab 字符進行縮進,而不使用空格。這個文件是一個 Makefile,因此 Tab 字符是 make 所期望的。
事實上 debian/rules 可能是一個相當復雜的文件。然而,在 debhelper 7 中的 dh 命令讓它可以在大多數情況下變得更簡單。
debian/source/format
最后一個我們需要的文件是 debian/source/format,它應當包含源代碼包的版本號,這里為 3.0 (quilt)。
3.0 (quilt)
debian/preinst, postinst, prerm, postrm
這些是軟件包安裝前后自動運行的可執行腳本. 統稱為控制文件, 是 Deian 軟件包的"控制"部分它們是:
preinst
Debian軟件包(".deb")解壓前執行的腳本, 為正在被升級的包停止相關服務,直到升級或安裝完成。 (成功后執行 'postinst' 腳本)。
postinst
主要完成軟件包(".deb")安裝完成后所需的配置工作. 通常, postinst 腳本要求用戶輸入, 和/或警告用戶如果接受默認值, 應該記得按要求返回重新配置這個軟件。 一個軟件包安裝或升級完成后,postinst 腳本驅動命令, 啟動或重起相應的服務。
prerm
停止一個軟件包的相關進程, 要卸載軟件包的相關文件前執行。
postrm
修改相關文件或連接, 和/或卸載軟件包所創建的文件。
當前的所有配置文件都可在 /var/lib/dpkg/info 目錄下找到, 與 foo 軟件包相關的命名以 "foo" 開頭,以 "preinst", "postinst", 等為擴展。這個目錄下的 foo.list 文件列出了軟件包安裝的所有文件。Debian里用apt-get安裝或卸載軟件時,會常發生前處理或后處理的錯誤,這時只要刪除 對應的腳本文件,重新執行安裝或卸載即可
第四步:構建這個包
第一次嘗試
現在我們可以構建這個包了。有很多我們可以使用的命令,但是我們只使用其中一個,如果您運行以下命令,您會得到像下面的輸出:
$ debuild -us -uc
make[1]: Entering directory '/home/liw/debian-packaging-tutorial/x/hithere-1.0'
install hithere /home/liw/debian-packaging-tutorial/x/hithere-1.0/debian/hithere/usr/local/bin
install: cannot create regular file '/home/liw/debian-packaging-tutorial/x/hithere-1.0/debian/hithere/usr/local/bin': No such file or directory
make[1]: *** [install] Error 1
make[1]: Leaving directory '/home/liw/debian-packaging-tutorial/x/hithere-1.0'
dh_auto_install: make -j1 install DESTDIR=/home/liw/debian-packaging-tutorial/x/hithere-1.0/debian/hithere returned exit code 2
make: *** [binary] Error 29
dpkg-buildpackage: error: fakeroot debian/rules binary gave error exit status 2
debuild: fatal error at line 1325:
dpkg-buildpackage -rfakeroot -D -us -uc failed
有些地方不太對勁。這經常發生:您已經盡力創建了符合規范的 debian/* 文件了,但是仍有一些東西不太對勁。可見,出錯的地方在:
install hithere /home/liw/debian-packaging-tutorial/x/hithere-1.0/debian/hithere/usr/local/bin
上游代碼中的 Makefile 嘗試將程序安裝到錯誤的地方。
這邊有許多可以做的事情,來解決這個問題:第一件事是 Debian 打包系統如何工作。
修正
當程序被構建並被“安裝”時,通常情況下,它還不會被安裝到 /usr 或者 /usr/local,而是被安裝到 debian/ 子目錄。
我們在 debian/hithere 目錄下創建了一個整個文件系統的子集,並將其打包進二進制包中。因此 .../debian/hithere/usr/local/bin 是沒問題的,除非它不應當被安裝到 usr/local 而是 usr 目錄。我們需要做一些事情來確保程序被安裝到正確的位置 debian/hithere/usr/bin。正確的方法是修改 debian/rules 文件來告訴 Makefile 應當在哪里安裝軟件。
#!/usr/bin/make -f
%:
dh $@
override_dh_auto_install:
$(MAKE) DESTDIR=$$(pwd)/debian/hithere prefix=/usr install
這個仍是一個小魔法,為了理解它,您應當知道 Makefile 如何工作,還應當知道 debhelper 的不同階段。
目前,我可以大概說明下:有一個名為 debherlper 的命令負責安裝上游文件,這個階段被稱為 dh_auto_install。我們需要覆蓋這個階段,為此,我們在 debian/rule 中重寫了 override_dh_auto_install 規則。這個文件的最后一行是一種1970年代的技術,為了從 debian/rules 中使用正確的參數調用上游中的 Makefile 文件。
讓我們再試一下。
debuild -us -uc
仍然失敗了!但這次失敗的命令是:
install hithere /home/liw/debian-packaging-tutorial/x/hithere-1.0/debian/hithere/usr/bin
我們正在嘗試將軟件安裝至正確的地方,但是這個目錄不存在。為了修正這個錯誤,我們應當告訴打包工具先創建這個目錄。
理想狀況下,上游 Makefile 文件會自動創建目錄,但這種情況下,是上游開發者太懶惰了,他沒有創建這個目錄。
另一個修正
打包工具(特別是debhelper)提供了一種實現方式。創建一個名為 debian/hithere.dirs 的文件,里面的內容應當是:
usr/bin
usr/share/man/man1
第二行創建了一個給手冊頁面的目錄。之后我們會需要它。您應當小心的維護這樣的文件,因為它可能會導致您的包在未來版本產生空目錄,當包中的項目不再有效時。
讓我們再試一下:
debuild -us -uc
現在構建成功了,但是仍有一些小問題。debuild 運行了 lintian 工具,這個工具可以檢測構建的包的一些常見的錯誤,它給出了我們創建的包的一些錯誤:
Now running lintian...
W: hithere source: out-of-date-standards-version 3.9.0 (current is 3.9.1)
W: hithere: copyright-without-copyright-notice
W: hithere: new-package-should-close-itp-bug
W: hithere: wrong-bug-number-in-closes l3:#XXXXXX
Finished running lintian.
這些錯誤應當被修正,但是對我們來說它們不會導致錯誤。現在我們先忽略他們。查看父目錄,您可以找到構建好的包。
$ ls ..
hithere-1.0 hithere_1.0-1_amd64.deb hithere_1.0.orig.tar.gz
hithere_1.0-1_amd64.build hithere_1.0-1.debian.tar.gz
hithere_1.0-1_amd64.changes hithere_1.0-1.dsc
第五步:安裝構建好的包
接下來的命令會安裝您構建好的包。不要在計算機上直接運行它,除非您不介意損壞系統。
通常情況下,在備份好的計算機上進行包開發是最好的,這樣,在所有事情變糟糕的情況下,您可以不用完全安裝整個系統。虛擬機是一個不錯的進行開發的地方。
$ sudo dpkg -i ../hithere_1.0-1_amd64.deb
[sudo] password for liw:
Selecting previously deselected package hithere.
(Reading database ... 154793 files and directories currently installed.)
Unpacking hithere (from ../hithere_1.0-1_amd64.deb) ...
Setting up hithere (1.0-1) ...
Processing triggers for man-db ...
liw@havelock$
那么,如何測試打好的包呢?我們可以運行命令:
hithere
OK 了!
但現在並不完美。記得 lintian 還有一些事情涵待解決,debian/copyright 仍然是空的,等等。我們現在有了一個可以運行的 deb 包了,但是它還並不是我們所期待的高質量的 Debian 包。
結論
一旦您構建了您自己的包,自然而然地,您會想要知道如何設置您自己的 apt 倉庫,這樣您自己的包會很容易被安裝。我所知道的最好的工具是 reprepro。為了更多的測試您的包,您可能也會想要了解 piuparts。原作者編寫的這個工具,他覺得這個工具很棒並且沒有任何 bug !
最后,如果您開始修改上游代碼,您可能想要了解一下 quilt 工具。
其他您可能想要閱讀的信息可以在 http://www.debian.org/devel/ 頁面找到。
參考鏈接:
https://blog.csdn.net/Veyx_shaw/article/details/105649548