在Linux上创建Mingw-w64交叉编译器

hamster 2021-05-07 PM 615℃ 0条

这篇文章记录了在Linux上通过源码编译安装Mingw-w64交叉编译工具链的步骤。Mingw-w64主要包括Binutils工具、GCC编译器、C Runtime (CRT)以及相应的头文件,在Linux系统上的Mingw-w64可以通过交叉编译生成Windows平台的可执行文件,其CRT的目标平台也是Windows。在Linux上安装Mingw-w64交叉编译工具链之后,不需要有Windows环境,就可以将GNU/Linux系统下的很多软件移植到Windows系统上。编译32位工具链和64位工具链的命令稍有不同,在文中有相应说明。

开发环境搭建

开发环境可以在任意主流Linux发行版上搭建。以Debian Buster为例,我们通过apt命令安装基本开发环境

sudo apt install g++ autoconf automake make patch autopoint bison gawk texinfo

准备工作

为了方便,设置环境变量

export TARGET=x86_64-w64-mingw32
export BUILDDIR=$HOME/mingw64-cross
export GCC_VERSION=11.1.0
export MINGW_VERSION=9.0.0

其中TARGET表示目标平台,BUILDDIR为安装目录,GCC_VERSION表示GCC版本,MINGW_VERSION表示Mingw-w64版本。

如果要编译32位的工具链,应该把TARGETBUILDDIR设置为

export TARGET=i686-w64-mingw32
export BUILDDIR=$HOME/mingw32-cross

下载需要的源代码

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-2.36.1.tar.xz
wget http://ftp.gnu.org/gnu/gmp/gmp-6.2.1.tar.xz
wget http://www.mpfr.org/mpfr-4.1.0/mpfr-4.1.0.tar.xz
wget https://ftp.gnu.org/gnu/mpc/mpc-1.2.1.tar.gz
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-2.36.1.tar.xz
cd binutils-2.36.1
./configure --prefix=$BUILDDIR --target=$TARGET --with-sysroot=$BUILDDIR --disable-multilib
make && make install

安装Mingw-w64头文件

cd $BUILDDIR/tmp
tar -xf mingw-w64-v$MINGW_VERSION.tar.bz2
cd mingw-w64-v$MINGW_VERSION/mingw-w64-headers
./configure --prefix=$BUILDDIR/$TARGET --host=$TARGET
make && make install

编译gcc-core

cd $BUILDDIR/tmp
tar -xf gcc-$GCC_VERSION.tar.xz
cd gcc-$GCC_VERSION
tar -xf ../mpfr-4.1.0.tar.xz
mv -v mpfr-4.1.0 mpfr
tar -xf ../gmp-6.2.1.tar.xz
mv -v gmp-6.2.1 gmp
tar -xf ../mpc-1.2.1.tar.gz
mv -v mpc-1.2.1 mpc
mkdir build
cd build
../configure --prefix=$BUILDDIR --target=$TARGET --with-sysroot=$BUILDDIR --disable-multilib --disable-shared --enable-languages=c,c++ --enable-threads=posix

其中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

因为还没有可用的CRT,libstdc++等库文件无法编译,目前我们只能编译gcc-core

make all-gcc && make install-gcc

至此,用于交叉编译的GCC核心编译器已经安装完成,打印其版本信息

$BUILDDIR/bin/$TARGET-g++ -v

输出信息为

使用内建 specs。
COLLECT_GCC=x86_64-w64-mingw32-g++
COLLECT_LTO_WRAPPER=/home/cat/mingw64-cross/libexec/gcc/x86_64-w64-mingw32/11.1.0/lto-wrapper
目标:x86_64-w64-mingw32
配置为:../configure --prefix=/home/cat/mingw64-cross --target=x86_64-w64-mingw32 --with-sysroot=/home/cat/mingw64-cross --disable-multilib --disable-shared --enable-languages=c,c++ --enable-threads=posix
线程模型:posix
Supported LTO compression algorithms: zlib
gcc 版本 11.1.0 (GCC)

编译Mingw-w64的CRT

现在可以用刚才生成的GCC交叉编译器生成目标平台为Mingw-w64的CRT。先把交叉编译器的路径加入环境变量

export PATH=$BUILDDIR/bin:$PATH

编译安装CRT

cd $BUILDDIR/tmp/mingw-w64-v$MINGW_VERSION/mingw-w64-crt/
./configure --prefix=$BUILDDIR/$TARGET --host=$TARGET --with-sysroot=$BUILDDIR/$TARGET --enable-lib64 --enable-lib32=no
make && make install

其中configure选项--enable-lib64 --enable-lib32=no的含义是只编译64位的CRT。编译32位的工具链时,configure选项应改为

./configure --prefix=$BUILDDIR/$TARGET --host=$TARGET --with-sysroot=$BUILDDIR/$TARGET --enable-lib64=no --enable-lib32

编译winpthreads

因为GCC编译器的线程模型为posix,所以还需要编译Mingw-w64提供的winpthreads库。

cd $BUILDDIR/tmp/mingw-w64-v$MINGW_VERSION/mingw-w64-libraries/winpthreads/
./configure --prefix=$BUILDDIR/$TARGET --host=$TARGET --with-sysroot=$BUILDDIR/$TARGET --enable-shared=no --enable-static
make && make install

继续编译GCC

现在可以编译完整的GCC编译器

cd $BUILDDIR/tmp/gcc-$GCC_VERSION/build
make && make install

最后要做的一点事情

把编译Mingw-w64的临时目录暂时复制到用户家目录,以后编译Mingw-w64本地编译器还用得到

cp -r $BUILDDIR/tmp/mingw-w64-v$MINGW_VERSION ~

删除临时文件

cd $BUILDDIR/
rm -rf $BUILDDIR/tmp/*
rm $BUILDDIR/mingw

strip命令减小可执行文件和库文件的体积

cd $BUILDDIR/
find -executable -type f -exec strip -s {} ";" >& /dev/null
find $TARGET -name "*.a" -type f -exec $TARGET-strip -d {} ";" >& /dev/null
find $TARGET -name "*.o" -type f -exec $TARGET-strip -d {} ";" >& /dev/null

把编译Mingw-w64的临时目录移动回来

mv ~/mingw-w64-v$MINGW_VERSION $BUILDDIR/tmp/

在文件.bashrc中把交叉编译器的路径加入到环境变量,方便以后使用

echo 'export PATH=$PATH:$HOME/mingw64-cross/bin' >> ~/.bashrc

对于32位的工具链,应该执行命令

echo 'export PATH=$PATH:$HOME/mingw32-cross/bin' >> ~/.bashrc
标签: GCC, Mingw-w64

非特殊说明,本博所有文章均为博主原创。

评论啦~