1. 编译环境准备

在 Windows 上为 i686-elf 编译 GCC 是一个痛苦的过程,期间可能会有大量的错误需要解决。所以选择 debian-11.0-i386 操作系统来编译 32 位的 gcc 工具,系统镜像下载地址如下所示:

# debian-11.0-i386 下载地址
http://gemmei.ftp.acc.umu.se/cdimage/archive/11.0.0/i386/iso-dvd/debian-11.0.0-i386-DVD-1.iso

1.1 更换镜像源

使用国内的镜像源如清华镜像源能显著的提高软件下载速度,可以在安装时选择镜像源,或者手动更换清华镜像源

1.2 安装相关软件

编译 GCC 源码前,必须安装相关的工具链,如下载源码的 git 工具,编译源码的 make 工具等。

# 切换为 root 用户
su root

apt update

apt install -y git make autoconf automake autopoint bash bison flex texinfo gettext g++ gperf \
    libffi-dev g++-multilib libtool libltdl-dev libssl-dev libxml-parser-perl pkg-config zip unzip \
    wget libtool-bin build-essential libc6-dev python scons p7zip-full ruby lzip intltool \
    librust-gdk-pixbuf-dev libgmp-dev

# 查看本地安装的 gcc 版本
# gcc version 10.2.1 20210110 (Debian 10.2.1-6)
gcc -v

1.3 交叉编译环境

使用 mxe 可以在 Linux 系统上交叉编译 windows 平台的应用程序,按照如下操作安装 mxe 交叉编译环境:

# 下载 mxe 源码
cd /opt
wget https://codeload.github.com/mxe/mxe/tar.gz/refs/tags/build-2021-04-22
# 解压 mxe 源码
tar -zxvf build-2021-04-22

# 编译 mxe
# 此步要下载 binutils、mingw、gmp、isl、mpfr、gcc等,相当慢
cd mxe-build-2021-04-22
make gcc

# 添加环境变量
vim /etc/profile
# 在 /etc/profile 文件末尾添加
export PATH="/opt/mxe-build-2021-04-22/usr/bin:$PATH"
# 更新环境变量
source /etc/profile

2. GCC源码编译

下载 binutils、gcc、gdb 源码

mkdir /home/build-i686
mkdir /home/build-i686/output
cd /home/build-i686

# 下载 需要编译的binutils, gcc, gdb 源码
wget https://ftp.gnu.org/gnu/binutils/binutils-2.35.tar.gz \
	https://ftp.gnu.org/gnu/gcc/gcc-10.2.0/gcc-10.2.0.tar.gz \
	https://ftp.gnu.org/gnu/gdb/gdb-10.2.tar.gz

# 解压 binutils
tar -zxvf binutils-2.35.tar.gz
# 解压 gcc
tar -zxvf gcc-10.2.0.tar.gz
# 解压 gdb
tar -zxvf gdb-10.2.tar.gz

2.1 编译 binutils

cd /home/build-i686
mkdir build-binutils
cd build-binutils

# 配置 binutils
../binutils-2.35/configure --target=i686-elf --with-sysroot --disable-nls \
    --disable-werror --prefix=/home/build-i686/output --host=i686-w64-mingw32.static

# 编译 binutils
make
# 安装 binutils
make install

2.2 编译 gcc

# 安装 gcc 相关依赖
cd /home/build-i686/gcc-10.2.0
./contrib/download_prerequisites

mkdir /home/build-i686build-gcc
cd /home/build-i686/build-gcc

# 配置 gcc
../gcc-10.2.0/configure --target=i686-elf --disable-nls --enable-languages=c,c++ \
    --without-headers --prefix=/home/build-i686/output --host=i686-w64-mingw32.static

# 编译安装
make all-gcc
make install-gcc
make all-target-libgcc
make install-target-libgcc

若编译过程中出现报错如下:

# 编译中遇到一些错误
i686-elf-gcc: command not found
i686-elf-cc: command not found
i686-elf-ar: command not found
i686-elf-ranlib: command not found

# 解决办法
ln -sf /usr/bin/gcc /usr/bin/i686-elf-gcc
ln -sf /usr/bin/cc /usr/bin/i686-elf-cc
ln -sf /usr/bin/ar /usr/bin/i686-elf-ar
ln -sf /usr/bin/ranlib /usr/bin/i686-elf-ranlib

2.3 编译 gdb

mkdir /home/build-i686/build-gdb
cd /home/build-i686/build-gdb

# 配置 gdb
../gdb-10.2/configure --target=i686-elf --disable-nls --disable-werror \
    --prefix=/home/build-i686/output --host=i686-w64-mingw32.static

# 编译安装
make
make install

2.4 打包

cd /home/build-i686/output
zip -r /home/build-i686/gcc-i686-elf.zip *

# 最后将 /home/build-i686/gcc-i686-elf.zip 文件通过 sftp 下载到 windows 中即可
# 在 windows 中检查测试ld支持的链接模式
i686-elf-ld -m --help

# 显示支持模式如下
# i686-elf-ld: unrecognised emulation mode: --help
# Supported emulations: elf_i386 elf_iamcu

3. 文件瘦身

GCC源码编译完成后的目录结果如下

.
+-- bin
+-- i686-elf
╎   +-- bin
╎   +-- lib
╎   └─── +-- ldscripts
+-- include
╎   +-- gdb
+-- lib
╎   +-- gcc
╎   └─── +-- i686-elf
╎        └─── +-- 10.2.0
╎             ╎    +-- 64
╎             ╎    +-- include
╎             ╎    +-- include-fixed
╎             ╎    +-- install-tools
╎             ╎    └─── +-- include
╎             └─── +-- x32
+-- libexec
╎   +-- gcc
╎   └─── +-- i686-elf
╎        └─── +-- 10.2.0
╎             └─── +-- install-tools
+-- share
╎   +-- gdb
╎   ╎    +-- syscalls
╎   └─── +-- system-gdbinit
╎   +-- info
╎   +-- man
╎   ╎    +-- man1
╎   ╎    +-- man5
╎   └─── +-- man7

仅保留 gcc,g++, ld, gdb, as, objcopy, objdump 的目录结构如下

.
+-- bin
╎   +-- i686-elf-as.exe
╎   +-- i686-elf-g++.exe
╎   +-- i686-elf-gcc.exe
╎   +-- i686-elf-gdb.exe
╎   +-- i686-elf-ld.exe
╎   +-- i686-elf-objcopy.exe
╎   +-- i686-elf-objdump.exe
+-- i686-elf
╎   +-- bin
╎   ╎    +-- as.exe
╎   ╎    +-- ld.exe
╎   ╎    +-- objcopy.exe
╎   └─── +-- objdump.exe
+-- libexec
╎   +-- gcc
╎   └─── +-- i686-elf
╎        └─── +-- 6.3.0
╎             ╎    +-- cc1.exe
╎             └─── +-- cc1plus.exe

若设置PATH环境变量, 再把文件重命名(去掉i686-elf),目录结构还可以进一步简化为

.
+-- bin
╎   +-- g++.exe
╎   +-- gcc.exe
╎   +-- gdb.exe
╎   +-- as.exe
╎   +-- ld.exe
╎   +-- objcopy.exe
╎   +-- objdump.exe
╎   +-- cc1.exe
╎   +-- cc1plus.exe