GNU

GNU 是一个操作系统项目, 名字是 GNU’s Not Unix! 的缩写。

Unix 系统被发明之后,开始收费和商业闭源了。RMS 发起 GNU 计划,模仿 Unix 的界面和使用方式,从头做一个开源的版本。然后他自己做了编辑器 Emacs 和编译器 GCC。GNU 是一个计划或者叫运动。在这个旗帜下成立了 FSF,起草了 GPL 等。

接下来大家纷纷在 GNU 计划下做了很多的工作和项目,基本实现了当初的计划。包括核心的 gcc 和 glibc。但是 GNU 系统缺少操作系统内核。原定的内核叫 HURD,一直完不成。同时 BSD(一种 UNIX 发行版)陷入版权纠纷,x86 平台开发暂停。然后一个叫 Linus 的同学为了在 PC 上运行 Unix,在 Minix 的启发下,开发了 Linux。

Linux 只是一个系统内核,系统启动之后使用的仍然是 gcc 和 bash 等软件。Linus 在发布 Linux 的时候选择了 GPL,因此符合 GNU 的宗旨。最后,大家突然发现,这玩意不正好是 GNU 计划缺的么。于是合在一起打包发布叫 GNU / Linux。然后大家念着念着省掉了前面部分,变成了 Linux 系统。实际上 Debian,RedHat 等 Linux 发行版中内核只占了很小一部分容量。

事实上,整个GNU计划开发出了除了操作系统内核以外的所有工具: GNU编译器套装(GCC)、GNU的C库(glibc)、以及GNU核心工具组(coreutils),另外也是GNU除错器(GDB)、GNU二进制实用程序(binutils)的GNU Bash shell中 和GNOME桌面环境。

不同平台的编译器

  • Windows 的 msvc (VS自带)

  • Mac 的 clang (Xcode提供,apple出品),经过 gcc -> LLVM -> clang 变迁

  • Linux 的 gcc (GNU出品),gcc 全称 GNU C Compiler

  • 古董Unix上有 cc 或者 gcc

MinGW

MinGW,即 Minimalist GNU For Windows,也就是 Win 版的 GCC。它是一些头文件和端口库的集合,该集合允许人们在没有第三方动态链接库的情况下使用 GCC(GNU Compiler C)产生 Windows32 程序。

实际上 MinGW 并不是一个 C/C++ 编译器,而是一套 GNU 工具集合。除开 GCC (GNU 编译器集合) 以外,MinGW 还包含有一些其他的 GNU 程序开发工具 (比如 gawk bison 等等)。

开发 MinGW 是为了那些不喜欢工作在 Linux(FreeBSD) 操作系统而留在 Windows 的人提供一套符合 GNU 的 GNU 工作环境。

MSYS2

MinGW 用来跨平台开发,MingW 也有一个叫 MSys(Minimal SYStem)的子项目,主要是提供了一个模拟 Linux 的 Shell 和一些基本的 Linux 工具。因为编译一个大型程序,光靠一个 GCC 是不够的,还需要有 Autoconf 等工具来配置项目,所以一般在 Windows 下编译 ffmpeg 等 Linux 下的大型项目都是通过Msys 来完成的,当然 Msys 只是一个辅助环境,根本的工作还是 MingW 来做的。

MinGW 编译出的程序

首先 MingW 不能让 Linux 下的程序直接运行在 Windows 上,必需通过源代码重新编译。

现代操作系统包括 Windows 和 Linux 的基本设计概念像进程线程地址空间虚拟内存这些都是大同小异的,之所以二者上的程序不能兼容,主要是它们对这些功能具体实现上的差异,首先是可执行文件的格式,Window 使用 PE 的格式,并且要求以 .EXE 为后缀名。Linux 则使用 Elf。其次操作系统的 API 也不一样,如 Windows 用 CreateProcess() 创建进程,而 Linux 使用 fork()。

MingW 有专门的 W32api 头文件,来把代码中 Linux 方式的系统调用替换为对应的 Windows 方式。

原理

让 Window 下的编译器把诸如 fork 的调用翻译成等价的形式,这就是 MingW 的做法。MingW 生成的程序,全部使用从 KERNEL32 导出的标准 Windows 系统 API(内部修改了编译器的实现代码写着是 fork 编译出来变成 CreateProcess )。

Cygwin

MinGW 允许人们在没有第三方动态链接库的情况下使用 GCC 产生 Windows32 程序,而 Cygwin 修改库,让 Window 提供一个类似 UNIX 提供的库,他们对程序的接口如同 UNIX 一样,而这些库,当然是由 win32 的 API 实现的,这就是 Cygwin 的做法。

Cygwin 最后的程序中源代码写着是 fork 实际上生成的程序还是 fork,但是 fork 函数 Cygwin 通过动态链接库实现了。

MSVC

1、大部分跨平台的大型C程序(如ffmpeg)早已完全使用C99标准编写,而msvc的编译器CL直到2015年才较好地支持了C99;

2、msvc的侧重点是对C++标准的支持以及对Windows SDK的支持,而不是对C语言的支持。

3、msvc的编译器很难用于生成和环境无关的代码(并不是不能,不过可能涉及到运用老版本和汇编器),用来编译像Bootloader、系统内核之类的特殊程序时会有麻烦。

4、msvc的编译器CL的命令行参数和gcc、clang等几乎完全不兼容,所有的makefile和其他脚本都必须专门为其做较大改动。

5、msvc工具链(编译器、链接器、nmake等)的ABI和gnu工具链的只有单向兼容,无法链接由gnu工具链生成的库。