Cygwin
Cygwin,原Cygnus出品(已被红帽收购),目前是RedHat名下的项目。项目的目的是提供运行于Windows平台的类Unix环境(以GNU工具为代表)。为了达到这个目的,Cygwin提供了一套抽象层dll,用于将部分Posix调用转换成Windows的API调用,实现相关功能。这里面最典型的,最基本的模拟层就是那个cygwin1.dll。除此之外,随着Linux系统的发展壮大,目前的Cygwin已经不仅仅提供POSIX兼容,因此也顺带多了更多模拟层的依赖关系。Cygwin的主要目的是通过重新编译,将POSIX系统(例如Linux、BSD,以及其他Unix系统)上的软件移植到Windows上。
Cygnus当初首先把gcc,gdb,gas等开发工具进行了改进,使他们能够生成并解释win32的目标文件。然后,他们要把这些工具移植到windows平台上去。一种方案是基于win32api对这些工具的源代码进行大幅修改,这样做显然需要大量工作。因此,他们采取了一种不同的方法,他们写了一个共享库(就是cygwindll),把win32api中没有的unix风格的调用(如fork,spawn,signals,select,sockets等)封装在里面,也就是说,他们基于win32api写了一个unix系统库的模拟层。这样,只要把这些工具的源代码和这个共享库连接到一起,就可以使用unix主机上的交叉编译器来生成可以在windows平台上运行的工具集。以这些移植到windows平台上的开发工具为基础,cygnus又逐步把其他的工具(几乎不需要对源代码进行修改,只需要修改他们的配置脚本)软件移植到windows上来。这样,在windows平台上运行bash和开发工具、用户工具,感觉好像在unix上工作。
Cygwin的目录结构基本照搬了linux的样子,但同时,也兼容了Windows的许多功能:大部分应用使用Unix风格的路径,Windows的盘符通过类似挂载点的方式提供给Cygwin使用;Cygwin中既可以运行Cygwin的应用(依赖模拟层),又可以运行Windows应用,而传递给应用的路径会经过它的模拟层变换,以此保证程序运行不会出错。
由于它的模拟层实现了相当良好的Posix兼容,人们试着将许多重要的Linux/BSD应用移植到了Cygwin下,使得Cygwin越来越大,功能也越来越丰富,以至于目前很多人直接把将Linux应用移植到Windows平台的任务都交给了Cygwin(当然,这种移植并非原生)。
Cygwin是运行于Windows平台的POSIX”子系统”,提供Windows下的类Unix环境,并提供将部分Linux应用”移植”到Windows平台的开发环境的一套软件。cygwin官方的一个定义是Cygwin is not a way to run native linux apps on Windows. You have to rebuild your application from source if you want it to run on Windows。cygwin不是让linux程序能在windows上运行的方法,如果你想要让linux程序能在windows运行,那么你只有用cygwin来重新编译一下源文件。这句话完全反驳了无缝运行在linux的说法。就是说你在linux上编译的elf程序不能直接拿到cygwin上运行,同样,你用cygwin编译的程序也不是linux的elf格式,而是exe格式,exe是无法在linux上运行的。
MinGW
MinGW,Minimalist GNU for Windows,用于开发原生(32位)Windows应用的开发环境。它主要提供了针对win32应用的GCC、GNU binutils等工具,以及对等于Windows SDK(的子集)的头文件和用于MinGW版本linker的库文件(so、a等,而不是VC的lib)。
在基本层,MinGW是一组包含文件和端口库,其功能是允许控制台模式的程序使用微软的标准C运行时间库(MSVCRT.DLL),该库在所有的NT OS上有效,在所有的Windows 95发行版以上的Windows OS有效,使用基本运行时间,你可以使用GCC写控制台模式的符合美国标准化组织(ANSI)程序,可以使用微软提供的C运行时间扩展。该功能是Windows 32 API不具备的。下一个组成部分是w32api包,它是一组可以使用Windows 32 API的包含文件和端口库。与基本运行时间相结合,就可以有充分的权利既使用CRT(C Runtime)又使用Windows 32 API功能。
MinGW能够替代cl用于编译不包含MFC的、以WinSDK为主的Windows应用,并且编译出来的应用不依赖于第三方的模拟层支持,其运行时为大部分Windows标配的msvcrt(故称原生Windows应用)。除此之外,MinGW也支持GCC支持的其他语言。因为这些原因,MinGW被许多Linux上发展起来的开发工具选择为Windows版本的默认编译器,例如Code:Blocks,例如DevC++。
MinGW是从Cygwin(1.3.3版)基础上发展而来。
前面提到的MinGW,是针对32位Windows应用开发的。而且由于版本问题,不能很好的支持较新的Windows API。MinGW-W64则是新一代的MinGW,支持更多的API,支持64位应用开发,甚至支持32位host编译64位应用以及反过来的”交叉”编译。除此之外,它本身也有32位和64位不同版本,其它与MinGW相同。
MSys
MSYS的全称叫Minimal SYStem,是MinGW的一个子系统,Unix-like command line utilities,是一套运行在Windows上的bash,包括基本的bash, make, gawk and grep等等。也就是运行在Win上的Linux Terminal。通常也可以认为是小型的UNIX on Windows。提供在windows上模拟Unix环境来使用MinGW。这个比较好理解,其实就是在Win上使用Linux的命令行进行操作,可以代替cmd来使用。对一些GNU的开源软件,MSYS可能是必需的,因为它们通常需要./configure然后make才能运行。
编译一个大型程序,光靠一个GCC是不够的,还需要有Autoconf等工具来配置项目,所以一般在Windows下编译ffmpeg等Linux下的大型项目都是通过Msys来完成的,当然Msys只是一个辅助环境,根本的工作还是MingW来做的。
与Cygwin的大而全不同,MSYS是冲着小巧玲珑的目标去的,所以整套MSYS以及MinGW,主要以基本的Linux工具为主,大小在200M左右,并且没有多少扩展能力。MSYS是用于辅助Windows版MinGW进行命令行开发的配套软件包,提供了部分Unix工具以使得MinGW的工具使用起来方便一些。如果不喜欢庞大的Cygwin,而且使用不多,可以试试。不过喜欢完整体验、不在乎磁盘占用等等,还是推荐Cygwin而不是MSYS。
由于MinGW万年不更新,MSYS更是,Cygwin的许多新功能MSYS没有同步过来,于是Alex等人建立了新一代的MSYS项目。仍然是fork了Cygwin(较新版),但有个更优秀的包管理器pacman,有活跃的开发者跟用户组,有大量预编译的软件包(虽然肯定没有Cygwin多)……对于不喜欢庞大的Cygwin的用户而言,推荐试试msys2。
MSYS2(Minimal SYStem 2)是一个MSYS的独立改写版本,主要用于shell命令行开发环境。同时它也是一个在Cygwin(POSIX兼容性层)和MinGW-w64(从”MinGW-生成”)基础上产生的,追求更好的互操作性的Windows软件。MSYS2是MSYS的一个升级版,准确的说是集成了pacman和Mingw-w64的Cygwin升级版,提供了bash shell等linux环境、版本控制软件(git/hg)和MinGW-w64工具链。与MSYS最大的区别是移植了Arch Linux的软件包管理系统Pacman(其实是与Cygwin的区别)。
Cygwin、MinGW、MSys比较
特点 | Cygwin | MinGW/MSYS | MSYS2 |
是否GNU | 否 | 是 | 是 |
更多软件支持? | 支持绝大多数的 GNU 软件 | 支持常用软件,git、Vim 等软件需要独立支持(详细介绍见下方) | 支持大多数 GNU 软件 |
更类 Linux? | Cygwin 在 Windows 中就好像 Wine 在 Linux 中 | 实现了 Bash 等主要的 Linux 程序 | 原生 64/32bit 支持 |
GCC 编译 | 内含 MingGW32 交叉编译功能,既支持依赖 cygwin1.dll 的程序编译,也支持独立的 Windows 程序编译;可以直接编译 Linux 下的应用程序 | 支持独立的 Windows 程序编译 | 支持独立的 Windows 程序编译 |
中文支持 | 直接支持中文显示和输入法 | 需要配置才能支持中文显示和输入,删除一个中文字符需要删除 2 次 | 支持中文显示和输入法,中文帮助系统和中文提示(部分软件) |
运行速度 | 慢 | 快 | 快 |
Unix 下编译通过的 C 代码在 win32 下编译是不能通过的,Unix 和 win32 的 API 都是符合标准 C,大多数函数调用在 unix 和 win32 下是相同的。但 unix 有自己一些独特的 API(如 fork, spawn, signals, select, sockets 等)如果代码中使用了这些 API 在 win32 下当然找不到对应的库。
区别总结:
- 修改编译器,让 window 下的编译器把诸如 fork 的调用翻译成等价的形式,这就是 mingw 的做法。
- 修改库,让 window 提供一个类似 unix 提供的库,他们对程序的接口如同 unix 一样,而这些库当然是由 win32 的 API 实现的,这就是 cygwin 的做法。
MingW 和 cygwin 都不能让 Linux 下的程序直接运行在 Windows 上,必需通过源代码重新编译。主要是它们对这些功能具体实现上的差异:
- 可执行文件的格式,Window 使用 PE 的格式,并且要求以 .EXE 为后缀名。Linux 则使用 Elf
- 操作系统的 API 也不一样,如 Windows 用 CreateProcess() 创建进程,而 Linux 使用 fork()
cygwin/gcc 完全可以和在 linux 下的 gcc 化做等号,这个可以从 boost 库的划分中可以看出来端倪,cygwin 下的 gcc 和 linux 下的 gcc 完全使用的是相同的 Toolsets。所以完全可以和 linux 一起同步更新 gcc 版本,而不用担心问题,并且在 cygwin/gcc 做的东西(不用 win32 的)可以无缝的用在 linux 下,没有任何问题。是在 windows 下开发 linux 程序的一个很好的选择。但是在 cygwin/gcc 下编译出来的程序,在 windows 执行必须依赖 cygwin1.dll,并且速度有些慢,如果不想依赖这个东西的化,必须在 gcc 的编译选项中加入 -mno-cygwin。加入这个选项其实 gcc 编译器就会自动的选择在安装 cygwin/gcc 时安上的 mingw, 这个 mingw 就是 gcc 的一个交叉编译。
MinGW 相比 CygWin/gcc 来讲,更加贴近 win32。因为它几乎支持所有的 Win32API。它所连接的程序,不需要任何第三方库即可运行。CygWin/gcc,其实这是两个东西。CygWin 是一个让 Windows 拥有 Unix-like 环境的软件。而 gcc 就是安装在 CygWin 上的编译器。
二者生成的程序都是能在 Windows 上运行的 EXE 文件,都是 PE 格式,用一个 PE 格式查看工具检查一下就能发现,Cygwin 生成的程序依然有 fork() 这样的 Linux 系统调用,但目标库是 cygwin1。而 MingW 生成的程序,则全部使用从 KERNEL32 导出的标准 Windows 系统 API。这样看来用 Mingw 编译的程序性能会高一点,而且也不用带着那个接近两兆的 cygwin1.dll 文件。但 Cygwin 对 Linux 的模拟比较完整,甚至有一个 Cygwin X 的项目,可以直接用 Cygwin 跑 X。另外 Cygwin 可以设置 -mno-cygwin 的 flag,来使用 Mingw 编译。而与 Cygwin 更有可比性的 MSys 上的工具也是通过 Cygwin 这种模拟的方式来提供。
Cygwin、MinGW、MSys 如何选择?
如果在 windows 开发 linux 程序,cygwin 是很好的选择。如果你开发的程序不介意有一个 cygwin1.dll 的话,也是可以选择 cygwin 的。如果你是想开发 windows 下的程序,还要必须用 gcc 的话,mingw 是很好的一个选择。总起来说,在 Windows 系统下,还是用 VC 编译比较合适,没办法的情况下才会选择 MinGW。
WSL
WSL全称为 Windows Subsystem for Linux,是一个为在 Windows 10 上能够原生运行 Linux 二进制可执行文件(ELF 格式)的兼容层。
Windows Subsystem for Linux 有什么用?跟虚拟机有什么区别?
相对于虚拟机,Windows Subsystem for Linux 有以下优点:
- 性能更好。由于实现更加底层,所以性能要比虚拟机好很多。
- 与 Windows 共享的文件系统。子系统是可以直接访问硬盘中的所有文件的,甚至可以执行 .exe 文件。
总结:WSL 是终极解决方案。