makepkg

来自 Arch Linux 中文维基
(重定向自Makepkg (简体中文)

makepkg是一个软件包自动编译脚本。使用时需要一个 Unix 环境和 PKGBUILD.

makepkg 是由 pacman 包提供的。

配置[编辑 | 编辑源代码]

makepkg 的详细配置选项可以通过 makepkg.conf(5) 查询。

/etc/makepkg.conf 是 makepkg 的主配置文件。用户的自定义配置位于 $XDG_CONFIG_HOME/pacman/makepkg.conf~/.makepkg.conf. 建议用户在编译软件包之前检查 makepkg 配置。

打包人信息[编辑 | 编辑源代码]

每个软件包都会有元数据信息,其中就包含 packager. 默认情况下,用户自己打包的软件标记为 Unknown Packager. 如果多个用户会在系统上编译,或者需要发布软件包给其他人,最好提供真实的联系人。可以通过 makepkg.conf 中的 PACKAGER 变量设置。

检查安装软件包的打包人:

pacman -Qi package
...
Packager       : Unknown Packager
...

修改之后:

pacman -Qi package
...
Packager       : John Doe <john@doe.com>
...

要自动签名过程,请同时在 makepkg.conf 中设置 GPGKEY 变量.

包输出[编辑 | 编辑源代码]

makepkg 默认会在工作目录创建软件包,并把源代码下载到 src/ 目录。可以配置到自定义的路径,比如所有安装的软件包放到 ~/build/packages/,所有源代码放到 ~/build/sources/.

配置以下makepkg.conf,如果需要配置变量:

  • PKGDEST - 目录中存储产生的包
  • SRCDEST - 目录中存储的source 数据 (符号链接将被放置到 src/ 如果点其他地方)
  • SRCPKGDEST - 目录存储产生的源代码包 (构建用 makepkg -S)
提示:可以用 paccache -c ~/build/packages/ 清理 PKGDEST 目录。

验证签名[编辑 | 编辑源代码]

注意: makepkg 中的签名验证并不使用 pacman 的密钥环, 而是使用用户的密钥[1]

如果签名文件是以 .sig.asc 形式作为 PKGBUILD 代码的一部分,makepkg 会自动验证软件包. 如果用户未提供需要的签名公钥,makepkg 会停止安装过程并提示用户说无法验证 PGP 密钥。

如果缺少公钥或希望其他开发者进行签名,可以手动导入或通过密钥服务器导入。要临时禁用签名检查请在执行 makepkg 命令时加上 --skippgpcheck 选项。

使用[编辑 | 编辑源代码]

继续之前,确保 base-devel包组 软件组已经安装。属于这个组的软件包不会列在 PKGBUILD 文件的依赖中。

注意:
  • Make sure sudo is configured properly for commands passed to pacman.
  • Running makepkg itself as root is disallowed.[2] Besides how a PKGBUILD may contain arbitrary commands, building as root is generally considered unsafe.[3] Users who have no access to a regular user account should run makepkg as the nobody user.

要编译软件包,用户必须首先建立一个 PKGBUILD,或者编译脚本(在创建软件包中有详细描述),或者从 ABS 编译系统Arch User Repository 或其他来源获取。

警告: 只从信任的来源编译和/或安装软件包。

拥有一个 PKGBUILD 之后,切换到存放这个文件的目录,输入下面的命令编译 PKGBUILD 描述的软件包:

$ makepkg

如果需要的依赖不满足,makepkg 会输出一个警告然后失败。想要编译软件包然后自动安装必须的依赖,只需要输入以下命令:

$ makepkg --syncdeps

注意这些依赖必须在已配置的软件源之中。另外,用户也可以在编译前手动安装需要的依赖(pacman -S --asdeps dep1 dep2)。如果添加了 -r/--rmdeps 选项,makepkg 会在结束前删除不再需要的编译依赖,如果需要持续编译软件包,请考虑使用删除未使用软件包的方式处理。

一旦所有的依赖都满足并且软件包成功编译,一个软件包文件 (pkgname-pkgver.pkg.tar.zst) 会在工作目录下创建。想安装,运行

$ makepkg --install

要清空残余的文件和目录,例如解压到 $srcdir 的文件,输入下面的选项。这对于在使用同一个文件夹多次编译同一个软件包或者升级软件包版本时很有用。它防止过期的或残余的文件呈递到新的编译任务中。

$ makepkg --clean

更多信息请阅读makepkg(8).

使用技巧[编辑 | 编辑源代码]

减少下载和解压时间[编辑 | 编辑源代码]

编译 VCS 软件包时,使用 SRCDEST 可以缩短获取和解压源代码的时间。

编译结果优化[编辑 | 编辑源代码]

在使用 makepkg 编译软件时,make, gccg++ 会使用 CFLAGSCXXFLAGS 选项。默认情况下,这些选项产生的是通用的包,可以在不同的机器上安装。使用针对目标机器的设置,可以获得性能提升,但编译出的包也许无法在其他机器上运行。

注意: 记住不是所有的包创建系统都会使用你设置的变量。一些包的 Makefiles 或者 PKGBUILD文件会覆盖设置。
/etc/makepkg.conf
...

#########################################################################
# ARCHITECTURE, COMPILE FLAGS
#########################################################################
#
CARCH="x86_64"
CHOST="x86_64-unknown-linux-gnu"

#-- Exclusive: will only run on x86_64
# -march (or -mcpu) builds exclusively for an architecture
# -mtune optimizes for an architecture, but builds for whole processor family
CFLAGS="-march=x86-64 -mtune=generic -O2 -pipe -fstack-protector --param=ssp-buffer-size=4 -D_FORTIFY_SOURCE=2"
CXXFLAGS="-march=x86-64 -mtune=generic -O2 -pipe -fstack-protector --param=ssp-buffer-size=4 -D_FORTIFY_SOURCE=2"
LDFLAGS="-Wl,-O1,--sort-common,--as-needed,-z,relro"
#-- Make Flags: change this for DistCC/SMP systems
#MAKEFLAGS="-j2"

...

默认的 makepkg.conf CFLAGSCXXFLAGS 是与所有机器各自的体系结构兼容的。

并不是所有的编译系统都使用 makepkg.conf 中定义的变量。例如, cmake 不会遵循 CPPFLAGS。所以 PKGBUILD 中会直接指定需要的配置。

源代码 Makefile 或编译命令行中指定的选项优先级更高,会取代 makepkg.conf 中的设置。

在 x86_64 机器上,不要花费时间进行编译选项优化,绝大部分情况下优化效果都不明显。使用非标准的 CFLAGS 非常容易降低性能,因为编译器倾向于快速增大生成的文件,例如解开循环、错误的向量化和非理性的内联函数。除非通过测评得出性能提升的结论,否则最好不要做优化。

GCC 的手册页面有完整的选项列表。GCC optimizationSafe CFLAGS wiki 文章提供了深入信息。

GCC 可以进行 CPU 自动检测,可以在编译时自动选择本地机器支持的优化。要使用它,删除所有 -march-mtune,然后添加 -march=native. 例如:

/etc/makepkg.conf
CFLAGS="-march=native -O2 -pipe -fno-plt"
CXXFLAGS="${CFLAGS}"

要查看march=native启用的选项,运行:

 $ gcc -march=native -v -Q --help=target
  • 如果没有指定 -march=native, -Q --help=target不会起作用。[4] 需要通过一个编译过程确定真正使用的选项是哪个,请参考 Gentoo:Safe CFLAGS#Manual

生成新 md5sums[编辑 | 编辑源代码]

pacman 4.1 pacman-contrib 和其中的 updpkgsums 已经合并进入 pacman,生成和替换 PKGBUILD 中的校验和:

$ updpkgsums

Starting in pacman version 5.2.2, makepkg.conf also includes overrides for the RUSTFLAGS environment variable, for flags given to the Rust compiler. The Rust compiler can also detect and enable architecture-specific optimizations by adding -C target-cpu=native to the given RUSTFLAGS value:

/etc/makepkg.conf
RUSTFLAGS="-C opt-level=2 -C target-cpu=native"

To see which CPU features this will enable, run:

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

Running --print cfg without -C target-cpu=native will print the default configuration. The opt-level parameter can be changed to 3, s, or z as desired. See The Rust compiler's documentation for details.

减少编译时间[编辑 | 编辑源代码]

并行编译[编辑 | 编辑源代码]

make 编译系统使用 MAKEFLAGS 环境变量指定 make 的额外选项。这个值也可以在 makepkg.conf 中进行设置。

使用多核系统的用户可以设定同时运行的任务数。可以用nproc获得可用处理器的个数,如果结果是 4, 则使用-j4. 有些 PKGBUILD 强制使用 -j1,因为某些版本会产生冲突或者软件包并不支持。如果出现软件包因为此原因无法编译,请在 bug 系统中报告

完整的选项请阅读 make(1)

使用内存文件系统进行编译[编辑 | 编辑源代码]

编译过程需要大量的读写操作,要处理很多小文件。将工作目录移动到 tmpfs 可以减少编译时间。

使用BUILDDIR变量可以临时将 makepkg 的编译目录设置到 tmpfs:

$ BUILDDIR=/tmp/makepkg makepkg

修改 makepkg.confBUILDDIR 选项可以永久变更编译目录。设置此变量为BUILDDIR=/tmp/makepkg可以利用 Arch 默认临时文件系统的/tmp

注意:
  • tmpfs 中构建大型软件包时可能会内存不足。
  • tmpfs 目录挂载时不能使用 noexec 选项,否则编译命令无法执行。
  • tmpfs 中编译的文件重启后会消失,设置 PKGDEST 选项可以将构建结果保存到其它目录。

ccache[编辑 | 编辑源代码]

ccache 可以将编译结果缓存起来供下次编译使用,减少编译时间。

生成新校验和[编辑 | 编辑源代码]

安装 pacman-contrib,然后用下面命令生成新校验和并替换 PKGBUILD 中的内容,只需要执行:

$ updpkgsums

updpkgsums uses makepkg --geninteg to generate the checksums. See this forum discussion for more details.

可以用 sha256sum 命令生成校验和并手动加入 sha256sums

使用其它压缩算法[编辑 | 编辑源代码]

为了加快打包和安装速度,您可以更改 PKGEXT ,代价是生成的软件包文件更大。例如,以下命令可以让此次调用生成不压缩的软件包:

$ PKGEXT='.pkg.tar' makepkg

另一个使用 lz4 算法的例子:

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

要使这些设置之一永久生效,请在 /etc/makepkg.conf 中设置 PKGEXT

在压缩时使用多个CPU核心[编辑 | 编辑源代码]

zstd 支持对称多处理 (SMP) ,通过添加 --threads 标志以加速压缩。例如,要让 makepkg 使用尽可能多的 CPU 核心来压缩软件包,可以编辑 /etc/makepkg.conf 文件中的 COMPRESSZST 数组:

COMPRESSZST=(zstd -c -z -q --threads=0 -)

xz 支持对称多处理 (SMP) ,通过添加 --threads 标志以加速压缩。例如,要让 makepkg 使用尽可能多的 CPU 核心来压缩软件包,可以编辑 /etc/makepkg.conf 文件中的 COMPRESSXZ 数组:

COMPRESSXZ=(xz -c -z --threads=0 -)

pigzgzip 的一个替代、并行实现,它默认使用所有可用的CPU核心 (可以使用 -p/--processes 标志来使用较少的核心) :

COMPRESSGZ=(pigz -c -f -n)

pbzip2bzip2 的一个替代、并行实现,它也默认使用所有可用的CPU核心。可以使用 -p# 标志来使用较少的核心 (注意:-p 和核心数之间没有空格) :

COMPRESSBZ2=(pbzip2 -c -f)

lbzip2bzip2 的另一个替代、并行实现,它也默认使用所有可用的CPU核心。可以使用 -n 标志来使用较少的核心。

COMPRESSBZ2=(lbzip2 -c -f)

plzipAURlzip 的一个多线程实现,它也默认使用所有可用的CPU核心。可以使用 -n/--threads 标志来使用较少的核心。

COMPERSSLZ=(plzip -c -f)

Show packages with specific packager[编辑 | 编辑源代码]

expac is a pacman database extraction utility. This command shows all packages installed on the system with the packager named packagername:

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

This shows all packages installed on the system with the packager set in the /etc/makepkg variable PACKAGER. This shows only packages that are in a repository defined in /etc/pacman.conf.

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

Build 32-bit packages on a 64-bit system[编辑 | 编辑源代码]

See 32-bit package guidelines.

Unattended package signing[编辑 | 编辑源代码]

本文或本章节可能需要合并到GnuPG#Unattended_passphrase

附注: This is not specific to makepkg(在 Talk:Makepkg 中讨论)

这篇文章的某些内容需要扩充。

原因: Another option is gnupg-set-passphrase(1)[失效链接 2022-06-25] (在 Talk:Makepkg 中讨论)

A person may not be available to provide the passphrase for the gpg private key used to sign with in automated build environments such as Jenkins. It is ill-advised to store a private gpg key on a system without a passphrase.

A resulting zst package made with makepkg can still be be signed after creation:

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

where the GPG passphrase is securely provided and obscured by your automation suite of choice.

The resulting zst and sig file can be referenced by pacman clients expecting a valid signature and repositories created with repo-add --sign when hosting your own repo.

Magnet URIs[编辑 | 编辑源代码]

Support for magnet URIs resources (with magnet:// prefix) in the source field can be added using the transmission-dlagentAUR download agent.

问题处理[编辑 | 编辑源代码]

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 进入了软件包中的文件,用下面命令检查:

grep -R "$(pwd)/src" pkg/

一个可能是 C/++ 代码使用了 __FILE__ 宏并将完整路径传递给了编译器。

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[5]:

/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.

参阅[编辑 | 编辑源代码]