makepkg - Arch Linux 中文维基

跳至內容

# makepkg

出自 Arch Linux 中文维基

相關文章

- .SRCINFO
- Arch 構建系統
- Arch 用戶軟體倉庫 (AUR)
- 創建軟體包
- GnuPG
- 官方倉庫
- OpenPGP
- pacman
- PKGBUILD

翻譯狀態：

- 本文（或部分內容）譯自 makepkg，最近一次同步於 2026-01-21，若英文版本有所更改，則您可以幫助同步與翻譯更改的內容。
- 您可以在 ArchWiki 的對應頁面找到本文翻譯的原始修訂歷史。
- 本文可能與英文原文存在出入。

makepkg 是一個軟體包自動化構建腳本，使用時需要一個具備構建條件的 Unix 環境和一個 PKGBUILD 文件。

makepkg 是由 pacman包 包提供的。

## 配置

全局配置位於 `/etc/makepkg.conf`，還可以通過 `$XDG_CONFIG_HOME/pacman/makepkg.conf` 或 `~/.makepkg.conf` 進行用戶特定配置。你還可以添加 `/etc/makepkg.conf.d/makepkg.conf` 文件進行系統全局配置更改。在構建軟體包前，建議先檢查 makepkg 配置。

提示：devtools包 用於從乾淨的 chroot 構建軟體包的助手腳本會使用 `/usr/share/devtools/makepkg.conf.d/arch.conf` 配置文件。

更多信息請參考 makepkg.conf(5)。

### 打包人信息

每個軟體包都會有元數據信息，其中就包含 packager。默認情況下，用戶自己打包的軟體標記為 `Unknown Packager`。如果多個用戶會在系統上編譯，或者需要發布軟體包給其他人，最好提供真實的聯繫人。打包人信息可以通過 `makepkg.conf` 中的 `PACKAGER` 變量進行設置。

要檢查已安裝軟體包的打包人：

    $ pacman -Qi package

    ...
    Packager       : John Doe <john@doe.com>
    ...

要自動化簽名過程，請同時在 `makepkg.conf` 中設置 `GPGKEY` 變量.

### 包輸出

makepkg 默認會在工作目錄創建軟體包，並把原始碼下載到 `src/` 目錄。可以配置到自定義的路徑，比如將所有構建出的軟體包放到 `~/build/packages/` 目錄，所有源文件放到 `~/build/sources/` 目錄下。

根據需求不同，可以配置 `makepkg.conf` 下的這些變量：

- `PKGDEST` - 軟體包構建輸出目錄
- `SRCDEST` - 用於存放源數據的目錄（在指向其它位置的情況下，軟連結將被放置到 `src/` 目錄下）
- `SRCPKGDEST` - 原始碼包構建輸出目錄（通過 `makepkg -S` 構建）

提示：可以參考 pacman#清理軟體包緩存 用命令（例如 `paccache -c ~/build/packages/`）清理 `PKGDEST` 目錄

你還可以#在包目錄下使用相對路徑。

### 驗證簽名

注意：makepkg 中的簽名驗證並不使用 pacman 的密鑰環, 而是使用用戶的密鑰[1]。

如果簽名文件是以 .sig 或 .asc 形式作為 PKGBUILD 源碼數組的一部分提供，makepkg 會自動驗證軟體包。如果用戶未提供需要的簽名公鑰，makepkg 會停止安裝過程並提示用戶說無法驗證 PGP 密鑰。

如果缺少軟體包所需的公鑰，那麼 PKGBUILD 很可能帶有 validpgpkeys 項，其中包含了所需的密鑰 ID。你可以手動進行導入，也可以在在公鑰伺服器上進行查找，然後導入。運行 makepkg 時使用 `--skippgpcheck` 選項可以臨時禁用簽名檢查。

## 使用

繼續之前，確保已安裝了 base-devel包組 軟體包組。屬於這個組的軟體包不會被要求列在 PKGBUILD 文件的構建時依賴（makedepends）中。

注意：

