最近需要在Windows上搭建C/C++的开发环境,首先要安装的就是编译器。微软提供的C/C++编译器是MSVC,不过MSVC和Visual Studio捆绑,过于庞大,所以我们还是选择更轻量级的Mingw-w64。Mingw-w64实际上是Windows版本的GCC,为了能够将GCC移植到Windows上,Mingw-w64通过一组头文件把部分Posix系统调用翻译为Windows API,并且使用Windows平台的CRT来替代Glibc。Mingw-w64可以直接下载安装,但是这里我们选择通过编译源代码来创建Mingw-w64,好处在于可以很方便地控制GCC版本。为了提升工作效率,我们在Linux环境下,通过交叉编译的方式产生Windows本地的Mingw-w64编译器。编译32位工具链和64位工具链的命令稍有不同,在文中有相应说明。
准备工作
搭建开发环境
开发环境可以在任意主流Linux发行版上搭建。以Debian Buster为例,我们通过apt
命令安装基本开发环境
sudo apt install g++ autoconf automake make patch autopoint bison flex gawk texinfo libtool
此外,还需要安装交叉编译的Mingw-w64编译器,请按照另一篇教程在Linux系统上创建Mingw-w64交叉编译器提供的步骤安装。
设置环境变量
为了方便,设置环境变量
export TARGET=x86_64-w64-mingw32
export CROSS_BUILDDIR=$HOME/mingw64-cross
export BUILDDIR=$HOME/mingw64
export GCC_VERSION=11.2.0
export MINGW_VERSION=9.0.0
export BINUTILS_VERSION=2.37
export MPFR_VERSION=4.1.0
export MPC_VERSION=1.2.1
export GMP_VERSION=6.2.1
export ISL_VERSION=0.24
其中
TARGET
表示目标平台CROSS_BUILDDIR
表示交叉编译工具链的安装路径BUILDDIR
为安装路径GCC_VERSION
表示GCC版本号MINGW_VERSION
表示Mingw-w64版本号BINUTILS_VERSION
表示Binutils版本号MPFR_VERSION
表示MPFR版本号MPC_VERSION
表示MPC版本号GMP_VERSION
表示GMP版本号ISL_VERSION
表示isl版本号
如果要编译32位的工具链,应该把TARGET
、CROSS_BUILDDIR
和BUILDDIR
设置为
export TARGET=i686-w64-mingw32
export BUILDDIR=$HOME/mingw32
export CROSS_BUILDDIR=$HOME/mingw32-cross
下载源代码
使用wget
把源代码下载到安装路径下的tmp
目录
mkdir $BUILDDIR/tmp -p
cd $BUILDDIR/tmp
wget http://ftp.gnu.org/gnu/gcc/gcc-$GCC_VERSION/gcc-$GCC_VERSION.tar.xz
wget http://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS_VERSION.tar.xz
wget http://ftp.gnu.org/gnu/gmp/gmp-$GMP_VERSION.tar.xz
wget http://ftp.gnu.org/gnu/mpfr/mpfr-$MPFR_VERSION.tar.xz
wget http://ftp.gnu.org/gnu/mpc/mpc-$MPC_VERSION.tar.gz
wget https://gcc.gnu.org/pub/gcc/infrastructure/isl-$ISL_VERSION.tar.bz2
wget https://jaist.dl.sourceforge.net/project/mingw-w64/mingw-w64/mingw-w64-release/mingw-w64-v$MINGW_VERSION.tar.bz2
编译Binutils
cd $BUILDDIR/tmp
tar -xf binutils-$BINUTILS_VERSION.tar.xz
编译Binutils 2.37时,需要打补丁
wget https://raw.githubusercontent.com/StephanTLavavej/mingw-distro/main/binutils-fix-uint.patch
patch -p0 < binutils-fix-uint.patch
然后就可以编译安装
cd binutils-$BINUTILS_VERSION
./configure --prefix=$BUILDDIR --host=$TARGET --target=$TARGET --with-sysroot=$BUILDDIR --disable-multilib
make -j$(nproc) && make install
安装Mingw-w64头文件
可以直接把交叉编译器安装目录下的头文件复制过来
cp $CROSS_BUILDDIR/$TARGET/include $BUILDDIR/$TARGET/ -r
编译GCC
cd $BUILDDIR/tmp
tar -xf gcc-$GCC_VERSION.tar.xz
cd gcc-$GCC_VERSION
tar -xf ../mpfr-$MPFR_VERSION.tar.xz
mv -v mpfr-$MPFR_VERSION mpfr
tar -xf ../gmp-$GMP_VERSION.tar.xz
mv -v gmp-$GMP_VERSION gmp
tar -xf ../mpc-$MPC_VERSION.tar.gz
mv -v mpc-$MPC_VERSION mpc
tar -xf ../isl-$ISL_VERSION.tar.bz2
mv -v isl-$ISL_VERSION isl
进入新建的build目录,配置编译选项
mkdir build
cd build
../configure --prefix=$BUILDDIR --host=$TARGET --target=$TARGET --with-sysroot=$BUILDDIR --disable-multilib --disable-shared --enable-languages=c,c++ --enable-threads=posix --disable-win32-registry --enable-version-specific-runtime-libs --enable-fully-dynamic-string --enable-libgomp --enable-libssp --enable-lto
其中configure
选项--enable-languages=c,c++
定义启用的编程语言,--disable-shared
的作用是可以让GCC编译出的程序不需要libgcc.dll
等动态库就能运行,--enable-threads=posix
表示线程模型为posix。当目标平台为Windows时,默认的线程模型为win32,这里为了完整支持C++ std::thread
,需要将线程模型手动设置为posix。
因为编译器会在路径$BUILDDIR/mingw
下搜索Mingw-w64的头文件,所以需要创建一个符号链接
ln -s $TARGET $BUILDDIR/mingw
正式编译安装
make -j$(nproc) && make install
安装Mingw-w64的CRT和winpthreads
直接把交叉编译器安装目录下的库文件复制过来
cp $CROSS_BUILDDIR/$TARGET/lib/* $BUILDDIR/$TARGET/lib
打包发布
最后做一些工作来打包发布我们编译的Mingw-w64编译器。首先删除临时文件
cd $BUILDDIR/
rm -rf $BUILDDIR/tmp/
rm $BUILDDIR/mingw
用$TARGET-strip
命令来缩减体积可执行文件和库文件的体积
cd $BUILDDIR/
find -name "*.exe" -type f -exec $TARGET-strip -s {} ";" >& /dev/null
find -name "*.a" -type f -exec $TARGET-strip -d {} ";" >& /dev/null
find -name "*.o" -type f -exec $TARGET-strip -d {} ";" >& /dev/null
最后用7-Zip进行压缩打包。安装7-Zip的命令为
sudo apt install p7zip-full
打包命令为
cd $BUILDDIR/..
7z a -mx9 mingw-w64-gcc-posix_${GCC_VERSION}_x64-msvcrt-${MINGW_VERSION}.7z mingw64