前言
交叉编译器(Cross Compiler)是一个在一种系统架构上编译出另一种系统架构可执行代码的编译器。
This compiler that we build here will have a generic target (i686-elf) that allows you to leave the current operating system behind, meaning that no headers or libraries of the host operating system will be used. Without using a cross-compiler for operating system development, a lot of unexpected things can happen because the compiler assumes that the code is running on the host operating system.
参考以上内容,如果选择使用C语言开发系统,需要为自己的系统编译专属的GCC交叉编译器,这样用高级语言开发的程序可以在自己的系统上跑,也就是可以将源代码转换为目标系统的目标文件。其他语言也要参考文档编译对应的编译器。
The compiler must know the correct target platform (CPU, operating system). The compiler that comes with the host system does not know by default that it is compiling something else entirely, unless a lot of problematic options are passed to it, which will create a lot of problems in the future. The solution is to build a cross-compiler.
如果不编译GCC交叉编译器,正常情况下,编译器必须知道正确的目标平台(CPU,以及操作系统),而自己开发的系统...?GCC编译器并不认识...这时候就需要自己编译了。
GNU编译器集合是一个具有依赖关系的高级软件,需要安装多个依赖,以及确保能够科学上网。
GNU Binutils是二进制工具的集合,总之看起来很厉害很高级就对了,需要使用Binutils构建GCC。请使用与所需的GCC编译器版本大致同时发布的Binutils,可以使用
ld --version检查binutils版本。
第一步:安装最新的GCC版本,以及依赖
GCC安装不写了,写一下需要的依赖:(很多我不认识不知道干什么的,大概就是需要安装Texinfo来构建Binutils。需要安装GMP、数学库MPC和MPFR来构建GCC。GCC可以选择使用ISL库。)
- 类Unix环境(可以使用Linux或WSL)
- wget(用来下载源码)
- GCC
- G++
- Make
- Bison
- Flex
- GMP
- MPFR
- MPC
- Texinfo
- ISL (可选)
全部都使用包管理器安装就可以了。我用apt install。
apt install make build-essential bison flex libgmp3-dev libgmp-dev libmpfr-dev libmpc-dev texinfo libisl-dev wget
注意事项
Linux发行版自带的GCC有可能会发布自己的补丁GCC和Binutils,大概率能够使用下面的源代码构建一个可以工作的交叉编译器,也有概率无法用当前的Linux发行版构建一个新的系统编译器。在这种情况下,尝试一个较新的GCC版本或获得补丁的源代码。
如果需要构建16位C/C++代码,请不要使用GCC版本13.X.X和14.X.X!当访问全局变量时,发生错误:
collect 2:fatal error:ld terminated with signal 11 [Segmentation fault],core dumped。可以构建GCC版本12.1.0。Debian 13 很新,默认源里的库应该都满足要求。如果遇到编译 GCC 时关于
MPC或MPFR的版本太旧,可能需要从源码编译这些库(较复杂)。但通常用apt安装的版本已经够用。
第二步:下载源代码并设置环境
挂梯子下载 binutils 和 GCC 的源码,将源码下载到~/src。可以在GNU主镜像下载源码,分别在GCC源码镜像和Binutils源码镜像。以当前的最新且时间相近版本为例(binutils 2.46.0 和 GCC 15.2.0)。换版本就把命令中的版本号替换掉。
| binutils-2.46.0.tar.gz | 2026-02-10 04:59 | 51M |
| gcc-15.2.0.tar.xz | 2025-08-08 03:35 | 96M |
# 下载 binutils 2.46.0
wget https://ftp.gnu.org/gnu/binutils/binutils-2.46.0.tar.xz
# 下载 GCC 15.2.0
wget https://ftp.gnu.org/gnu/gcc/gcc-15.2.0/gcc-15.2.0.tar.xz
# 解压两个压缩包
tar -xf binutils-2.46.0.tar.xz
tar -xf gcc-15.2.0.tar.xz

