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 as well excludes 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
添加话题