- 確保為傳入 pacman 的命令正確配置了 sudo。另外，可以通過 makepkg.conf(5) 配置文件的 `PACMAN_AUTH` 參數指定不同的認證命令。
- 不允許以根用戶（root）身份運行 `makepkg`。[2] 原因除了 `PKGBUILD` 可能包含惡意代碼外，以 root 身份構建軟體一般都被認為是不安全的。[3] 無法使用普通用戶時需以 nobody 用戶的身份運行 `makepkg`（例如 `runuser -u nobody makepkg`）。

要構建軟體包，用戶必須首先創建一個 PKGBUILD 文件或編譯腳本（在創建軟體包中有詳細描述），或者從 Arch 構建系統（ABS）、AUR 或其他來源獲取。獲取到 `PKGBUILD` 後，切換到該文件所在文件夾中，然後執行以下命令構建軟體包：

    $ makepkg

如果需要的依賴不滿足，makepkg 會輸出一個警告然後失敗。想要編譯軟體包並自動安裝必須的依賴，只需添加 `-s`/`--syncdeps` 參數：

    $ makepkg --syncdeps

如果添加了 `-r`/`--rmdeps` 選項，makepkg 會在結束後刪除不再需要的編譯依賴。如果需要持續編譯軟體包，請考慮定期刪除未使用軟體包。

注意：

- 這些依賴必須在已配置的軟體源之中存在，具體信息請參考 pacman#軟體倉庫。另外，用戶也可以在編譯前手動安裝需要的依賴：(`pacman -S --asdeps dep1 dep2`)。
- 在安裝依賴包時，只使用全局值，即不會使用拆分包打包功能中的任何覆蓋值。

在滿足所有依賴並成功編譯軟體包後，一個軟體包文件（`pkgname-pkgver.pkg.tar.zst`）將會被創建在工作目錄下。如需安裝，請使用 `-i`/`--install` 參數（與 `pacman -U pkgname-pkgver.pkg.tar.zst` 相同）：

    $ makepkg --install

要清理殘餘的文件和目錄（如解壓到 `$srcdir` 的文件），請使用 `-c`/`--clean` 選項。這對於在使用同一個文件夾多次編譯同一個軟體包或者升級軟體包版本時很有用。它可以防止過期或殘餘的文件被呈遞到新的構建任務中：

    $ makepkg --clean

更多信息請閱讀 makepkg(8)。

## 優化

默認選項與 devtools包 為官方倉庫構建軟體包使用的選項一致[4]。因此，用戶可以通過調整以下選項來適應本地環境，以獲得或多或少的收益。

### 優化編譯結果

通過啟用針對主機的編譯器優化，可以提高打包後軟體的性能。缺點是，為特定處理器架構編譯的二進制文件無法在其他機器上正常運行。在 x86_64 機器上，重新構建官方軟體包通常不會有顯著的性能提升，因此不值得為此投入時間。

不過，使用 「非標準」 編譯器標誌很容易降低性能。許多編譯器優化僅在某些情況下有用，不應對軟體包隨意應用。除非有評測數據證明某項優化更快，否則很有可能會導致性能下降！Gentoo 的 GCC 優化和安全的 CFLAGS 文章提供了有關編譯器優化的更多信息。

#### C 和 C++

傳遞到 C/C++ 編譯器（例如 gcc包 或 clang包）的選項是通過 `CFLAGS`、`CXXFLAGS` 和 `CPPFLAGS` 環境變量傳入的。在使用 Arch 構建系統時，makepkg 會將 `makepkg.conf` 中的配置項作為這些環境變量進行傳遞。默認值會生成通用的二進制文件，可安裝在各種機器上。

注意：

- 記住，不是所有的構建系統都會使用 `makepkg.conf` 中設置的變量。例如，cmake 不會遵循 `CPPFLAGS` 預處理器選項環境變量。因此，很多 PKGBUILD 都包含了針對打包軟體所使用的構建系統而設置的選項。
- 源碼提供的 `Makefile` 或編譯命令行中指定的參數優先級更高，並有可能會取代掉 `makepkg.conf` 中的配置。

GCC 可以自動檢測架構，並應用安全的架構特定優化項。要使用該特性，首先需要移除所有 `-march` 和 `-mtune` 標誌，然後添加 `-march=native`，例如：

    /etc/makepkg.conf

    CFLAGS="-march=native -O2 -pipe ..."
    CXXFLAGS="${CFLAGS} ..."