可能解压时遇到的错误
xz: (stdin):输入意外结束和tar: 归档文件中异常的 EOF,通常意味着下载的文件不完整或已损坏。如果像我一样中断下载很多次,wget每次发现当前目录已有同名文件时会自动添加数字后缀。你需要全部删掉,然后一次性完整下载。(我就遇到了)下载很慢挂梯子即可解决,代理工具需要选择全局,开启系统代理与虚拟网卡。免费梯子可能网络波动,导致下载中断,换个梯子即可解决。
第三步:编译Binutils和GCC
配置环境
目前系统:Debian 13 (这是当前电脑操作系统)
目标:i686-elf(这是新系统的内核平台:32位 x86,无操作系统环境)
编译好之后的安装位置:~/opt/cross(需要准备一个安装目录,我想只为自己安装到~/opt/cross,如果需要全局安装,可以安装到/usr/local/cross。)
打开终端,复制粘贴下面三行命令,为了告诉系统要把新编译器装在哪里,以及目标平台是什么。
export PREFIX="$HOME/opt/cross"
export TARGET=i686-elf
export PATH="$PATH:$PREFIX/bin"
注意:打开新终端需要重新运行这三条命令。如果想永久生效,可以把它们加到
~/.bashrc文件末尾。(不推荐)
编译Binutils
我们先编译 binutils,编译需要等一小会即可。
# 回到src目录
cd ~/src
# 创建一个单独的构建目录(好习惯)
mkdir build-binutils
cd build-binutils
# 配置:检查环境,生成 Makefile,这个时候会输出很多yes和no结尾的东西,没报错内容即可继续
../binutils-2.46.0/configure --target=$TARGET --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror
# 编译(-j$(nproc) 表示用所有 CPU 核心并行编译,速度更快)
make -j$(nproc)
# 安装到 $PREFIX 目录
make install
解释
那一条../目录开头的命令看起来很奇怪,其实是用来生存Makefile的。
--target=$TARGET:指定我们想要的工具链目标(i686-elf)--prefix="$PREFIX":安装路径--disable-nls:禁用本地语言支持(编译更快)--disable-werror:不要将警告当作错误(避免因旧系统警告导致编译失败)
make 命令就是编译。
-j$(nproc)会利用你 CPU 的所有核心并行编译,速度更快。- 第一条
make命令会编译整个 binutils,时间取决于机器性能(通常几分钟到十几分钟)。 - 完成后,第二条
make install会将编译好的程序安装到$PREFIX/bin目录(即~/opt/cross/bin)。
如果一切顺利,~/opt/cross/bin 下应该会出现 i686-elf-ld、i686-elf-as 等程序。
编译GCC
现在开始编译 GCC 本身。这一步会花比较长的时间(可能 1-40 分钟,由你的电脑性能决定),请耐心等待。
cd ~/src
# 依旧好习惯
mkdir build-gcc
cd build-gcc
# 配置 GCC(注意:我们只编译 C 语言支持,并且不依赖任何头文件)
../gcc-15.2.0/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --enable-languages=c --without-headers
# 编译 GCC 的核心部分(只编译 C 编译器,不编译完整的运行时库)
make -j$(nproc) all-gcc
# 编译 libgcc(一个底层支持库,编译器需要它)
make -j$(nproc) all-target-libgcc
# 安装
make install-gcc
make install-target-libgcc
解释:
--enable-languages=c:只编译 C 前端(如果你以后想用 C++,可以改成c,c++)--without-headers:告诉 GCC 不要找目标系统的头文件(新系统还没有)all-gcc和all-target-libgcc是分步构建,避免编译整个 GCC 套件里我们不想要的部分。
第四步:验证编译器
编译完成后,我们来检查一下新编译器是否能运行。
# 查看版本信息
$HOME/opt/cross/bin/$TARGET-gcc --version
如果显示出 GCC 的版本号(例如 gcc (GCC) 14.2.0),那就说明交叉编译器构建成功!

注意:这个编译器不能编译普通的C程序。当用#包含任何标准头文件时,交叉编译器都会抛出错误(除了少数几个实际上是平台无关的,并且是由编译器自己生成的)。
C标准定义了两种不同的执行环境-“独立”和“托管”。虽然对于一般的应用程序员来说,这个定义可能相当模糊,但进行操作系统开发时,它是非常明确的:内核是“独立的”,你在用户空间中所做的一切都是“托管的”。
调用新GCC编译器
要临时通过$TARGET-gcc来使用新的编译器,可以在终端执行以下命令将$HOME/opt/cross/bin添加到$PATH中:
export PATH="$HOME/opt/cross/bin:$PATH"
需要永久添加到~/.bashrc中,可以这样做:
编辑 ~/.bashrc 文件
使用文本编辑器打开该文件:
nano ~/.bashrc
在文件末尾添加一行
将以下内容粘贴到文件末尾:
# 添加自定义交叉编译工具链路径
export PATH="$HOME/opt/cross/bin:$PATH"

保存并退出
在 nano 中按 Ctrl+O 保存,然后 Ctrl+X 退出。
使配置立即生效
执行以下命令重新加载 ~/.bashrc:
source ~/.bashrc
或者直接关闭当前终端并重新打开一个新终端。
验证是否生效
运行:
echo $PATH
输出中应该能看到这样的内容。
worable@worable:~/下载$ echo $PATH
/home/worable/opt/cross/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
Comments NOTHING