经常被各种名词搞得头昏脑涨,虽然也没有什么大的影响,但有不清楚不了解的地方总觉得十分烦躁,干脆简单总结一下好了.
1. Unix、Linux、GNU、FSF的历史
- 1965年,Bell、MIT和GE共同发起Multics项目,想要开发一个强大的分时操作系统,但最终失败,Bell退出项目。
- 之后,贝尔实验室的Ken Thompson受multics的启发,希望开发一个小的操作系统供自己使用,于是以汇编语言写出一套内核程序,Unics
- 虽然Unics很好用,但由于是根据汇编语言写成的,安装到不同架构的机器都需要重构,于是后来Thompson和Ritchie合作,以C语言重写Unics内核,从而诞生了Unix,是的Unix容易被移植到不用的机器上。(其中x就是cross的略写,跨平台的意思)
- Unix具有高度可移植性和强大的性能,但几年后版权意识渐强,逐步商业化,并不可对学生提供源码。为了教授操作系统,,1984年Andrew Stuart Tanenbaum教授便自己写了一个叫Minix的Unix-like系统。
- 1984年,Stallman发起了GNU项目,这个项目的目的是创建一个自由开放的UNIX操作系统,之后又创立的自由软件基金会FSF。著名的C语言编译程序GNU C Compiler(GCC)也在这里诞生。此外还编写了可以被调用的C函数库GNU C Library,以及可以被用来操作操作系统的基本接口bash shell.
- 为避免GNU所开发的自由软件被他人利用而成为专利软件,诞生了有名的通用公共许可证GPL,General public license. 但此时这些自由软件仍然只能工作在被授权的UNIX系统上。
- 到1991年,芬兰赫尔辛基大学的学生Linus基于Minix、GCC、Bash等工具写了一个小小的内核程序,也就是Linux。但不同于Minix系统就是为当做教学用具而生的,Linux则是向一个实用的操作系统发展。很多人一起为Linux写了无数行的代码,最终让它成为了一个使用很广泛的系统。
总的来说,Linux兼容Unix系统的很多东西,但二者的不同之处也一点不少。Unix其实在很多程度上就是一个商标,现在经过认证了的真·Unix系统大概也只有Solaris了,像FreeBSD、Linux、Darwin(MacOS的底层系统)都只是类Unix,即类似Unix的系统(参考)。
2. gcc,g++
首先看一下程序的编译过程
在Unix系统上,从源文件到目标文件的转化是由编译器驱动程序完成的:
unix>gcc -o hello hello.c
执行这四个阶段的程序(预处理器、编译器、汇编器、链接器)一起构成了编译系统(compilation system).
- 预处理阶段:在C语言的语法中,就是将#include所指向的一些文件,包那些写入到程序文本中,然后形成一个.i为后缀的文件;
- 编译阶段:编译器(ccl)将文本文件hello.i翻译成文本文件hello.s,它包含一个汇编语言程序.
- 汇编阶段:汇编器as将hello.s翻译成机器语言指令,并将指令打包成为一种叫做可重定位目标程序(relocatable object program)的格式,并将结果保存在hello.o中。 hello.o是一个二进制文件,它的字节编码是机器语言指令而不是字符。
- 链接阶段:printf函数存在于一个名为printf.o的单独的预编译好了的目标文件中,链接器ld负责合并printf.o和hello.o文件。结果就得到了hello文件,他是一个可执行目标文件,可以被加载到内存中由系统执行.
之前提到gcc(GNU C Compiler)诞生于GNU,是一个c语言的编译程序,但如今它可以编译很多种编程语言(括C、C++、Objective-C、Fortran、Java等等)。
之前一直以为gcc和g++是一样的,但在尝试用GCC编译cpp文件的时候,结果却报错了,如果按照C语言的写法是没问题的。1
undefined reference to `std::cout'
所以这里需要纠正一下之前的说法:
- GCC:GNU Compiler Collection(GUN 编译器集合),它可以编译C、C++、JAV、Fortran、Pascal、Object-C、Ada等语言。
- gcc是GCC中的GUN C Compiler(C 编译器)
- g++是GCC中的GUN C++ Compiler(C++编译器)
GCC原名GNU C Compiler, 原本只能处理C语言,但由于很快的发展,变得可以处理多种语言,于是也就改名称为GNU Compiler Colletion, 同样简称GCC(哎,令人头痛)
一个有趣的事实就是,就本质而言,gcc和g++并不是编译器,也不是编译器的集合,它们只是一种驱动器,根据参数中要编译的文件的类型,调用对应的GUN编译器而已,比如,用gcc编译一个c文件的话,会有以下几个步骤:
Step1:Call a preprocessor, like cpp.
Step2:Call an actual compiler, like cc or cc1.
Step3:Call an assembler, like as.
Step4:Call a linker, like ld
由于编译器是可以更换的,所以gcc不仅仅可以编译C文件
所以,更准确的说法是:gcc调用了C compiler,而g++调用了C++ compiler
以上四步正好对应了上图中程序编译的四步。
对于 .c和.cpp文件,gcc分别当做c和cpp文件编译(c和cpp的语法强度是不一样的)
对于 .c和.cpp文件,g++则统一当做cpp文件编译
使用g++编译文件时,g++会自动链接标准库STL,而gcc不会自动链接STL
gcc在编译C文件时,可使用的预定义宏是比较少的
在用gcc编译c++文件时,为了能够使用STL,需要加参数 –lstdc++ ,但这并不代表 gcc –lstdc++ 和 g++等价,它们的区别不仅仅是这个.
gcc在编译cpp文件时/g++在编译c文件和cpp文件时(这时候gcc和g++调用的都是cpp文件的编译器),会加入一些额外的宏,这些宏如下:
1
2
3
4
5
6
7 >#define __GXX_WEAK__ 1
>#define __cplusplus 1
>#define __DEPRECATED 1
>#define __GNUG__ 4
>#define __EXCEPTIONS 1
>#define __private_extern__ extern
>
3. make,makefile和cmake
这几个的关系也一度让我头疼,好已有DL给出了不错的解答,搬运一下放在这里
作者:辉常哥
链接:https://www.zhihu.com/question/27455963/answer/89770919
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
- gcc是GNU Compiler Collection(就是GNU编译器套件),也可以简单认为是编译器,它可以编译很多种编程语言(括C、C++、Objective-C、Fortran、Java等等)。
- 当你的程序只有一个源文件时,直接就可以用gcc命令编译它。
- 但是当你的程序包含很多个源文件时,用gcc命令逐个去编译时,你就很容易混乱而且工作量大
- 所以出现了make工具make工具可以看成是一个智能的批处理工具,它本身并没有编译和链接的功能,而是用类似于批处理的方式—通过调用makefile文件中用户指定的命令来进行编译和链接的。
- makefile是什么?简单的说就像一首歌的乐谱,make工具就像指挥家,指挥家根据乐谱指挥整个乐团怎么样演奏,make工具就根据makefile中的命令进行编译和链接的。
- makefile命令中就包含了调用gcc(也可以是别的编译器)去编译某个源文件的命令。
- makefile在一些简单的工程完全可以人工手下,但是当工程非常大的时候,手写makefile也是非常麻烦的,如果换了个平台makefile又要重新修改。
- 这时候就出现了Cmake这个工具,cmake就可以更加简单的生成makefile文件给上面那个make用。当然cmake还有其他功能,就是可以跨平台生成对应平台能用的makefile,你不用再自己去修改了。
- 可是cmake根据什么生成makefile呢?它又要根据一个叫CMakeLists.txt文件(学名:组态档)去生成makefile。
- 到最后CMakeLists.txt文件谁写啊?亲,是你自己手写的。
11.当然如果你用IDE,类似VS这些一般它都能帮你弄好了,你只需要按一下那个三角形