章 5. `debian` 目錄下的其他檔案

# 章 5. `debian` 目錄下的其他檔案

The dh_make command had major updates since this old document was written. So some parts of this document aren't applicable any more.

本教程文件已被重寫為另外的 Debian 維護者指導 文件，其中包含了更新的內容與更多實際例子。請使用新的教程作為主要的教程文件。

The debmake command is used in place of the dh_make command in my new Guide for Debian Maintainers.

要控制 `debhelper` 在構建軟件包過程中的大部分行爲，可以在 `debian` 目錄中放置可選的配置文件。本章將會對這些文件和它們的格式進行概述。請閱讀 Debian Policy Manual 和 Debian Developer's Reference 來瞭解更多關於打包方針的內容。

The dh_make command will create some template configuration files under the `debian` directory. Take a look at all of them.

在本章節中， 只要不產生歧義，所有提及的 `debian` 目錄下的文件均會省去 `debian/` 前綴以求簡潔方便。

還有一些 `debhelper` 的配置文件模板可能未被 dh_make 命令創建。在這種情況下如果你需要它們，則要使用文本編輯器手工創建。

如果你希望或需要激活它們中的任意一個或多個，請按照下面的方法做：

- 把配置文件的名稱改爲實際的二進制軟件包名，例如 ``package``;

- 修改模板文件來滿足你的需要;

- 刪除不需要的模板文件;

- 如果需要，修改 `control` 文件(參看 節 4.1, “`control`”)。

- 如果需要，修改 `rules` 檔案(參考 節 4.4, “`rules`”)。

任何不帶有 ``package`` 前綴的`debhelper` 配置文件， 比如應用到第一個二進制包的 `install`。 當此處有多個二進制包時，可以通過在文件名中前置 它們各自的名稱來指定它們各自的配置文件，比如``package-1`.install`, ``package-2`.install`, 之類。

## 5.1. `README.Debian`

所有關於你的 Debian 版本與原始版本間的額外訊息或差別都應在這裏記錄。

dh_make 創建了一個默認的文件，以下是它的樣子：

    gentoo for Debian
    -----------------
    <possible notes regarding this package - if none, delete this file>
     -- Josip Rodin <joy-mg@debian.org>, Wed, 11 Nov 1998 21:02:14 +0100

如果你沒有需要寫在這裏的東西，則刪除這個檔案。參考 dh_installdocs(1)

## 5.2. `compat`

`compat` 檔案定義了 `debhelper` 的相容級別。目前你應當使用如下方法將其設定為 `debhelper` V10：

    $ echo 10 > debian/compat

在特定場景下，你可以在需要相容舊版本系統時使用相容等級9。然而，我們不建議你使用任何低於 9 的相容等級，在新建軟體包時也應避免使用這些低的等級。

## 5.3. `conffiles`

關於軟件有件很惱人的事，就是當你付出了很多時間和精力來自定義一個程序，但是升級後所有的修改都被覆蓋掉了。Debian 通過將配置文件單獨標記來解決這個問題， [54] 當軟件包升級的時候，你將會被詢問是否要保留你的舊配置文件。

dh_installdeb(1) automatically 會把 `/etc` 目錄下的任何文件都標記爲 conffiles，所以如果你的程序在那只有 conffiles 的話就不需要再在這個文件中指定它們。 對於大多數軟件包類型，唯一合理的 conffiles 文件存放位置自始至終應當在 `/etc` 目錄下， 正因如此，該文件也沒有存在的必要。

如果你的程序使用配置文件，但程序會自動對配置文件進行改寫，則最好別將其標記爲 conffiles ，因爲 dpkg 總是會要求用戶校驗變更。

如果你正在打包的程序需要所有用戶都爲自己修改 `/etc` 目錄中的配置文件，那麼有兩種常見的方法讓 dpkg 不將其記錄爲 conffiles，以使其沉默。

- 在 `/etc` 目錄中創建指向 `/var` 中維護者腳本(maintainer scripts)生成的文件的符號鏈接。

- 用維護者腳本(maintainer scripts)在 `/etc` 目錄中生成一個文件。

更多關於維護者腳本(maintainer scripts)的信息，參看 節 5.18, “`{pre,post}{inst,rm}`”

## 5.4. ``package`.cron.*`

