wine + mingw 在macOS上生成exe可执行文件
背景
由于数据结构实验课需要将C++代码编译成exe文件提交,自己的Win本又过于笨重不想带到实验室里面去用,之前都是把cpp文件发给室友帮忙编译的,但是由于强迫症,我还是想在自己的电脑上编译((
前前后后用过很多种方法,试过用xmake这个构建工具来进行平台交叉编译,但是失败了;尝试过通过wine来运行Dev C来傻瓜式编译生成exe,虽然效果不错,但是总感觉不够优雅,而且Dev C这个软件也一百年都没更新过了,好多C++新特性都无法使用。于是我就萌生了一个想法:让Windows平台上的编译工具链通过wine运行在macOS上不就行了吗。于是就有了本文,由于捣鼓了好多天才弄出来,所以写一篇博客记录一下过程
PS:只适用于平时练习一下cpp题,对于有众多第三方库的项目未尝试过。
操作环境说明
由于Apple的M系列芯片采用了ARM架构,而wine又是为x86_64架构设计的,所以需要Rosetta转译运行
本文的运行环境是:MacBook Pro M3 Pro
如果你的运行环境差异很大,那么你就要根据自己实际的环境来进行配置,下面的内容仅供参考
安装wine
在macOS下使用homebrew可以很方便地安装wine
1 | brew install --cask wine-stable |
第一个命令来自homebrew官方
除了安装wine之外,我们还需要安装一个名为winetricks的包,这个包可以让我们自定义Windows层的一些功能,例如添加新的dll文件、更改系统字体、更改渲染方式等等。
在安装过程中homebrew可能会提示:
1 | wine-stable is built for Intel macOS and so requires Rosetta 2 to be installed. |
现在的日期时2024/10/23,在此时间及之后购买的MacBook Pro M3 芯片系列应该都已经预装了Rosetta 2,如果你不确定是否已经安装了Rosetta 2,你可以打开另一个终端,运行:
1 | arch -x86_64 zsh |
如果没有报错则说明已经安装了Rosetta 2
上面的命令实际上是打开了一个x86_64架构下的zsh终端
在homebrew的上述提示后会卡住一会,这个时候不要以为它执行失败了,实际上后台还在下载东西,静静等待即可
如果等了很久都没反应你可以先设置终端代理
安装完成后,运行以下命令检查是否安装成功(你可能重启终端):
1 | wine --version |
如果输出了版本号则说明安装成功
然后运行:
1 | winecfg |
这会打开一个图形化配置界面,实际上我们什么都不需要配置,直接点击OK(或者确定),即可完成wine的初始化
还有一些额外的针对字体的配置:
1 | winetricks wenquanyi |
前两行安装中文字体,防止显示中文时乱码,最后一行设置字体平滑,能让你的wine使用体验更加舒适
这时候你可以在网上去找几个小型的exe看看能不能运行,比如扫雷之类的,运行命令如下:
1 | wine your.exe |
如果能成功运行,那么你可以进行下一步啦!
安装MinGW
建议直接去 MinGW的Github官网 进行下载,我下载的是:
x86_64-14.2.0-release-win32-seh-msvcrt-rt_v12-rev0.7z
大家根据自己的需要进行下载
下载完毕后找一个位置解压它,随便什么位置都可以 (只要你能找到
配置运行命令
想要通过wine正确运行MinGW的GCC/G++编译器,需要一大堆环境变量,我建议将这一整个命令以别名的形式写在你的Shell配置文件中,macOS Sonoma 默认使用Zsh终端,所以我在 ~/.zshrc 中加入了以下代码:
1 | # 编译 exe 文件 |
可以看到确实很长(((
我们来解释一下里面的环境变量都应该怎么填
- COLLECT_LTO_WRAPPER: 这个变量要填写你的MinGW安装目录中的
lto-wrapper.exe
的路径 - COLLECT_GCC: 填写MinGW安装目录中的bin文件夹中的
g++.exe
的路径 - C_INCLUDE_PATH: 这个变量指定C程序编译时的include目录,注意这个地方一定要指定,否则将会采用Xcode中的include目录,这样你在编译时就会看到一堆找不到对象的错误!该目录的位置仍然在MinGW的安装位置中,请自行寻找
- CPLUS_INCLUDE_PATH: 指定C++程序编译时的include目录,和C_INCLUDE_PATH同理
配置了这一堆环境变量后,就是命令的主角 wine 了:
1 | wine /Users/graftcopolymer/mingw64/bin/g++.exe -B /Users/graftcopolymer/mingw64/bin/ -static |
首先就是编译器的可执行文件,我们使用wine来执行编译器进行编译
然后我们需要指定 -B
参数,这个参数指定了编译器的进行编译时所用的汇编器 as.exe
和链接器 ld.exe
的目录,这两个exe一般是放在同一个文件夹的,所以我们只需要指定一个目录就行了,如果你不指定就会报链接器错误,因为会使用Xcode提供的链接器(( 可恶的Xcode
注意在指定目录时一定要加上一个尾随斜杠,告诉g++.exe这是一个目录
然后就是 -static
参数,这个参数让编译器使用静态链接,即将所需要的所有依赖库都打包在同一个exe文件中,否则你就必须要将一大堆dll
文件复制到你编译出来的exe文件的同目录下才能运行,但是这样也有缺点,就是编译出来的exe文件很大,大概会多出12MB左右,如果引用的库比较多会更大,这个由大家自己取舍
测试
1 | mkdir -p ~/cpp_code |
用上述命令创建一个cpp文件,编辑后保存退出vim
然后使用:
1 | mingw-exe -o hello.exe hello.cpp |
这一步如果提示mingw-exe不是命令或者不存在,重启一次终端应该就没问题了
即可编译出一个exe文件,运行exe文件:
1 | wine hello.exe |
如果成功输出就成功了!
把这个exe拿到Windows上去也是可以正常运行的