交叉编译wxWidgets应用

众所周知wxWidgets是一个跨平台的GUI库,支持Linux(GTK/X11),Windows和macOS(cocoa),与Qt不同的是,他足够轻量,不需要魔改C++语言本身(qmake说的就是你),而且它调用平台原生API实现GUI,而Qt在Windows上实际上是绘制的界面,所以我打算用wxWidgets来做毕设。

众所周知Windows是现阶段的主流操作系统,而我用来写代码的电脑是mac,所以最终我可能仍然需要提供一个Windows版本的程序,但是我实在是不想在虚拟机上再折腾一套开发环境,所以就想着能不能直接在macOS或者Linux上编译出exe呢?答案是可以的,那就是mingw。

mingw(Minimalist GNU for Windows)是将GCC编译器和GNU Binutils移植到Win32平台下的产物,它是开源的软件,并且提供了macOS和Linux的版本,所以我们可以很容易的在macOS或者Linux上编译出exe。

接下来就是wxWidgets了,虽然官网提供了适用于mingw的预编译库,但是我自己测试发现不太能用,所以干脆直接从源码编译了。

教程

安装mingw-w64

首先需要安装mingw-w64,如果是macOS+Homebrew,那么可以直接brew

1
brew install mingw-w64

如果是Debian/Ubuntu,可以用apt安装,同时还要安装 gcc-multilib

1
apt-get install mingw-w64 gcc-multilib -y

下载wxWidgets源码并编译安装

建议从Github克隆仓库下来,因为我们只需要代码文件,不需要历史信息,所以可以加上 --depth 1 来减小仓库体积,以v3.1.5版本为例

1
git clone --branch v3.1.5 --depth 1 https://github.com/wxWidgets/wxWidgets.git && cd wxWidgets

然后我们进入 wxWidgets 目录,创建一个目录 build-win64 用于保存编译wx时产生的中间文件,以及 build-win64/install 存放最终的预编译库

1
mkdir -p build-win64/install && cd build-win64

我们进入了这个新创建的目录,现在需要运行wx的configure脚本,配置安装路径(--prefix $PWD/install)和交叉编译(--host x86_64-w64-mingw32,这是64位的,如果要编译32位的版本就使用i686-w64-mingw32),我们通常希望最后构建的exe能不需要其他依赖直接运行,所以动态库就没必要了(--disable-shared)。

最后的命令是

1
../configure --prefix $PWD/install --host x86_64-w64-mingw32 --with-msw --enable-unicode --disable-shared

等待configure完成,就可以执行make了

1
make -j4 # 4核处理器,如果你的电脑有更多核心的话建议指定更大的数字

我自己的mac上是跑了挺久的,不过我在我们工作室的48核服务器上编译只用了3分钟左右。

总之编译完成后就可以安装了,安装命令是

1
make install

我们之前把安装路径指定到了 build-win64/install ,它不是系统路径所以不需要root权限,但是需要注意的是因为没有安装到系统路径,所以像cmake这样的构建工具很可能找不到依赖,所以我们就需要用 wx-config 命令来生成编译参数。

编译wxWidgets应用

在上一步的 build-win64 目录中有一个 wx-config 程序,他和 pkg-config 很像,可以用来生成编译参数,比如我们的应用是 main.cpp ,那么可以这样

1
x86_64-w64-mingw32-g++ -o main.exe main.cpp -static `/path/to/wxWidgets/build-win64/wx-config --cxxflags --libs`

如果之前编译的32位版本那就把编译器换成i686-w64-mingw32-g++

如果没有问题的话会产生 main.exe,他可以直接放到Windows操作系统中运行。

使用资源文件

你可能会发现界面很丑,是Windows95的样式,如果你想要比较现代的界面,那么需要使用资源文件,wx提供了一个 wx.rc,用它就好了。

首先需要编译 wx.rc,用 windres 程序,这个程序包含在binutils里,之前可能没有安装,现在我们来安装他。

如果是macOS+Homebrew,可以直接brew

1
brew install x86_64-elf-binutils # 64位,如果是32位的话是i686-elf-binutils

如果是Debian/Ubuntu,可以用apt安装

1
apt-get install binutils-mingw-w64 -y

编译rc文件也很简单

1
x86_64-w64-mingw32-windres /path/to/wxWidgets/include/msw/wx.rc `/path/to/wxWidgets/build-win64/wx-config --cxxflags` -O coff wx.res

于是我们得到了 wx.res 文件,现在需要把他链接到程序里,这也很容易,首先我们在编译的时候先不要链接,而是编译到.o文件(注意命令加了个 -c

1
x86_64-w64-mingw32-g++ -o main.o -c main.cpp `/path/to/wxWidgets/build-win64/wx-config --cxxflags`

然后在链接这一步加入 wx.res

1
x86_64-w64-mingw32-g++ -o main.exe main.o wx.res -static `/path/to/wxWidgets/build-win64/wx-config --libs`

这样得到的 main.exe 就是带资源文件的,有一个wx默认的图标,并且界面风格也比较21世纪了。