2020-03-25 | 研究与探索 | UNLOCK

Windows 上的编译系统

最近我在 改造 EGE 的编译系统, 这是我第一次实践写 CMake,整个项目其实比较简单,几个 C++ 文件和 lpng 目录下的 C 文件全部编译链接就行,没有第三方库。但是 EGE 有很重的“跨平台”需求,这里“跨平台”打引号是因为 EGE 目前只支持 Windows 系统,跨的平台是编译器平台,包括各个版本的 MSVC 和各个版本的 MinGW。

在此过程中我深深体会到了 CMake 的给力,踩的坑主要是编译器上的,比如 MSVC 的 /ML/MT/MD 三个参数,MinGW 和 MSVC 各自支持 stdint.h 的最低版本之类。我还了解到一些之前不知道的关于编译系统的事。

在命令行输入 cmake -G 可以看到 CMake 在 Windows 下有几种不同的 Makefile 目标:MSYS MakefilesMinGW MakefilesUnix MakefilesNMake Makefiles,其中 Unix Makefiles 可以顾名思义,但其它的我就分不清楚有什么区别,想生成 MinGW Makefiles 说我路径上有 sh.exe,不行,想生成 MSYS Makefiles 又在调用 CreateProcess 时报错。我研究了一下,发现在 Windows 上搞 GNU 风格的开发时有两种 make 程序,一种是 MinGW 自带的 mingw32-make,一种是 MSYS 项目下的 make,后者和 Unix 上的原版 make 更像。mingw32-make 和 MSYS 的 make 的主要区别就是 mingw32-make 只能处理 Windows 式的路径如 D:\Code\main.cpp,而 MSYS 的 make 就能进行相应的转换。之前我都是把 mingw32-make.exe 重命名成 make.exe 然后直接用的,还奇怪它为啥不直接叫 make.exe。另一方面我之前为了方便直接把我 git-bash 的 bin 目录添加到了 PATH 里,这也是不合规矩的。

相应地,CMake 的两种 Makefile 目标就对应两种 make 程序,在 CMD 和 PoweShell 下应该生成 MinGW Makefiles,在 MSYS 下应该生成 MSYS Makefiles

NMake Makefiles 则是我在支持 EGE 的 VC6 版本时了解的。EGE 还支持 VC6,主要是因为还有相当数量的老师要求学生使用 VC6 学习 C++。CMake 自从 3.7 之后就停止了对 VC6 项目的支持,也就是说不能直接生成 VC6 可以直接打开的 .dsw 工作空间文件和 .dsp 项目文件了,但我们不必为了支持 VC6 而安装旧版本 CMake,因为 CMake 还有 NMake Makefiles 目标。

不得不说,MSVC 虽然辣鸡,但微软作为技术公司的责任还是有的,比如包括 VC6 在内的所有 MSVC 都能通过 _MSC_VER 宏定义来判断版本,MSVC 工具链在 VC6 即支持一键配置命令行环境——VC98\Bin 下的 VCVARS32.BAT 脚本。MSVC 除了在 IDE 里使用、用项目文件作为命令行配置这两种用法外,还有一种较少被使用的、更接近 Unix 的方法,就是使用 nmake 程序。nmakemake 类似,是 MSVC 自带的编译工具,也是 CMake 支持的编译系统目标,这样想要生成 VC6 版本的二进制文件,我们只需要用 VCVARS32.BAT 配置 VC6 命令行环境,CMake 目标参数使用 -G "NMake Makefiles" 就行了。不仅是 VC6,一直到 VS2019 的其它版本 MSVC 也支持 NMake 编译。