Arch 软件包指南
32位 – CLR – CMake – Cross – DKMS – Eclipse – Electron – 字体 – Free Pascal – GNOME – Go – Haskell – Java – KDE – 内核模块 – Lisp – Meson – MinGW – Node.js – 非自由软件 – OCaml – Perl – PHP – Python – R – Ruby – Rust - 安全 – Shell – VCS – Web – Wine
本页面描述了如何为交叉编译器工具链创建软件包。另一种交叉编译的方法是使用 distcc 在混合架构上进行。请参阅 Distcc#使用 distcc 进行交叉编译。
提示 作为创建交叉编译器包的替代方案,您可以使用 crosstool-ng 以全自动化方式创建您自己的工具链。crosstool-ng 可以在 crosstool-ng 中找到。
重要提示
本页面描述了新的方法,其灵感来源于以下软件包
mingw-w64-gcc 和 mingw-w64-* 系列的其他软件包
arm-none-eabi-gcc 和 arm-none-eabi-* 系列的其他软件包
arm-wince-cegcc-* 系列的其他软件包
版本兼容性
警告 使用不兼容的工具链编译软件包版本会导致不可避免的失败。默认情况下,请认为**所有**版本都不兼容。
以下策略允许您选择兼容的 gcc、binutils、内核和 C 库版本
一般规则gcc 和 binutils 版本之间存在关联,请同时使用已发布的版本;
最好使用最新的内核头文件来编译 libc,但使用 --enable-kernel 开关(glibc 特有,其他 C 库可能使用不同的约定)来强制在旧内核上工作;
官方仓库:您可能需要应用额外的修复和技巧,但 Arch Linux(或其特定架构的派生版)使用的版本很可能可以协同工作;
软件文档:所有 GNU 软件都有 README 和 NEWS 文件,记录了诸如依赖项的最低要求版本等信息;
其他发行版:它们也进行交叉编译
https://trac.clfs.org 涵盖了构建交叉编译器所需的步骤,并提到了相对最新的依赖项版本。
构建交叉编译器
构建交叉编译器的通用方法是
binutils:构建一个交叉 binutils,用于链接和处理目标架构
头文件:安装一套目标架构的 C 库和内核头文件使用 linux-api-headers 作为参考,并将 ARCH=target-architecture 传递给 make
创建 libc 头文件包(Glibc 的过程在此 处描述)
gcc-stage-1:构建一个基础(stage 1)的 gcc 交叉编译器。它将用于编译 C 库。由于它无法链接到它没有的 C 库,因此它几乎无法构建任何其他东西。
libc:构建交叉编译的 C 库(使用 stage 1 交叉编译器)。
gcc-stage-2:构建一个完整的(stage 2)C 交叉编译器
头文件和 libc 的来源因平台而异。
提示 精确的流程因您的需求而异。例如,如果您想创建一个与 Arch Linux 系统相同的内核和 glibc 版本的“克隆”,则可以跳过构建头文件,并将 --with-build-sysroot=/ 传递给 configure。
包命名
包名**不**应以 cross- 开头(之前曾提出过,但未被官方软件包采纳,可能是因为名称过长),而应由包名组成,前面加上 GNU 三元组,不包含供应商字段或在供应商字段中包含“unknown”;例如:arm-linux-gnueabihf-gcc。如果存在更短的命名约定(例如 mips-gcc),则可以使用,但不推荐。
文件放置
最新版本的 gcc 和 binutils 为 sysroot 和库使用了不冲突的路径。可执行文件应放在 /usr/bin/ 中,为避免冲突,请在所有可执行文件前加上架构名称。
通常,./configure 会至少包含以下参数
_target=your_target
_sysroot=/usr/lib/${_target}
...
./configure \
--prefix=${_sysroot} \
--sysroot=${_sysroot} \
--bindir=/usr/bin
其中 your_target 可以是,例如,“i686-pc-mingw32”。
示例
这是 MinGW 的 binutils 的 PKGBUILD。值得注意的地方是
指定交叉环境的根目录
使用 ${_pkgname} 、${_target} 和 ${_sysroot} 变量使代码更具可读性
删除重复/冲突的文件
# Maintainer: Allan McRae
# cross toolchain build order: binutils, headers, gcc (pass 1), w32api, mingwrt, gcc (pass 2)
_target=i686-pc-mingw32
_sysroot=/usr/lib/${_target}
pkgname=${_target}-binutils
_pkgname=binutils
pkgver=2.19.1
pkgrel=1
pkgdesc="MinGW Windows binutils"
arch=('i686' 'x86_64')
url="https://gnu.ac.cn/software/binutils/"
license=('GPL')
depends=('glibc>=2.10.1' 'zlib')
options=('!libtool' '!distcc' '!ccache')
source=(http://ftp.gnu.org/gnu/${_pkgname}/${_pkgname}-${pkgver}.tar.bz2)
md5sums=('09a8c5821a2dfdbb20665bc0bd680791')
build() {
cd ${_pkgname}-${pkgver}
mkdir binutils-build && cd binutils-build
../configure --prefix=${_sysroot} --bindir=/usr/bin \
--with-sysroot=${_sysroot} \
--build=$CHOST --host=$CHOST --target=${_target} \
--with-gcc --with-gnu-as --with-gnu-ld \
--enable-shared --without-included-gettext \
--disable-nls --disable-debug --disable-win32-registry
make
make DESTDIR=${pkgdir}/ install
# clean-up cross compiler root
rm -r ${pkgdir}/${_sysroot}/{info,man}
}
注意 在构建交叉工具链时,始终从专用目录(所谓的“out-of-tree”编译)执行 configure 和 make 命令,并在 PKGBUILD 发生任何微小更改后删除整个 src 目录。
方法与原因
为什么不安装到 /opt
两个原因
首先,根据《文件系统标准》,这些文件就属于 /usr。就这样。
其次,安装到 /opt 是在没有其他选择时的最后手段。
“不在路径中的可执行文件”是什么意思?
这个奇怪的技巧可以简化交叉编译。有时,项目的 Makefiles 不使用 CC 等变量,而是直接使用 gcc。如果您只想尝试交叉编译这样的项目,编辑 Makefile 可能会非常耗时。然而,更改 $PATH 以优先使用“我们的”可执行文件是一个非常快速的解决方案。然后您将运行 PATH=/usr/arch/bin/:$PATH make 而不是 make。
故障排除
编译失败但没有明确信息怎么办?
对于运行 configure 时发生的错误,请阅读 $srcdir/pkgname-build/config.log。对于编译时发生的错误,请向上滚动控制台日志或搜索“error”。
这个错误 [error message] 意味着什么?
很可能您犯了一些非明显的错误
配置标志过多或过少。尝试使用已证明有效的标志集。
依赖项已损坏。例如,错放或丢失的 binutils 文件可能导致 gcc 配置期间出现模糊的错误。
您未在 build() 函数中添加 export CFLAGS=""(参见 GCC Bugzilla 中的 bug 25672)。
某些 --prefix/--with-sysroot 组合可能需要目录是可写的(clfs 指南中未明确说明)。
sysroot 尚未包含内核/libc 头文件。
如果谷歌搜索无果,请立即放弃当前配置,尝试更稳定/经过验证的配置。
为什么文件会被安装到错误的位置?
各种运行通用 make install 行的方法会导致不同的结果。例如,某些 make 目标可能不支持 DESTDIR,而需要使用 install_root。tooldir、prefix 和其他类似参数也一样。有时以参数形式提供参数而不是环境变量,例如
./configure CC=arm-elf-gcc
而不是
CC=arm-elf-gcc ./configure
反之亦然,可能会导致不同的结果(通常由 configure/make 的递归自我调用引起)。
参见
https://wiki.osdev.org/GCC_Cross-Compiler