交叉编译工具包指南
32 位 – CLR – CMake – 交叉 – 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 进行交叉编译。
重要提示
本页面描述了新的做事方式,灵感来自以下软件包
- 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 库可能使用不同的约定)来强制在旧内核上工作;
- 官方仓库:您可能需要应用额外的修复和 hack,但 Arch Linux(或其特定于架构的分支)使用的版本最有可能可以协同工作;
- 软件文档:所有 GNU 软件都有
README和NEWS文件,记录了诸如依赖项的最低要求版本之类的内容; - 其他发行版:它们也进行交叉编译
- https://trac.clfs.org 涵盖了构建交叉编译器所需的步骤,并提到了依赖项的最新版本。
构建交叉编译器
构建交叉编译器的一般方法是
- binutils:构建交叉 binutils,它为目标架构链接和处理
- headers:为目标架构安装一组 C 库和内核头文件
- 使用 linux-api-headers 作为参考,并将
ARCH=目标架构传递给 make - 创建 libc 头文件软件包(Glibc 的处理过程在此处描述链接)
- 使用 linux-api-headers 作为参考,并将
- gcc-stage-1:构建基本的(stage 1)gcc 交叉编译器。这将用于编译 C 库。它几乎无法构建任何其他东西(因为它无法链接到它没有的 C 库)。
- libc:构建交叉编译的 C 库(使用 stage 1 交叉编译器)。
- gcc-stage-2:构建完整的(stage 2)C 交叉编译器
头文件和 libc 的来源将因平台而异。
--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 <allan@archlinux.org>
# 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}
}
方法和原因
为什么不安装到 /opt 中
两个原因
- 首先,根据文件系统层次结构标准,这些文件就应该属于
/usr下的某个位置。句号。 - 其次,安装到
/opt是在没有其他选择时的最后措施。
什么是“路径外可执行文件”?
这种奇怪的方法可以更轻松地进行交叉编译。有时,项目 Makefile 不使用 CC 和 co. 变量,而是直接使用 gcc。如果您只想尝试交叉编译这样的项目,则编辑 Makefile 可能是一项非常耗时的操作。但是,更改 $PATH 以首先使用“我们”的可执行文件是一个非常快速的解决方案。然后,您将运行 PATH=/usr/arch/bin/:$PATH make 而不是 make。
故障排除
如果编译失败且没有明确的消息怎么办?
对于在运行 configure 期间发生的错误,请阅读 $srcdir/pkgname-build/config.log。对于在编译期间发生的错误,请向上滚动控制台日志或搜索单词“error”。
这个错误 [错误消息] 是什么意思?
很可能您犯了一些不明显的错误
- 配置标志过多或过少。尝试使用已经验证过的标志集。
- 依赖项已损坏。例如,错放或丢失的 binutils 文件可能会导致 gcc 配置期间出现神秘错误。
- 您没有将
export CFLAGS=""添加到您的build()函数中(请参阅 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 的递归自调用引起的)。