vimacs's personal siteWritten with Vim and Emacs

构建和使用 MinGW 交叉工具链的一些记录

首先说一下为什么要自己构建 MinGW 交叉工具链。我单位的服务器用着个古老的操作系统,而且没办法联网安装软件,所有的软件都要找相关部门的人复制进去。因为我习惯使用最新的软件,所以我经常复制软件的源代码进服务器,然后自己编译。

构建 MinGW 交叉工具链

这个工作主要参考 Arch Linux 的 mingw-w64 的软件包 PKGBUILD. 从 PKGBUILD 可以注意到,Arch 打包这些软件有循环依赖,例如 mingw-w64-crt 需要 mingw-w64-gcc 构建,而 mingw-w64-gcc 又依赖 mingw-w64-crt. 因此,从头构建整套 MinGW 交叉工具链,照抄 Arch 的构建脚本是不行的。我们要按照构建一般的交叉工具链的方法来做,重点是分析各个组件的依赖关系。

首先要构建的是 mingw-w64-binutils, 它不依赖于其他的 MinGW 包,同时构建其他的包都需要它的汇编器和链接器。

接下来是构建 GCC 和 MinGW 的 C 库。MinGW 的 C 库需要用 MinGW GCC 构建,而 MinGW GCC 在构建的过程中需要 MinGW 的头文件构建 libgcc 等库。所以这些软件中要先构建的是 MinGW 头文件,对应于 Arch 的包 mingw-w64-headers. 构建和安装头文件不需要编译,只需要复制头文件到安装目录就行了。

接下来构建第一份 GCC,我们称它为 stage1-gcc. 它的作用仅用于构建 MinGW 的 C 库。在 GCC configure 的时候,只需要启用 C 语言的支持,并且不构建 libatomic, libssp, libquadmath 这些库。

有 stage1-gcc, 就可以构建 MinGW 的 C 库了。我们需要的是 mingw-crt 和 winpthreads 库,这两个库需要分开构建和安装,先构建并安装 mingw-crt,再构建和安装 winpthreads 即可。

最后构建最终版的 GCC. 配置这份 GCC 就没什么限制了,一般的配置是启用 C,C++ 语言,其他配置选项按照需求启用就行了。

用 MinGW 交叉工具链构建 Windows 版的 LLVM

以构建 LLVM 为例介绍一下 MinGW 交叉工具链的用法。

LLVM 使用 CMake 构建系统,我们可以直接使用系统中安装好的 cmake 和 ninja 去构建 LLVM.

LLVM 在构建的过程中,要使用 llvm-tblgen 生成一些文件,这份 llvm-tblgen 必须是在构建的机器上运行的,所以需要先用系统的工具链构建 llvm-tblgen:

mkdir build-tblgen
cd build-tblgen
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ../llvm-project-12.0.0.src/llvm
ninja bin/llvm-tblgen

然后交叉编译 LLVM, 为了演示方便,我们这里只构建 llvm-mc.exe. 要注意 CMake 使用交叉工具链的方法:

mkdir build
cd build
cmake -G Ninja \
  -DCMAKE_SYSTEM_NAME=Windows \
  -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++ \
  -DLLVM_TABLEGEN="$(realpath ../build-tblgen/bin/llvm-tblgen)" \
  ../llvm-project-12.0.0.src/llvm
ninja bin/llvm-mc.exe