最近我在 改造 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 Makefiles
、MinGW Makefiles
、Unix Makefiles
和 NMake 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
程序。nmake
和 make
类似,是 MSVC 自带的编译工具,也是 CMake 支持的编译系统目标,这样想要生成 VC6 版本的二进制文件,我们只需要用 VCVARS32.BAT
配置 VC6 命令行环境,CMake 目标参数使用 -G "NMake Makefiles"
就行了。不仅是 VC6,一直到 VS2019 的其它版本 MSVC 也支持 NMake 编译。