在整个大学的学习过程中,经常在各种编程环境配置中遇到诸如GNU的gcc/g++、LLVM的clang/clang++、Windows的Mingw/MSVC、还有CMake。
本文希望能捋一捋这些名词之间的关系,这将有助于理解各种环境配置中的各种操作,并且能对程序运行本身有更为深入的理解。
老生常谈
在开始之前我们先放一段Hello World:hello.c
#include <stdio.h>
int main()
{
printf("Hello World");
return 0;
}
然后就是一段老生常谈的描述了:
要想让这段代码在Linux上运行,我们需要使用GCC
- 预编译:将hello.c和stdio.h预编译为hello.i
- 编译:将hello.i编译为hello.s
- 汇编:将hello.s翻译为机器指令hello.o(.o目标文件)
- 链接:链接各种需要的库和其他目标文件(该hello程序不需要)得到可执行文件hello.out(相当于windows的.exe)
整个过程将高级语言翻译成了机器语言,而编译器,就是这样的一个工具。GCC可以完成从预编译编译,汇编,链接整个过程。
但是平时使用Visual Studio等软件时并没有接触到这个过程,因为VS是高度集成开发环境(IDE、Integrated Development Environment),集成了代码编辑器,编译器,调试器和图像化用户界面,上述所有程序编译和链接过程都用一步build构建带过了。
GNU的GCC/G++
首先GNU是什么呢,GNU计划,又称革奴计划,是由Richard Stallman在1983年9月27日公开发起的。它的目标是创建一套完全自由的操作系统。因为当时1969年在贝尔实验室诞生的Unix是商业操作系统。
而Stallman发起GNU计划的目的之一,就是"重现当年软件界合作互助的团结精神",而为保证GNU软件可以自由地"使用、复制、修改和发布",所有GNU软件都有一份在禁止其他人添加任何限制的情况下授权所有权利给任何人的协议条款,GNU通用公共许可证(GNU General Public License,GPL)。
看到这就知道了吧,Stallman便是开源运动的先驱。而他最初的目标"创建一套完全自由的操作系统"也实现了,就是GNU/Linux,简称Linux!
Gnu英文愿意就是非洲牛羚,所以它的头像也是如此。
Linux 内核最初是由Linus Torvalds在赫尔辛基大学读书时出于个人爱好而编写的,第一版于1991年发布,当时仅1W行代码。1992年Linux与其他GNU软件结合(自然包括GCC),完全自由的操作系统正式诞生。
而Linux的logo,就是企鹅啦,因为根据国际公约,南极洲为全人类共同所有,不属于世界上的任何国家。Linux 选择企鹅图案作为 Logo,代表了开放源代码的 Linux 为全人类共同所有。
此外,Linus Torvalds做出了全世界最大的程序员交友社区 GitHub(开源代码库及版本控制系统),因此无疑是这个世界上最伟大的程序员之一。
回到正题:GNU的GCC/G++
首先我们可以将GCC/G++看成一个整体,不存在GCC专门编译C语言,G++专门编译C++语言这种分别,因为编程语言发展至今是非常复杂的,编译器同样也是。我们将两者都看成GCC,GCC支持C、C++和Fortran语言。
而GCC(GNU Compiler Collection,GNU编译器集合),就是GNU运动的代表性成果,它的初衷是为GNU的自由系统开发完整的编译器。
所以,在Linux甚至Windows上各种涉及开发环境配置,源码编译的地方,都离不开gcc和g++。
Windows的Mingw/MSVC
MinGW(Minimalist GNUfor Windows),它是一个可自由使用和自由发布的Windows特定头文件和使用GNU工具集导入库的集合,允许你在Windows平台生成本地的Windows程序而不需要第三方C运行时(C Runtime)库。
运行时库:支持程序运行的基本函数的集合,一般是静态库lib或动态库dll。
而MSVC,就是上文所说的第三方C运行时库:由微软开发的VC运行时库,被Visual Studio IDE所集成。所以我们使用VS时会附带MSVC编译器。
所以可以看到啦,MinGW和MSVC都是Windows C/C++语言编译支持,配置环境时遇到两者择其一即可。
LLVM的clang/clang++
有了前文,对LLVM与clang不用解释应该也知道了。
LLVM是构架编译器(compiler)的框架系统,以C++编写而成,用于优化以任意程序语言编写的程序的编译时间(compile-time)、链接时间(link-time)、运行时间(run-time)以及空闲时间(idle-time),对开发者保持开放,并兼容已有脚本。
LLVM计划启动于2000年,最初由美国UIUC大学的Chris Lattner博士主持开展。2006年Chris Lattner加盟Apple Inc.并致力于LLVM在Apple开发体系中的应用。Apple也是LLVM计划的主要资助者。
目前LLVM已经被苹果IOS开发工具、Xilinx Vivado、Facebook、Google等各大公司采用。
Make/CMake
有了编译器GCC等等, 为什么要有make这个构建生成器,同样是老生常谈的内容。
编译hello.c非常简单,只需要
就可以了,但当项目庞大起来后,假设hello.c依赖与a.c、b.c,而a.c又依赖于库w.lib,每一次编译,我们都要重新编写一次gcc编译命令行吗?
所以,GNU发明了make这个工具软件,可以编写makefile文件来指定特定的项目构建过程,当项目一个文件的代码更改时,我们只需要重新make一下就可以了。
但make依然有很多不足,比如
- make对于类unix系统是通用的,但对windows系统并不友好(不能跨平台)
- make语法简单,也就导致了它功能的限制
- 不同编译器的语法规则不同,编写的makefile语法如果适合GCC则不适合MSVC
所以,CMake就应运而生啦。
CMake是比Make更高一层的工具,Make是编写对应编译器的makefile从而实现编译,而CMake是写一份独立的CmakeList.txt文件,然后该文件会根据当前系统环境选择适合的构建生成器(如VS或者make),然后将CmakeList.txt翻译为适合的文件,再进一步调用系统编译器进行项目构建。
THE END
OK,到这儿我们就捋完了从GCC到MSVC再到CMake这些名词啦,若文中有谬误,一定要指出哦。