要查看該操作會啟用的選項，執行：

    $ gcc -march=native -v -Q --help=target

注意：如果沒有指定 `-march=native`，`-Q --help=target` 將不會起作用[5]。具體啟用的選項需要編譯後才能知道。詳細步驟請參考[6]。

進一步優化需要啟用對內存占用和編譯時間有較大負面影響的選項，做法為將優化級別從 `-O2` 設為 `-O3`。使用該選項一般都能提升二進制文件的性能，但具體效果取決於文件本身。更多信息請參考 Gentoo:GCC optimization#-O 和 GCC 優化選項頁。

#### Rust

從 `pacman` 5.2.2 開始，`makepkg.conf` 還包含了對 `RUSTFLAGS` 環境變量的覆寫，用於替換 Rust 編譯器的標誌。通過在 `RUSTFLAGS` 中添加 `-C target-cpu=native`，Rust 編譯器還能檢測並應用架構特定優化項：

    /etc/makepkg.conf.d/rust.conf

    RUSTFLAGS="-C force-frame-pointers=yes -C target-cpu=native"

查看該操作會已啟用的 CPU 特性：

    $ rustc -C target-cpu=native --print cfg

在不包含 `-C target-cpu=native` 的情況下運行 `--print cfg` 將輸出默認配置。

下面為一些可以添加到 `RUSTFLAGS` 的優化參數：

- `-C opt-level=3`：可以根據需要將該值更改為 `3`、`s` 或 `z`。針對分發的構建默認使用 `opt-level=3`。
- `-C codegen-units=n`：選擇小於 `16` 的 `n` 值可以優化二進制文件，但會增加構建耗時。
- `-C link-arg=-z -C link-arg=pack-relative-relocs` 可以降低二進制文件的大小。

更多信息請參考 Rust 編譯器文檔。

### 減少編譯時間

#### 並行編譯

make包 編譯系統使用 `MAKEFLAGS` 環境變量指定 make 的額外選項。這個值也可以在 `makepkg.conf` 文件中進行設置。

使用多核/多處理器系統的用戶可以設定同時運行的任務數。可以用 nproc(1) 獲得可用處理器的個數，例如：`MAKEFLAGS="--jobs=$(nproc)"`。

有些 `PKGBUILD` 會強制使用 `-j1`，因為某些版本會產生衝突或者軟體包本身並不支持。如果出現軟體包因為此原因無法編譯，請在確認錯誤是由 `MAKEFLAGS` 引起的前提下，在 bug 跟蹤系統中進行報告（如果是 AUR 包，則向包維護者報告）。

完整可用選項請參考 make(1)。

#### 使用內存文件系統進行編譯

編譯過程需要大量的讀寫操作，要處理很多小文件。將工作目錄移動到 tmpfs 可能會減少編譯時間。

使用 `BUILDDIR` 變量可以臨時將 makepkg 的編譯目錄設置到現有 tmpfs，例如：

    $ BUILDDIR=/tmp/makepkg makepkg

將 `makepkg.conf` 中的 `BUILDDIR` 選項取消注釋可以永久變更編譯目錄，具體位於 `/etc/makepkg.conf` 文件末尾的 `BUILD ENVIRONMENT` 一節。設置此變量為 `BUILDDIR=/tmp/makepkg` 可以利用 Arch 默認的 `/tmp` 臨時文件系統。

注意：

- 在 tmpfs 中構建大型軟體包時可能會內存不足。
- 掛載 tmpfs 目錄時不能使用 `noexec` 選項，否則編譯命令無法執行。
- 在 tmpfs 中構建好的包重啟後會消失，設置 PKGDEST 選項可以將構建結果保存到其它目錄。

#### 使用編譯緩存

ccache 可以將編譯結果緩存起來供下次編譯使用，減少編譯時間。

#### 使用 mold 連結器

mold包 是 ld/lld 連結器的直接替代，據稱其速度稍微較快。

要使用 mold，需添加 `-fuse-ld=mold` 到 `LDFLAGS`，例如：

    /etc/makepkg.conf

    LDFLAGS="... -fuse-ld=mold"

