交叉编译工具包指南
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 的递归自调用引起的)。