這裏有一些關於你可能遇到的高級打包問題的提示。如果有需要的話,本教程強烈建議閱讀這裏引用和建議的文檔。
你可能需要手工編輯由 dh_make 命令生成的打包模板文件,以此來解決本章中所討論的問題。 新的 debmake 命令應該能更好地解決這些問題。
在打包 共享庫 之前,你 應該閱讀以下的主要參考資料:
以下是幫助你開始的極簡解釋:
共享庫均爲 elf 對象文件,其包含編譯好的機器碼。
共享庫以 *.so
文件的形式發放。(既非 *.a
文件也非
*.la
文件)
共享庫主要用於在不同的二進制可執行程序之間共享代碼,這背後使用了 ld (譯註:鏈接)機制。
共享庫有時會爲一個可執行程序提供多個插件,這背後使用了 dlopen 機制。
共享庫能導出代表着變量,函數和類的 symbols (符號); 並讓鏈接到它的可執行文件訪問。
共享庫
lib
.foo
.so1
中的 SONAME : objdump -p
lib
[88]
foo
.so.1
| grep
SONAME
共享庫的 SONAME 常常與庫文件自身文件名一致(不過有特例)。
鏈接到
的共享庫的
SONAME : /usr/bin/foo
objdump -p
[89]
/usr/bin/foo
| grep
NEEDED
lib
:
共享庫
foo
1
lib
的庫文件包,其 SONAME ABI 版本爲 foo
.so.1
1
.[90]
在某些情況下,庫軟件包的 maintainer scripts 必須調用 ldconfig 來爲 SONAME 創建 必要的符號鏈接。[91]
lib
:
包含了調試共享庫包用的調試符號的軟件包 foo
1
-dbglib
.
foo
1
lib
:
包含了頭文件等內容的開發包。用於
foo
-devlib
.[92]
foo
.so.1
一般而言,Debian 軟件包不應當包含 *.la
Libtool 歸檔文件。 [93]
一般來說,Debian 軟件包不應當使用 RPATH 。[94]
雖然這有點過時,而且是第二參考, Debian Library Packaging Guide 可能仍然對你有用。
當你給共享庫打包時,你應當創建
debian/
文件來管理
在共享庫名稱不變,在同一個 SONAME 下又要提供 ABI 向後兼容,的情況下每個符號關聯到的最小版本。 [95] 你可以閱讀下邊的主要參考以獲知細節:
package
.symbols
dh_makeshlibs(1)
dpkg-gensymbols(1)
dpkg-shlibdeps(1)
deb-symbols(5)
這是個粗略的例子來演示創建 libfoo1
軟件包,對應上游版本
1.3
,並有着妥當的debian/libfoo1.symbols
文件:
使用上游提供的 libfoo-1.3.tar.gz
文件來準備 Debian化 的源碼骨架。
如果這是庫軟件包 libfoo1
的第一次打包,那麼以空內容創建
debian/libfoo1.symbols
文件。
如果之前的上游版本 1.2
已經被 libfoo1
軟件包打包了,並且其源碼包中有妥當的
debian/libfoo1.symbols
, 再用它一次。
如果前一個上有版本 1.2
打包時沒有
debian/libfoo1.symbols
,那就從具有相同庫 SONAME
的同一個共享庫包的所有可用的二進制軟件包中創建它到 symbols
文件。比如
1.1-1
和 1.2-1
。 [97]
$ dpkg-deb -x libfoo1_1.1-1.deb libfoo1_1.1-1 $ dpkg-deb -x libfoo1_1.2-1.deb libfoo1_1.2-1 $ : > symbols $ dpkg-gensymbols -v1.1 -plibfoo1 -Plibfoo1_1.1-1 -Osymbols $ dpkg-gensymbols -v1.2 -plibfoo1 -Plibfoo1_1.2-1 -Osymbols
嘗試用像 debuild 和 pdebuild
這樣的工具來對源碼樹進行試構建。 (如果這因爲缺失符號之類原因而失敗,那麼這裏就有一些不向後兼容的 ABI
改變,這就需要你轉移(bump)共享庫的名稱到諸如 libfoo1a
,並重新開始一次。
$ cd libfoo-1.3 $ debuild ... dpkg-gensymbols: warning: some new symbols appeared in the symbols file: ... see diff output below --- debian/libfoo1.symbols (libfoo1_1.3-1_amd64) +++ dpkg-gensymbolsFE5gzx 2012-11-11 02:24:53.609667389 +0900 @@ -127,6 +127,7 @@ foo_get_name@Base 1.1 foo_get_longname@Base 1.2 foo_get_type@Base 1.1 + foo_get_longtype@Base 1.3-1 foo_get_symbol@Base 1.1 foo_get_rank@Base 1.1 foo_new@Base 1.1 ...
如果你如上述看見由 dpkg-gensymbols 命令打印出來的差異, 那就從生成的二進制庫包中抽取妥當更新的
symbols
文件。 [98]
$ cd .. $ dpkg-deb -R libfoo1_1.3_amd64.deb libfoo1-tmp $ sed -e 's/1\.3-1/1\.3/' libfoo1-tmp/DEBIAN/symbols \ >libfoo-1.3/debian/libfoo1.symbols
使用像 debuild 和 pdebuild 這樣的工具來構建發行軟件包。
$ cd libfoo-1.3 $ debuild clean $ debuild ...
對上邊這個例子補充一點,我們需要進一步檢查 ABI (應用程序二進制接口) 兼容性 並在需要的時候手動更新一些符號的版本。 [99]
雖然這只是第二參考, Debian wiki UsingSymbolsFiles 和它指向的頁面可能會有所幫助。
Debian wheezy 引入的多體繫結構特性,集成了對 二進制包跨體繫結構安裝的支持 (尤其是
i386
<->amd64
,其他的組合也有) 於
dpkg
和 apt
中。你可以閱讀下邊的參考:
Debian wiki Multiarch/Implementation (Debian 的局勢)
它爲每個共享庫的安裝路徑使用了類似 i386-linux-gnu
和
x86_64-linux-gnu
這樣的三元名字。實際上每個二進制軟件包構建的三元路徑是被動態設置到
$(DEB_HOST_MULTIARCH)
變量中的,經由 dpkg-architecture(1)
命令。舉個例子, 安裝多體繫結構庫文件的路徑被按照下表進行了修改:[100]
舊路徑 | i386 多體繫結構路徑 | amd64 多體繫結構路徑 |
---|---|---|
/lib/
|
/lib/i386-linux-gnu/
|
/lib/x86_64-linux-gnu/
|
/usr/lib/
|
/usr/lib/i386-linux-gnu/
|
/usr/lib/x86_64-linux-gnu/
|
下面是一些典型的多體繫結構軟件包分離情景:
庫源碼 lib
foo
-1.tar.gz
一個用編譯型語言編寫的工具的源碼
bar
-1.tar.gz
一個用解釋型語言編寫的工具的源碼
bar
-1.tar.gz
軟件包 | 體繫結構: | 多體繫結構: | 軟件包內容 |
---|---|---|---|
lib
|
任何 | 相同 | 共享庫,可共同安裝 |
lib
|
任何 | 相同 | 共享庫調試符號,可共同安裝 |
lib
|
任何 | 相同 | 共享庫頭文件之類,可共同安裝 |
lib
|
任何 | 外來 | 運行時支持程序,不可共同安裝 |
lib
|
全部 | 外來 | 共享庫文檔 |
|
任何 | 外來 | 編譯好的程序文件,不可共同安裝 |
|
全部 | 外來 | 程序的配套文檔文件 |
|
全部 | 外來 | 解釋型程序文件 |
請注意,開發軟件包應該包含一個指向共享庫的符號鏈接並且 不帶有版本號。 比如:
/usr/lib/x86_64-linux-gnu/libfoo.so
->
libfoo.so.1
你可以用 dh(1) 通過以下方法構建一個支持多體繫結構的 Debian 庫軟件包:
更新 debian/control
。
爲源碼包部分添加 Build-Depends: debhelper (>=9)
部分。
爲每個二進制庫軟件包添加 Pre-Depends: ${misc:Pre-Depends}
。
在每個二進制包的段中添加 Multi-Arch:
小節。
設置 debian/compat
爲"9"。
將所有打包腳本中的路徑從普通的 /usr/lib/
調整到 多體繫結構的
/usr/lib/$(DEB_HOST_MULTIARCH)/
。
首先,在 debian/rules
中調用 DEB_HOST_MULTIARCH ?=
$(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
以設置
DEB_HOST_MULTIARCH
變量。
在 debian/rules
中用
/usr/lib/$(DEB_HOST_MULTIARCH)/
替換
/usr/lib/
。
如果 debian/rules
文件中的
override_dh_auto_configure
target 使用了
./configure
文件,那麼請確認用 dh_auto_configure --
來替換它。 [101]
在debian/
文件中將所有
foo
.install/usr/lib/
的事件替換爲 /usr/lib/*/
。
欲從 debian/
動態地生成像 foo
.links.indebian/
這樣的文件,可以添加一個腳本到 foo
.linksdebian/rules
文件的
override_dh_auto_configure
target 中。
override_dh_auto_configure: dh_auto_configure sed 's/@DEB_HOST_MULTIARCH@/$(DEB_HOST_MULTIARCH)/g' \ debian/foo
.links.in > debian/foo
.links
請確認該共享庫軟件包僅僅包含預期中的文件,並且你的 -dev 軟件包還奏效。
所有作爲多體繫結構軟件包而同時安裝到同一個文件路徑的所有文件應當具有完全一致的文件內容。你必須小心由 數據字節序 和 壓縮算法 造成的區別。
如果一個軟件包是僅僅爲 Debian 維護的,或者是可能的本地使用,那麼它的源碼可以容納所有的
debian/*
於其中。這裏有它的兩種打包方式。
你可以將除 debian/*
文件之外的部分製作成上游 tarball,然後將其作爲非本土 Debian
軟件包來打包,正如 節 2.1, “Debian 軟件包構建流程” 所述。 這是一些人鼓勵使用的普通方法。
另一種方法就是本土 Debian 軟件包的打包工作流。
用包含所有文件的,單一壓縮過的 tar 文件,以 3.0 (native)
格式來創建本土 Debian 源碼包。
package
_version
.tar.gz
package
_version
.dsc
用 Debian 本土源碼包構建二進制包
package
_version
_arch
.deb
比如說,如果你的源代碼文件都存放在 ~/mypackage-1.0
中,而且沒有
debian/*
文件,那麼你可以用它創建 一個本土 Debian 軟件包,只要按照下邊的方法使用
dh_make 命令:
$ cd ~/mypackage-1.0 $ dh_make --native
接下來 debian
目錄和它的內容都會被創建, 正如 節 2.8, “初始化外來 Debian 軟件包” 中那樣。 這不會創建一個 tarball,因爲這是個本土 Debian
軟件包。不過這也是唯一的區別。 剩下的打包操作就是完全一致的了。
在執行了 dpkg-buildpackage 命令後,你將會在上一級目錄中看到這些文件:
mypackage_1.0.tar.gz
這是 dpkg-source 命令用 mypackage-1.0
目錄創建出來的源代碼 tarball 。 (它的 文件名後綴不是 orig.tar.gz
)
mypackage_1.0.dsc
這是對源碼內容的簡述,正如在非本土 Debian 軟件包中那樣。(沒有 Debian 修訂)
mypackage_1.0_i386.deb
這是完成的二進制包,正如在非本土 Debian 軟件包中那樣。(沒有 Debian 修訂)
mypackage_1.0_i386.changes
這個文件描述了這個軟件作爲外來 Debian 包,在當前版本所作出的所有更改。(沒有 Debian 修訂)
[88]
或者這樣: readelf -d
lib
foo
.so.1
| grep
SONAME
[89]
或者這樣: readelf -d
lib
foo
.so.1
| grep
NEEDED
[92] 參見 Debian Policy Manual, 8.3 "Static libraries" and Debian Policy Manual, 8.4 "Development files".
[95] 向後不兼容的 ABI 變更常常需要你更新共享庫的 SONAME,並把共享庫名稱換成新的。
[96] 對於 C++ 庫和其他追蹤單個符號過於困難的情況下,請遵循 Debian Policy Manual, 8.6.4 "The shlibs system"。
[97]
所有先前的 Debian 軟件包版本都能在 http://snapshot.debian.org/ 找到。不過 Debian 修訂號
被去掉了,以使軟件包的 backport 更爲容易: 1.1
<<
1.1-1~bpo70+1
<< 1.1-1
and
1.2
<< 1.2-1~bpo70+1
<<
1.2-1
[98]
Debian 修訂號已被從版本中去掉,這能讓軟件包的 backport 更爲容易: 1.3
<<
1.3-1~bpo70+1
<< 1.3-1
[100] 老舊且具有特殊用途的庫路徑,比如 /lib32/
和 /lib64/
不再被使用。
[101]
作爲替代,你可以添加 --libdir=\$${prefix}/lib/$(DEB_HOST_MULTIARCH)
和 --libexecdir=\$${prefix}/lib/$(DEB_HOST_MULTIARCH)
參數到
./configure
後頭。 請注意 --libexecdir
指定了
安裝可執行程序(它們被其他程序使用,而更少是用戶)的默認路徑。它的 Autotools 默認設置爲
/usr/libexec/
但是 Debian 的設置爲
/usr/lib/
。