要向 mold 添加額外選項，可以將它們添加到 `LDFLAGS` 中，例如：

    /etc/makepkg.conf

    LDFLAGS="... -fuse-ld=mold -Wl,--separate-debug-file"

要為 Rust 軟體包使用 mold，可以將 `-C link-arg=-fuse-ld=mold` 添加到 `RUSTFLAGS` 中，例如：

    /etc/makepkg.conf.d/rust.conf

    RUSTFLAGS="... -C link-arg=-fuse-ld=mold"

#### 禁用調試包和 LTO

包含在 2024 年 2 月 pacman 6.0.2-9 版本的 90bf367e 號提交默認啟用了 `debug` 和 `lto` 選項。

構建調試包能讓官方倉庫為用戶提供更多的問題排查工具（archlinux/packaging/packages/pacman#23#note_173528），但在自行構建軟體包時，調試包不是必需的，而且會減慢構建進程。參見 archlinux/packaging/packages/pacman#23#note_173782。

連結時優化可以生成更優化的二進制文件，但會增加構建耗時（archlinux/packaging/packages/pacman#23#note_173678），不一定是一個理想的權衡。

如需禁用這些選項，可以在 `OPTIONS=()` 數組中的這些選項前直接添加 `!` 符號，例如：`OPTIONS=(...!debug !lto...)`

### 壓縮

#### 使用其它壓縮算法

為了加快打包和安裝速度，您可以更改 `PKGEXT`，代價是生成的軟體包文件更大。

例如，以下命令可以跳過壓縮步驟，使得安裝時無需解壓：

    $ PKGEXT='.pkg.tar' makepkg

另一個例子使用 lz4 算法，可以提升速度：

    $ PKGEXT='.pkg.tar.lz4' makepkg

要使這些設置之一永久生效，請在 `/etc/makepkg.conf` 中設置 `PKGEXT` 。

#### 在壓縮時使用多個 CPU 核心

zstd包 支持對稱多處理（SMP），通過添加 `-T`/`--threads` 標誌可以加速壓縮。默認情況下，`/etc/makepkg.conf` 中的 `COMPRESSZST` 數組包含了 `-T0` 標誌，使得 zstd 儘可能使用多的物理 CPU 核心來壓縮軟體包。可以通過 `--auto-threads=logical` 標誌讓 zstd 根據邏輯 CPU 核心數進一步提升調用數：

    COMPRESSZST=(zstd -c -T0 --auto-threads=logical -)

lz4包 和 xz包 默認使用多線程，不需要對 `/etc/makepkg.conf` 進行修改。

pigz包 是 gzip包 的一個替代、並行實現，它默認使用所有可用的CPU核心（可以使用 `-p`/`--processes` 標誌來使用較少的核心）：

    COMPRESSGZ=(pigz -c -f -n)

pbzip2包 是 bzip2包 的一個替代、並行實現，它也默認使用所有可用的CPU核心。可以使用 `-p#` 標誌來使用較少的核心（注意：`-p` 和核心數之間沒有空格）：

    COMPRESSBZ2=(pbzip2 -c -f)

lbzip2包 是 bzip2包 的另一個替代、並行實現，它也默認使用所有可用的CPU核心。可以使用 `-n` 標誌來使用較少的核心。

    COMPRESSBZ2=(lbzip2 -c -f)

plzipAUR 是 lzip包 的一個多線程實現，它也默認使用所有可用的 CPU 核心。可以使用 `-n`/`--threads` 標誌來使用較少的核心。

    COMPRESSLZ=(plzip -c -f)

#### 修改壓縮等級

有幾種壓縮算法（包括 zstd 和 xz）支持設定壓縮等級，以在速度、內存占用和壓縮效率間進行取捨。

## 小技巧

### 減少下載和解壓時間

#### 設定源文件位置

特別是在編譯 VCS 軟體包時，使用 `SRCDEST` 可以縮短重新構建時獲取和解壓原始碼的時間。

#### 自定義 DLAGENTS

可以使用支持並行下載的下載器，以 axel包 為例：

    /etc/makepkg.conf

    DLAGENTS=('file::/bin/curl -gqC - -o %o %u'
              'ftp::/bin/axel -n 2 -o %o %u'
              'http::/bin/axel -n 2 -o %o %u'
              'https::/bin/axel -n 2 -o %o %u')