如果你的軟件包需要有計劃運行的操作以保證正常工作，可以使用這個文件達成。你既可以設置常規的任務使其在每小時、每天、每星期、每月或其他情況或你希望的時間下運行。相應的文件名是：

- ``package`.cron.hourly` - 安裝至 `/etc/cron.hourly/`package`` ；每小時運行一次。

- ``package`.cron.daily` - 安裝至 `/etc/cron.daily/`package`` ；每天運行一次。

- ``package`.cron.weekly` - 安裝至 `/etc/cron.weekly/`package`` ；每週運行一次。

- ``package`.cron.monthly` - 安裝至 `/etc/cron.monthly/`package`` ：每月運行一次。

- ``package`.cron.d` - 安裝至 `/etc/cron.d/`package``： 對於其他的任何時間。

這些文件均爲 shell 腳本。唯一不同的是 ``package`.cron.d`，它的格式需要參照 crontab(5)

有必要顯式地用 `cron.*` 文件來設置日誌輪轉； 關於這個問題，請參見 dh_installlogrotate(1) 和 logrotate(8).

## 5.5. `dirs`

這個文件指定了我們需要，但在正常安裝過程(`dh_auto_install` 觸發的 `make install DESTDIR=...`)裏沒有被安裝的目錄。通常這是由於 `Makefile` 中存在問題。

`install` 文件中列出的文件不需要爲其提前創建目錄，參看 節 5.11, “`install`”。

最好是先嘗試安裝，如果遇到了問題再使用這個文件。在 `dirs`中列出的目錄名中不應有前導的 / (斜槓)符號。

## 5.6. ``package`.doc-base`

如果你的軟件包在 man 手冊頁和 info 信息文檔外還有其他文檔，你應該使用 `doc-base` 文件註冊它們，這樣用戶可以使用例如 dhelp(1)、dwww(1) 或 doccentral(1) 的工具找到它們。

這通常包括 HTML、PS 和 PDF 檔案，放置在 `/usr/share/doc/`packagename`/`。

