网络上相关资料更多都是在制作 Linux x86_64 和 Linux arm64 之间的交叉编译器,我也尝试过,但流程很复杂,每个人的编译环境又不同,很容易编译失败。 因为我平时主要在 Windows 平台上工作,所以尝试在 Linux 上编译一个 Windows 上运行的 GCC,经过无数次编译失败,耗费N个小时后,终于成功了!
首先有些基本概念要了解一下:
有个工具包叫Binutils,它是汇编器、链接器的源码,是必须要编译的,它不依赖 glibc 和 Linux 头文件。比较独立,所以编译一般不会出问题。
如果目标是 Linux 平台,则编译过程比较复杂,gcc、glibc要分阶段编译,比较复杂,容易失败。而目标平台是 Windows 的话则简单很多。
cd /opt tar xf binutils-2.44.tar.xz cd binutils-2.44/ mkdir build && cd build ../configure --prefix=/opt/x86_64-w64-mingw32-gcc15 --disable-multilib --disable-nls --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-w64-mingw32 make -j$(nproc) make install-strip
编译 GCC
1 2 3 4 5 6 7
cd /opt tar xf gcc-15.1.0.tar.xz cd gcc-15.1.0/ ./contrib/download_prerequisites mkdir build && cd build ../configure --prefix=/opt/x86_64-w64-mingw32-gcc15 -with-sysroot=/usr/x86_64-w64-mingw32 --enable-languages=c,c++ --enable-threads=win32 --enable-shared --disable-multilib --disable-werror --disable-checking --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-w64-mingw32 make -j$(nproc)
$ dpkg -l | grep mingw-w64 ii mingw-w64-common 7.0.0-2 all Common files for Mingw-w64 ii mingw-w64-x86-64-dev 7.0.0-2 all Development files for MinGW-w64 targeting Win64
cd /opt tar xf binutils-2.44.tar.xz cd binutils-2.44/ mkdir build && cd build ../configure --prefix=/opt/x86_64-w64-mingw32-gcc15 --disable-multilib --disable-nls --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-w64-mingw32 make -j$(nproc) make install-strip
# 注意,我们指向的是 mingw-w64-headers 子目录下的 configure 脚本 cd /opt/mingw-w64-v13.0.0/mingw-w64-headers mkdir build && cd build
$ ../configure -h 'configure' configures mingw-w64-headers 4.0b to adapt to many kinds of systems.
Usage: ../configure [OPTION]... [VAR=VALUE]...
To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables.
Defaults for the options are specified in brackets.
Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print'checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache aliasfor'--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or '..']
Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [/usr/local] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX]
By default, 'make install' will install all the files in '/usr/local/bin', '/usr/local/lib' etc. You can specify an installation prefix other than '/usr/local' using '--prefix', for instance '--prefix=$HOME'.
For better control, use the options below.
Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/mingw-w64-headers] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR]
Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names
System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD]
Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer --enable-w32api Enable building a w32api package for Cygwin (shorthand for --includedir=PREFIX/include/w32api --disable-crt) --disable-crt Do not use the default crt headers --enable-sdk=ARG Add the desired SDK, where ARG can be one of ddk, no or all. Default is all. --enable-idl Enable installing idl files
Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-widl=PATH use widl to update idl-based headers. Optionally search for a compatible widl in PATH --with-default-win32-winnt=VER Default value of _WIN32_WINNT (default: 0xa00) --with-default-msvcrt=LIB Default msvcrt to target (default: ucrt)
有两个参选项得注意:--with-default-win32-winnt和--with-default-msvcrt。 --with-default-win32-winnt决定了支持最低的 Windows API,这里的默认值是0x0A00,表示 Windows 10,有些高了,因为我要求兼容至 Vista,那么要改为0x0600,其他值查看微软手册:更新 WINVER 和 _WIN32_WINNT。 --with-default-msvcrt决定了运行时类型,默认是ucrt,意味着最终编译出的程序会依赖一堆api-ms开头的 DLL 文件,这需要用户电脑安装 VC 运行库,这是默认且推荐的方式。 如果要用老的运行时msvcrt,就将选项改为--with-default-msvcrt=msvcrt即可。
1 2
../configure --prefix=/opt/sysroot/mingw --with-default-win32-winnt=0x0600 --with-default-msvcrt=msvcrt --build=x86_64-linux-gnu --host=x86_64-w64-mingw32 make install-strip
用msvcrt的好处是不需要额外安装 VC Runtime,仅依赖msvcrt.dll,特别是编译 32 位程序的话,可以运行在 XP 系统上。
$ which x86_64-w64-mingw32-gcc /opt/x86_64-w64-mingw32-gcc15/bin/x86_64-w64-mingw32-gcc
OK,没问题。开始编译完整的mingw-w64:
1 2 3 4 5
cd /opt/mingw-w64-v13.0.0/mingw-w64-crt mkdir build && cd build ../configure --prefix=/opt/sysroot/mingw --with-default-msvcrt=msvcrt --build=x86_64-linux-gnu --host=x86_64-w64-mingw32 make -j$(nproc) make install-strip
第二次编译 GCC
这是最后一步,编译完整的 GCC。注意编译时新建一个文件夹,不要在第一次的 build 目录中进行
1 2 3 4 5
cd /opt/gcc-15.1.0/ mkdir build-gcc-final && cd build-gcc-final ../configure --prefix=/opt/x86_64-w64-mingw32-gcc15 -with-sysroot=/opt/sysroot --enable-languages=c,c++ --enable-threads=win32 --enable-shared --disable-multilib --disable-werror --disable-checking --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-w64-mingw32 make -j$(nproc) make install-strip
大功告成!再次编译示例程序
1
/opt/x86_64-w64-mingw32-gcc15/bin/x86_64-w64-mingw32-g++ -std=c++23 main.cpp -o main