我们在*nix或者Mac系统中做开发会经常使用Makefile来组织构建规则,然后使用make来构建项目。
Makefile可以手动编写,也可以使用工具生成。生成Makefile的工具还是比较多的,目前比较常用的跨平台的Makefile生成工具要算CMake了。CMake非常强大,可以生成很多类型的Makefile或者工程文件,可以通过下面的指令来查看具体的可生成的文件。
cmake --help
随着Mingw、MSYS2、cygwin这些Linux移植系统在Windows上的出现,Windows上也可以在这些移植系统中使用Makefile来构建项目了。
在说这几个系统中Makefile的差别之前,先说一下这几个系统:
-
Cygwin
Cygwin是Windows(Win32子系统)之上的POSIX平台,以用户模式运行。它在运行时需要POSIX兼容层(Cygwin提供了一个称为的运行时库的cygwin1.dll)。它不模拟Linux,与WSL不同。 -
MSYS、MSYS2
MSYS2是对MSYS的独立重写,其基于现代Cygwin和MinGW-w64,目的是与本机Windows软件实现更好的互操作性。它在运行时也需要一个POSIX兼容层(MSYS2提供了运行时库msys-2.0.dll)。可以随便找一个msys2系统/usr/bin中的程序查看依赖都可以发现需要依赖msys-intl-8.dll和msys-2.0.dll。
-
Mingw
Mingw包括MinGW32与MinGW64,是Windows的Native应用,即是Windows的本机应用,它与使用MSVC编译的程序一样。可以随便找一个mingw中的程序查看依赖,都不会有像msys-2.0.dll这样的中间层依赖。
这些系统都是从Linux中移植过来的,由于Windows系统的设计与Linux系统的设计有一些冲突,最明显的就是路径分隔符了。
Linux下的路径分隔符为/
,不能使用\
,\
与C语言一样,是作为转义字符存在的:
而Windows下的路径分隔符为\
,虽然Windows下在大多数情况下也可以使用/
,但命令行cmd.exe中不行,比如:
正是由于这个问题才导致了Makefiles的差异:
在MSYS、MSYS2与Cygwin系统中,由于是模拟的Linux,Shell为sh,所以其使用的路径分隔符与Linux一致为/
;而MinGW32、Mingw64之类的Mingw系统是采用的Windows本机的机制,Shell为cmd.exe,所以使用的是\
。
可以比较使用cmake生成的MSYS Makefiles、 MinGW Makefiles与Unix Makefiles的文件的差异:
下面是MSYS Makefiles与MinGW Makefiles的差异:
可以看到MSYS的SHELL使用的是/bin/sh,而MinGW的SHELL使用的是cmd.exe。
正是因为使用的SHELL的不同,所以导致其路径的表示也不同:
MSYS中路径分隔符使用的/
,Windows的磁盘分区是通过挂载到根目录/
来表示的,比如G:盘,在MSYS中使用/g来表示。
Mingw中路径分隔符使用的\
,Windows的磁盘分区还是按Windows本身的表示方法来表示。
再比较一下MSYS Makefiles与Unix Makefiles的差异:
可以看到使用的SHELL是没有不同的,唯一不同的就是Windows下的磁盘表示,由于Linux/Unix下根本就不会有Windows下的磁盘盘符存在,所以Unix Makefiles不会处理Windows下的磁盘盘符,还是原样表示。而MSYS本身就是运行在Windows平台下的Linux模拟,所以它需要处理Windows下的磁盘盘符问题。
既然Makefile文件有差别,那使用的make程序也有所不同,否则会出现各种莫名其妙的问题:
MinGW Makefiles需要使用Mingw系统中的mingw32-make.exe来构建。
MSYS Makefiles与Windows下的Unix Makefiles需要使用MSYS系统中/usr/bin/make.exe来构建。