另請參考 Nonfree applications package guidelines#Custom DLAGENTS。

### 生成新校驗和

安裝 pacman-contrib包，然後在 PKGBUILD 文件所在目錄中執行以下命令來生成新校驗和：

    $ updpkgsums

`updpkgsums` 使用 `makepkg --geninteg` 生成校驗和，查看此論壇了解詳情

也可以用如 `sha256sum` 命令生成校驗和並手動加入到 `sha256sums` 數組中。

### 從本地源文件生成

如果您想對原始碼進行更改，可以使用`-o`、`--nobuild`下載原始碼，而無需構建軟體包，僅進行下載和解壓縮文件選項。

    $ makepkg -o

您現在可以對原始碼進行更改，然後使用`-e`，`--noextract` 不提取源文件（使用現有的$srcdir/ dir）選項構建軟體包。使用`-f`選項覆蓋已經生成的和現有的包。

    $ makepkg -ef

### 顯示具有特定打包程序的包

expac包 是一個pacman資料庫提取工具。此命令顯示系統上安裝的所有打包程序名為packagername的包：

    $ expac "%n %p" | grep "packagername" | column -t

這將顯示系統上安裝的所有軟體包， `/etc/makepkg` 變量 `PACKAGER`僅顯示在中定義的存儲庫中的包 `/etc/pacman.conf`。

    $ . /etc/makepkg.conf; grep -xvFf <(pacman -Qqm) <(expac "%n\t%p" | grep "$PACKAGER$" | cut -f1)

### 在 64 位系統上構建 32 位軟體包

參考32位軟體包打包準則。

### 軟體包簽名託管

本文或本章節可能需要合併到GnuPG#Unattended_passphrase。

附註： 非 makepkg 特定。（在 Talk:Makepkg 中討論）

這篇文章的某些內容需要擴充。

原因：還可以使用 gpg-preset-passphrase(1) (在 Talk:Makepkg 中討論)

在使用類似 Jenkins 的自動構建環境時，用戶可能無法為用於軟體簽名的 gpg 私鑰提供密碼。另外，不建議在沒有密碼保護的系統上存放 GPG 私鑰。

使用 makepkg 創建的 zst 軟體包可以在創建後通過如下命令進行簽名：

    $ gpg --detach-sign --pinentry-mode loopback --passphrase --passphrase-fd 0 --output NewlyBuilt.pkg.tar.zst.sig --sign NewlyBuilt.pkg.tar.zst

其中 GPG 密碼由你選擇的自動化套件安全地提供和隱藏。

生成的 `zst` 和 `sig` 文件可被需要有效簽名的 pacman 客戶端和使用 `repo-add --sign` 創建的軟體倉庫引用。

### 磁力連結 URI

使用 transmission-dlagentAUR 下載器可以支持在 `source` 欄位使用磁力連結 URI（前綴為 `magnet://`）。

### Running makepkg in a systemd control group

If the package you are building takes too many resources to build with your default make flags, which are otherwise set properly for most packages, you can try running it in its own control group. makepkg-cgAUR is a wrapper for makepkg that achieved this via systemd control groups (see systemd.resource-control(5)).

### Running with idle scheduling policy

Package build process can lead to high CPU utilization, especially in case of #Parallel compilation. Under heavy CPU load, the system can issue a significant slowdown up to becoming unusable, even with the highest nice(1) value. User interface and foreground applications may stutter or even became unresponsive.

This can be worked around by changing the scheduling policy to `SCHED_IDLE` before running makepkg. It ensures that package building process does not interfere with regular tasks and only utilizes remaining unused CPU time.

From sched(7) § SCHED_IDLE: Scheduling very low priority jobs:

  This policy is intended for running jobs at extremely low priority (lower even than a +19 nice value with the `SCHED_OTHER` or `SCHED_BATCH` policies).

The `SCHED_IDLE` policy can be set by running chrt(1) command with the `-i` flag, specifying priority 0 (the only valid option for `SCHED_IDLE`) and specifying the PID of the current shell.

For most shells:

    $ chrt -iap 0 $$

