类UNIX下编译器 cc、gcc、g++、clang 的理解
前言
平时编译一些基于C/C++的程序,难免需要使用到C++编译器,在macOS下也会需要要求安装 XCode的扩展。使用中,会看到GCC的身影。
在我们平时自己研究的时候就会发现有:cc、gcc、g++、CC、llvm 等映入眼帘。
gcc 是GNU Compiler Collection,原名为Gun C语言编译器,因为它原本只能处理C语言,但gcc很快地扩展,包含很多编译器(C、C++、Objective-C、Ada、Fortran、 Go、Objective-C),可以说gcc是GNU编译器集合。
g++ 是C++编译器。
cc 是 Unix系统的 C Compiler,一个是古老的 C 编译器。而 Linux 下 cc 一般是一个符号连接,指向 gcc;可以通过 $ ls -l /usr/bin/cc 来简单察看,该变量是 make 程序的内建变量,默认指向 gcc 。 cc 符号链接和变量存在的意义在于源码的移植性,可以方便的用 gcc 来编译老的用cc编译的Unix软件,甚至连 makefile 都不用改在,而且也便于 Linux 程序在 Unix下 编译。
clang则为BSD系列系统,如macOS内部的LLVM底层虚拟机模式的编译器。
CC 则一般是 makefile 里面的一个名字标签,即宏定义,表示采用的是什么编译器(如:CC = gcc)。
误区一:gcc只能编译C代码,g++只能编译C++代码。
两者都可以,但请注意:
(1)后缀为.c的,gcc把它当作是C程序,而g++当作是c++程序;后缀为.cpp的,两者都会认为是C++程序,注意,虽然C++是C的超集,但是两者对语法的要求是有区别的。C++的语法规则更加严谨一些。
(2)编译阶段,g++会调用gcc,对于C++代码,两者是等价的,但是因为gcc命令不能自动和C++程序使用的库联接,所以通常用g++来完成链接,为了统一起见,干脆编译/链接统统用g++了,这就给人一种错觉,好像cpp程序只能用g++似的。
误区二:gcc不会定义__cplusplus宏,而g++会
实际上,这个宏只是标志着编译器将会把代码按C还是C++语法来解释,如上所述,如果后缀为.c,并且采用gcc编译器,则该宏就是未定义的,否则,就是已定义。
误区三:编译只能用gcc,链接只能用g++
严格来说,这句话不算错误,但是它混淆了概念,应该这样说:编译可以用gcc/g++,而链接可以用g++或者gcc -lstdc++。因为gcc命令不能自动和C++程序使用的库联接,所以通常使用g++来完成联接。但在编译阶段,g++会自动调用gcc,二者等价。
C++的编译器肯定可以编译C的代码,注意除了C++对C的语法扩充之外,编译和链接C和C++的标准库通常也不一样呢,用gcc而非g++也编译了C++的程序就证明了这一点。
误区四:clang只能编译oc的文件
Objective-C只是一种语言,clang会调用整个LLVM编译工具链,甚至能够支持cgo的编译。
总结
关于 c 编译器,发展离不开整个 UNIX 环境的共同进步,以达到今天的方便,同学们理解了吗。
|
|