以下是 `gentoo` 的 doc-base 文件 `gentoo.doc-base` 的樣子：

    Document: gentoo
    Title: Gentoo Manual
    Author: Emil Brink
    Abstract: This manual describes what Gentoo is, and how it can be used.
    Section: File Management
    Format: HTML
    Index: /usr/share/doc/gentoo/html/index.html
    Files: /usr/share/doc/gentoo/html/*.html

關於文件格式的更多信息，參看 install-docs(8) 以及 Debian `doc-base` 手冊頁，在 `/usr/share/doc/doc-base/doc-base.html/index.html` 有一份本地拷貝，這是由 `doc-base` 軟件包提供的。

關於安裝附加文件的更多訊息，査看 節 3.3, “把文件安裝到目的位置”。

## 5.7. `docs`

這個檔案制定了我們使用 dh_installdocs(1) 安裝到臨時目錄的檔案名。

默認情況下它會加入程式碼目錄頂層的所有名爲 `BUGS`、`README*`、`TODO` 等的檔案。

對於 `gentoo`，這裏還加入了一些其他文件：

    BUGS
    CONFIG-CHANGES
    CREDITS
    NEWS
    README
    README.gtkrc
    TODO

## 5.8. `emacsen-*`

如果你的套件提供可以在安裝時編譯爲字節碼的 Emacs 檔案，你可以使用這些檔案設置。

它們會被 dh_installemacsen(1) 安裝到臨時目錄。

如果你不需要這些，就刪除它們。

## 5.9. ``package`.examples`

dh_installexamples(1) 會將列出的檔案和目錄作爲範例檔案安裝。

## 5.10. ``package`.init` 和 ``package`.default`

如果你的軟件包需要在系統啓動時運行一個守護進程，那麼你顯然沒有按照我最初的建議做事，不是嗎？ :-)

Please read dh_installinit(1) dh_installsystemd(1) to provide startup script.

``package`.default` 檔案 會被安裝至 `/etc/default/`package``。 這個檔案設定被 init 指令碼使用的預設設定。 ``package`.default` 檔案最經常用於設定 一些預設標記或者超時。 如果你的 init 指令碼中有某種 可配置的特性，你可以在 ``package`.default` 檔案中設定它們， 而不是 init 指令碼本身。

如果你的上遊程序中包含了給 init 用的腳本文件，那用不用它都可以。如果不使用，則創建相應的 ``package`.init` 文件；然而如果上游的 init 腳本很好且被安裝到正確的位置，你仍然需要設置 `rc*` 符號鏈接。你需要按照以下的方法在 `rules` 文件中凌駕 dh_installinit：

    override_dh_installinit:
            dh_installinit --onlyscripts

如果你不需要這些，就刪除它們。

## 5.11. `install`

如果你的軟體包需要那些標準的 `make install` 沒有安裝的檔案，你可以把檔名和目標路徑寫入 `install` 檔案，它們將被 dh_install(1) 安裝。[55] 你需要首先檢查要安裝的檔案是否有更有針對性的特定工具會對其進行安裝。例如，文件應寫在 `docs` 檔案中安裝，而不是這一個。

這個 `install` 文件每行安裝一份文件，格式上先是相對於編譯目錄的文件路徑，然後是一個空格，接下來是相對於安裝目錄的目標目錄。例如，假設某個二進制文件 `src/`bar``沒有被默認安裝，則應讓 `install` 呈現成這樣：

    src/bar usr/bin

這意味着安裝這個軟件包時，將有一個二進制文件 `/usr/bin/`bar``.

當然，在相對路徑保持不變的情況下 `install` 文件也可以只包含相對的源路徑而不帶目標位置。這樣的格式通常用於使用 ``package-1`.install`、``package-2`.install` 等將大軟件包分割爲多個二進制包的情況。

如果 dh_install 命令沒有在當前目錄(或者你可能使用 `--sourcedir` 參數指定的位置)找到文件，它會回滾至使用 `debian/tmp` 目錄。

## 5.12. ``package`.info`

如果你的軟件包有 info 信息頁，應該使用 dh_installinfo(1) 安裝，要安裝的文件列於 ``package`.info` 文件中。

## 5.13. ``package`.links`

如果你作爲包維護者需要在包中創建附加的符號鏈接，你應該使用 dh_link(1) 來安裝，要安裝的文件完整路徑列於 ``package`.info` 文件中。

## 5.14. `{`package`.,source/}lintian-overrides`

如果 `lintian` 根據 Debian Policy 的某些規則允許例外從而報告了錯誤診斷，你可以使用 ``package`.lintian-overrides` 或 `source/lintian-overrides` 使其不再警告。請認真閱讀 Lintian 使用者手冊(`https://lintian.debian.org/manual/index.html`) 並避免濫用。

``package`.lintian-overrides` 是對於名爲 ``package`` 的二進制包的有效配置，會由 dh_lintian 命令安裝到`usr/share/lintian/overrides/`package``。

`source/lintian-overrides` 是針對原始碼套件的，不會安裝。

## 5.15. `manpage.*`

你的程序應該有 man 手冊頁，如果它們沒有自帶則需要由你來創建。dh_make 命令創建了幾個 man 手冊頁的模板。爲每一個缺手冊的命令拷貝一份模板，並妥善地編寫，並且要刪除未使用的模板。

### 5.15.1. `manpage.1.ex`

man 手冊頁通常是使用 nroff(1) 的格式編寫的。`manpage.1.ex` 模板也是使用 nroff 格式的。參考 man(7) 手冊頁來簡要瞭解如何編輯這個檔案。

最終的 man 手冊頁文件的名稱，應當爲其對應的程序名稱。 所以我們將 `manpage` 重命名爲 `gentoo`。 同時，它的文件名當然要以 `.1` 作爲第一個後綴，這表示本手冊頁是爲一個用戶命令而攢寫的。 再者，請校驗本 man 手冊處在正確的節(section)。這個簡短的列表列舉了 man 手冊頁的章節：

Section(部分) | Description(描述) | Notes(提示)
--- | --- | ---
1 | User commands(用戶命令) | Executable commands or scripts(可執行命令或腳本)
2 | System calls(系統調用) | Functions provided by the kernel(由內核提供的功能)
3 | Library calls(庫調用) | Functions within system libraries(系統庫中的功能)
4 | Special files(特殊文件) | 經常在 `/dev` 目錄中出沒
5 | File formats(文件格式) | 例如， `/etc/passwd` 的格式
6 | Games(遊戲) | Games or other frivolous programs(遊戲或無聊的程序)
7 | Macro packages(宏包) | 比如 man 宏
8 | System administrarion(系統管理) | Programs typically only run by root(典型的root專用程序)
9 | Kernel routines(內核慣例) | Non-standard calls and internals(非標準調用及內部構建)

所以 `gentoo` 的 man 手冊頁應叫 `gentoo.1`。如果原始代碼中沒有 `gentoo.1` man 手冊頁，你需要重命名 `manpage.1.ex` 模板爲 `gentoo.1` 並按照示例和上游文檔編輯它。

你也可以使用 help2man 命令來藉助每個程序的 `--help` 和 `--version` 參數的輸出來生成 man 手冊頁。[56]

### 5.15.2. `manpage.sgml.ex`

如果你希望使用 SGML 而非 nroff 格式編寫 man 手冊頁，可以使用 `manpage.sgml.ex` 模板。如果你要這樣，需要進行以下步驟：

- 重命名檔案爲類似 `gentoo.sgml` 的名稱。

- 安裝 `docbook-to-man` 套件。

- 在 `control` 文件中將 `docbook-to-man` 添加到 `Build-Depends` 行。

- 在 `rules` 文件裏添加 `override_dh_auto_build` target：

      override_dh_auto_build:
              docbook-to-man debian/gentoo.sgml > debian/gentoo.1
              dh_auto_build

### 5.15.3. `manpage.xml.ex`

如果你希望使用XML 而非 SGML，可以使用 `manpage.xml.ex` 模板。如果你要這樣，需要進行以下步驟：

- 重命名源檔案爲類似 `gentoo.1.xml` 的名稱。

- 安裝 `docbook-xsl` 套件和一個 XSLT 處理器，例如 `xsltproc` (推薦)。

- 在 `control` 文件中將 `docbook-xsl`, `docbook-xml`, 以及 `xsltproc` 軟件包添加到 `Build-Depends` 行。

- 在 `rules` 文件裏添加 `override_dh_auto_build` target：

      override_dh_auto_build:
              xsltproc --nonet \
               --param make.year.ranges 1 \
               --param make.single.year.ranges 1 \
               --param man.charmap.use.subset 0 \
               -o debian/ \
      http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl\
              debian/gentoo.1.xml
              dh_auto_build

## 5.16. ``package`.manpages`

如果你的軟件包有 man 手冊頁，你應該將它們列在 ``package`.manpages` 文件中以便 dh_installman(1) 進行安裝。

要將 `doc/gentoo.1` 安裝爲 `gentoo` 的 man 手冊頁，創建一個 `gentoo.manpages`，內容如下：

    docs/gentoo.1

## 5.17. `NEWS`

dh_installchangelogs(1) 命令會安裝這個檔案。

## 5.18. `{pre,post}{inst,rm}`

`postinst`、`preinst`、`postrm` 和 `prerm` 文件 [57] 被稱爲 maintainer scripts。它們是放置於軟件包控制區域，並由 dpkg 在軟件包安裝、升級或卸載時執行的腳本。

作爲一個新維護人員，你應當避免手工編輯 maintainer scripts ，因爲它們常存在各種問題。更多信息請閱讀 Debian Policy Manual, 6 "Package maintainer scripts and installation procedure" 並查看 dh_make 給出的示例文件。

如果你不聽我的勸告，自己爲一個軟件包創建並定製了 maintainer scripts，你必須保證不僅測試 install 和 upgrade，還應測試 remove 和 purge。

升級到新版本應當是靜默且非侵入式的(已有用戶應當只在發現舊的 Bug 被修復或有新特性時注意到升級的變化)。

當更新必須以非靜默模式進行時(例如分散在多個主目錄中的配置文件都要改爲完全不同的結構時)，作爲最後的手段，你應該考慮將軟件包設置到安全的回退狀態(例如禁用服務)並按照 Debian Policy 提供相應的文檔(`README.Debian` 和 `NEWS.Debian`)。不要在升級時使用 maintainer scripts 觸發 debconf 來打擾用戶。

`ucf` 軟件包提供了 類似 conffile 對可能不標記爲 conffiles 的文件的保留機制，比如由 maintainer scripts 來管理的配置文件。這可以把最大程度減少相關的問題。

這些 maintainer scripts 是 Debian 的增強特性，它們解釋了 人們爲什麼選擇 Debian。你必須非常小心，保證人們不因此產生煩惱。

## 5.19. ``package`.examples`

對於新維護者而言，打包一個庫非常不易，因此不建議嘗試。 這樣說吧，如果你的軟體包有庫，那你應該處理好 `debian/`package`.symbols` 檔案。 參見 節 A.2, “管理 `debian/`package`.symbols`”.

## 5.20. `TODO`

dh_installdocs(1) 命令會安裝這個檔案。

## 5.21. `watch`

`watch` 檔案的格式被詳述於 uscan(1) man 手冊頁中。`watch` 檔案配置了 uscan 程式(它在 `devscripts` 中)以便監視你獲得原始原始碼的網站。它還被用於 Debian 軟體包跟蹤系統（PTS） 服務。

它的內容如下：

    # watch control file for uscan
    version=3
    http://sf.net/gentoo/gentoo-(.+)\.tar\.gz debian uupdate

通常，在按照這個 `watch` 文件執行時，URL `http://sf.net/gentoo` 會被下載，程序會在其中搜索 `<a href=...>`。最後一個斜槓 `/` 後的基本名稱會按照 Perl 正則表達式匹配(參看 perlre(1)) `gentoo-(.+)\.tar\.gz`。在所有匹配的文件裏，將會下載帶有最大版本號的，此後由 uupdate 程序創建更新的源代碼樹。

儘管上述內容對於所有站點都適用，但 SourceForge 下載服務(http://sf.net)仍是一個例外。當 `watch` 中包含匹配 Perl 正則表示式 `^http://sf\.net/` 的 URL 時，uscan 程式會將其替換為 `http://qa.debian.org/watch/sf.php/` 然後應用此規則。http://qa.debian.org/ 的 URL 重定向服務被設計用於提供一個穩定的重定向服務以滿足 `watch` 檔案中的 `http://sf.net/`project`/`tar-name`-(.+)\.tar\.gz` 形式，這樣解決了 SourceForge 經常性的 URL 變更導致的問題。

如果上游提供 tarball 的加密簽章，那麼推薦校驗其真實性，可以用 `pgpsigurlmangle` 選項來實現，這一點在 uscan(1) 中有描述。

## 5.22. `source/format`

在 `debian/source/format` 中只包含一行，寫明瞭此原始碼套件的格式(査看 dpkg-source(1) 獲得完整列表)。在 `squeeze` 後，它應該是以下二者之一：

- `3.0 (native)` - Debian 本土軟件或者

- `3.0 (quilt)` - 其他所有軟體

全新的 `3.0 (quilt)` 原始碼格式將所有修改使用 quilt 補丁系列記錄到 `debian/patches`。這些修改會在解壓原始碼套件時自動應用。[58] Debian 修改保存於 `debian.tar.gz` 壓縮檔，其中包含了整個 `debian` 目錄。這個新格式支持直接添加例如 PNG 圖示等的二進位檔案。[59]

dpkg-source 解壓 `3.0 (quilt)` 格式的源碼包時會自動應用所有列於 `debian/patches/series` 的補丁。你可以使用 `--skip-patches` 選項避免在解壓後自動應用補丁。

## 5.23. `source/local-options`

如果你希望使用版本控制系統（VCS）管理 Debian 打包活動，你可以建立一個分支(例如叫做 `upstream`) 來跟蹤上游程式碼，和另一個分支(對於 Git 而言典型的是 `master` 分支)來跟蹤你的 Debian 軟體包。對於後者，通常會將未應用補丁的上游程式碼和你的 `debian/*` 檔案放在一起以便容易合併上游的新程式碼。

在編譯軟件包之後，源代碼通常會被保持在應用補丁後的狀態。你需要手工執行 `quilt pop -a` 來解除這些補丁，然後再提交到 `master` 分支。你可以向 `debian/source/local-options` 文件裏添加一行 `unapply-patches` 來自動實現此目的。這個文件不會被加入到生成的源代碼包，它隻影響本地的編譯構建行爲。這個文件裏還可以包含 `abort-on-upstream-changes` (參看 dpkg-source(1))。

    unapply-patches
    abort-on-upstream-changes

## 5.24. `source/options`

在源碼樹下自動生成的文件有時會超級討厭，因爲它們會生成毫無意義巨大無比的補丁文件。 爲了減輕這種問題，可以用一些定製模塊比如 dh_autoreconf ，參見 節 4.4.3, “定製 `rules` 檔案”。

你可以給 `--extend-diff-ignore` 選項提供一個 Perl 正則表達式作爲 dpkg-source(1) 的參數，以此忽略 在創建源碼包時自動生成的文件所發生的變更。

作爲這個自動生成文件的問題的通用解決辦法 你可以存放像 dpkg-source 這樣的選項參數到源碼包的 `source/options` 文件中。如下將會跳過給 `config.sub`, `config.guess`, 以及 `Makefile` 創建補丁文件。

    extend-diff-ignore = "(^|/)(config\.sub|config\.guess|Makefile)$"

## 5.25. `patches/*`

舊的 `1.0` 源代碼包格式使用單一的大 `diff.gz` 文件爲源碼保存 `debian` 中的維護文件和補丁。這樣的軟件包比較難於在事後檢查和分析。這不是很好。

新的 `3.0 (quilt)` 源碼格式將補丁存儲在 `debian/patches/*` 中，用 quilt 命令。 這些補丁和其他 `debian` 目錄下的打包數據都會被打包成 `debian.tar.gz` 文件。由於 dpkg-source 命令可以處理 quilt 格式的補丁數據 (在格式爲 `3.0 (quilt)` 的源碼中)，而不需要 `quilt` 軟件包；不需要在 `Build-Depends` 中添加 `quilt`。 [60]

quilt 命令在 quilt(1) 中有詳細描述。它將對源代碼的修改維護於 `debian/patches` 中一系列 `-p1` 級別的補丁文件中，`debian` 目錄外的文件沒有任何修改。這些補丁的順序記錄於 `debian/patches/series` 文件中。你可以輕鬆地 apply (=push)、un-apply (=pop) 和 refresh 補丁。[61]

在 章 3, 修改原始碼 中，我們在 `debian/patches` 創建了三個補丁。

因爲 Debian 補丁位於 `debian/patches`，請確定按照 節 3.1, “設置 quilt” 中的方法正確配置 dquilt。

如果在之後有人(包括你自己)提供了一個補丁 ``foo`.patch`，對於 `3.0 (quilt)` 源代碼包格式可以很容易修改：

    $ dpkg-source -x gentoo_0.9.12.dsc
    $ cd gentoo-0.9.12
    $ dquilt import ../foo.patch
    $ dquilt push
    $ dquilt refresh
    $ dquilt header -e
    ... describe patch

用新的 `3.0 (quilt)` 源代碼包格式存儲的補丁必須有 清晰的邊界。你應該通過 `dquilt pop -a; while quilt push; do quilt refresh; done` 來驗證這點。

[54] 參見 dpkg(1) 以及 Debian Policy Manual, "D.2.5 Conffiles".

[55] 這取代了已經廢棄的 dh_movefiles(1) 命令，它本是用 `files` 檔案所設定的。

[56] 注意， help2man 的佔位符性質 man 手冊頁會聲稱 在 info 系統中有着更爲詳盡的細節。如果命令 缺少 info 頁，那你應該手工編輯由 help2man 命令創建的 man 手冊頁。

[57] 儘管這裏使用 bash 表達式速記法 `{pre,post}{inst,rm}` 來指示這些文件名，但你應該使用 純 POSIX 語法來編寫 maintainer scripts，這是爲了兼容 dash 作爲系統 shell 的情況。

[58] 參看 DebSrc3.0 以瞭解轉換到新的 `3.0 (quilt)` 和 `3.0 (native)` 源代碼格式時的總結。

[59] 實際上新格式還支持多個上游 tarball 和更多的壓縮方法，但這已超出本文件講述的範圍。

[60] 這裏已經提出了若干種補丁集維護方法，並且正爲 Debian 軟件包所採用。 quilt 系統是最推薦的維護系統。而其他的有包括 dpatch, dbs, 以及 cdbs。 其中有許多將 補丁保存爲 `debian/patches/*` 文件。

[61] 如果你需要一個 sponsor 上傳你的軟件包，這種情況下，清晰的軟件包分離和記錄更改的文檔對於軟件包審查過程的順利程度非常重要。

章 4. `debian` 目錄中的必須內容 |  | 章 6. 構建套件