提示：You can apply this command for every build by placing it into `makepkg.conf`.

For the fish shell, where `$$` is not set:

    $ chrt -iap 0 %self

### 在包目錄下使用相對路徑

Instead of using absolute paths for the package output options, you can also configure relative paths inside each package directory.

注意：The following options might cause problems with some AUR helpers, as they might use `makepkg.conf` in a context where `$startdir` is not defined. So be careful.

For example, you can define target paths in your `makepkg.conf` file as follows. The `$startdir` variable refers to the directory where a `PKGBUILD` is located when you build a package.

    PKGDEST="$startdir/build/packages/"
    SRCDEST="$startdir/build/sources/"
    SRCPKGDEST="$startdir/build/srcpackages/"
    LOGDEST="$startdir/logs/"

This will result in:

- Built packages will be stored in: `"package directory"/build/packages/`
- All downloaded source files will be stored in: `"package directory"/build/sources/`
- Built source packages will be stored in: `"package directory"/build/srcpackages/`
- All logs will be stored in: `"package directory"/logs/`

makepkg will still create `src/` and `pkg/` directories as usual, so this is expected behaviour.

## 問題處理

### Specifying install directory for QMAKE based packages

The makefile generated by qmake uses the environment variable `INSTALL_ROOT` to specify where the program should be installed. Thus this package function should work:

    PKGBUILD

    ...
    package() {
    	cd "$srcdir/${pkgname%-git}"
    	make INSTALL_ROOT="$pkgdir" install
    }
    ...

Note, that qmake also has to be configured appropriately. For example put this in the corresponding .pro file:

    YourProject.pro

    ...
    target.path = /usr/local/bin
    INSTALLS += target
    ...

### WARNING: Package contains reference to $srcdir

由於某種原因，有時 `$pkgdir` 或 `$srcdir` 中的字面字符串會進入到軟體包中的文件[7]。

可以在 makepkg 構建文件夾中執行以下命令進行檢測：

    $ grep -R "$PWD/src" pkg/

一個可能是 C/++ 代碼使用了 `__FILE__` 宏並將完整路徑傳遞給了編譯器。

Dotnet 二進制文件有時也會在默認配置文件中包含 `.pdb` 文件的完整路徑。

### Makepkg fails to download dependencies when behind proxy

When makepkg calls dependencies, it calls pacman to install the packages, which requires administrative privileges via sudo. However, sudo does not pass any environment variables to the privileged environment, and includes the proxy-related variables `ftp_proxy`, `http_proxy`, `https_proxy`, and `no_proxy`.

In order to have makepkg working behind a proxy, invoke one of the following methods.

#### Enable proxy by setting its URL in XferCommand

The XferCommand can be set to use the desired proxy URL in `/etc/pacman.conf`. Add or uncomment the following line in `pacman.conf`:

    /etc/pacman.conf

    ...
    XferCommand = /usr/bin/curl --proxy http://username:password@proxy.proxyhost.com:80 --location --continue-at - --fail --output %o %u
    ...

#### Enable proxy via sudoer's env_keep

Alternatively, one may want to use sudoer's `env_keep` option, which enables preserving given variables the privileged environment. See Pacman#pacman does not honor proxy settings for more details.

### Makepkg fails, but make succeeds

If something successfully compiles using make, but fails through makepkg, it is almost certainly because `/etc/makepkg.conf` sets an incompatible compilation variable. Try adding these flags to the PKGBUILD `options` array:

`!buildflags`, to prevent its default `CPPFLAGS`, `CFLAGS`, `CXXFLAGS`, and `LDFLAGS`.

`!makeflags`, to prevent its default `MAKEFLAGS`.

`!debug`, to prevent its default `DEBUG_CFLAGS`, and `DEBUG_CXXFLAGS`, in case the PKGBUILD is a debug build.

If any of these fix the problem, this could warrant an upstream bug report assuming the offending flag has been identified.

## 參閱

- makepkg(8)
- makepkg.conf(5)
- Makepkg 流程概覽
- makepkg 源碼

分類：​

- 包開發
- 關於 Arch
- 命令
- OpenPGP

隱藏分類：​

- 使用「模板:合併」標記的頁面或章節

makepkg
新增話題