百度词条
- GNU:GNU是一个自由的操作系统,其内容软件完全以GPL方式发布。这个操作系统是GNU计划的主要目标,名称来自GNU's Not Unix!的递归缩写,因为GNU的设计类似Unix,但它不包含具著作权的Unix代码。GNU的创始人是理查德·马修·斯托曼。
- GPL:GNU通用公共许可证简称为GPL,是由自由软件基金会发行的用于计算机软件的协议证书,使用该证书的软件被称为自由软件。大多数的GNU程序和超过半数的自由软件使用它。
- FSF:自由软件基金会(Free Software Foundation,FSF)是一个致力于推广自由软件、促进计算机用户自由的美国民间非盈利性组织。它于1985年10月由理查德·斯托曼建立。其主要工作是执行GNU计划,开发更多的自由软件,完善自由软件理念。
- GCC:GCC(GNU Compiler Collection,GNU编译器套件)是由GNU开发的编程语言译器。GNU编译器套件包括C、C++、 Objective-C、 Fortran、Java、Ada和Go语言前端,也包括了这些语言的库(如libstdc++,libgcj等。)
GUN计划(GNU工程)产出了很多自由软件,包括GNU操作系统、GCC编译器套件、GDB等。可以说在GPL条例下发布的软件都可以说是自由软件。
理查德·马修·斯托曼(Richard Matthew Stallman, RMS)
GNU、GPL、FSF、GCC全部和一个人有关,就是理查德·马修·斯托曼(Richard Matthew Stallman, RMS),斯托曼于1953年出生,自由软件运动的精神领袖、GNU计划以及自由软件基金会(Free Software Foundation)的创立者、著名黑客。
作为自由软件运动的精神领袖,他所建立的GNU工程激励了很多的年轻黑客,这些人也创作了很多自由软件。 他所写作的GNU通用公共许可证(GPL)是世上最广为采用的自由软件许可证,为copyleft观念开拓出一条崭新的道路。
经历
斯托曼1953年出生于美国纽约曼哈顿地区,1971年进入哈佛大学学习,同年受聘于麻省理工学院人工智能实验室(AI Laboratory),成为一名职业黑客。 在AI实验室工作期间,斯托曼开发了多种今后影响深远的软件,其中最著名的就是Emacs。斯托曼在AI是一名典型的黑客,是整个黑客文化的一份子。
然而进入八十年代后,软件进入版权时代,黑客社群在软件工业商业化的强大压力下日渐土崩瓦解,甚至连AI实验室的许多黑客也组成了Symbolic公司,试图以专利软件来取代实验室中黑客文化的产物-免费可自由流通的软件。
斯托曼对此感到气愤与无奈。在对Symbolic进行了一段时间的抗争后,他于1985年发表了著名的GNU宣言(GNU Manifesto),正式宣布要开始进行一项宏伟的计划:创造一套完全自由免费,兼容Unix的操作系统GNU(GNU's Not Unix!)。之后他又建立了自由软件基金会来协助该计划。
他于1989年与一群律师起草了广为使用的GNU通用公共协议证书(GNU General Public License, GNU GPL),创造性地提出了“反版权”(或“版权属左”,或“开权”,copyleft)的概念。 同时,GNU计划中除了最关键的Hurd操作系统内核之外,其他绝大多数软件已经完成。
1991年芬兰大学生Linus Torvalds在GPL条例下发布他自己创作的Linux操作系统内核,至此GNU计划正式完成,操作系统被命名为GNU/Linux(或简称Linux)。
斯托曼是一名坚定的自由软件运动倡导者与其他提倡开放源代码的人不同,斯托曼并不是从软件质量的角度而是从道德的角度来看待自由软件。他认为使用专利软件是非常不道德的事,只有附带了源代码的程序才是符合其道德标准的。对此许多人表示异议,并也因此有了自由软件运动与开源软件运动之分。
GCC
GCC是以GPL许可证所发行的自由软件,也是GNU计划的关键部分。GCC的初衷是为GNU操作系统专门编写一款编译器,现已被大多数类Unix操作系统(如Linux、BSD、MacOS X等)采纳为标准的编译器,甚至在微软的Windows上也可以使用GCC。GCC支持多种计算机体系结构芯片,如x86、ARM、MIPS等,并已被移植到其他多种硬件平台。
GCC原名为GNU C语言编译器(GNU C Compiler),只能处理C语言。但其很快扩展,变得可处理C++,后来又扩展为能够支持更多编程语言,如Fortran、Pascal、Objective -C、Java、Ada、Go以及各类处理器架构上的汇编语言等,所以改名GNU编译器套件(GNU Compiler Collection) 。
基本用法
使用GCC编译器的时候,我们必须给出一系列必要的调用参数和文件名称。GCC编译器的调用参数大约有100多个,这里只介绍其中最基本、最常用的参数。
GCC最基本的用法是∶gcc [options] [filenames]
其中options就是编译器所需要的参数,filenames给出相关的文件名称。
- -c,仅执行编译操作,不进行连接操作,不链接成为可执行文件,编译器只是由输入的.c等源代码文件生成.o为后缀的目标文件,通常用于编译不包含主程序的子程序文件。
- -o output_filename,指定生成的输出文件,确定输出文件的名称为output_filename,同时这个名称不能和源文件同名。如果不给出这个选项,gcc就给出预设的可执行文件a.out。
- -g,产生符号调试工具(GNU的gdb)所必要的符号资讯,要想对源代码进行调试,我们就必须加入这个选项。
- -O,对程序进行优化编译、链接,采用这个选项,整个源代码会在编译、链接过程中进行优化处理,这样产生的可执行文件的执行效率可以提高,但是,编译、链接的速度就相应地要慢一些。
- -O2,比-O更好的优化编译、链接,当然整个编译、链接过程会更慢。
- -E:仅执行编译预处理;
- -S:将C代码转换为汇编代码;
- -wall:显示警告信息;
- -v gcc执行时执行的详细过程,gcc及其相关程序的版本号
基本规则
gcc所遵循的部分约定规则:
- .c为后缀的文件,C语言源代码文件;
.a为后缀的文件,是由目标文件构成的档案库文件;
.C,.cc或.cxx 为后缀的文件,是C++源代码文件且必须要经过预处理;
.h为后缀的文件,是程序所包含的头文件;
.i 为后缀的文件,是C源代码文件且不应该对其执行预处理;
.ii为后缀的文件,是C++源代码文件且不应该对其执行预处理;
.m为后缀的文件,是Objective-C源代码文件;
.mm为后缀的文件,是Objective-C++源代码文件;
.o为后缀的文件,是编译后的目标文件;
.s为后缀的文件,是汇编语言源代码文件;
.S为后缀的文件,是经过预编译的汇编语言源代码文件。
执行过程
虽然我们称GCC是C语言的编译器,但使用gcc由C语言源代码文件生成可执行文件的过程不仅仅是编译的过程,而是要经历四个相互关联的步骤∶预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编(Assembly)和链接(Linking)。
命令gcc首先调用cpp进行预编译,在预编译过程中,对源代码文件中的文件包含(include)、预编译语句(如宏定义define等)进行分析,由.c为后缀的文件生成.i为后缀的文件。接着调用cc1进行编译,这个阶段根据输入文件(xxx.i)生成以.s为后缀的目标文件。汇编过程是针对汇编语言的步骤,调用as进行工作,一般来讲,.S或.s为后缀的汇编语言源代码文件都生成以.o为后缀的目标文件。当所有的目标文件都生成之后,gcc就调用ld来完成最后的关键性工作,这个阶段就是链接。在链接阶段,所有的目标文件被安排在可执行程序中的恰当的位置,同时,该程序所调用到的库函数也从各自所在的档案库中连到合适的地方。
执行过程示例
- 示例代码,创建hello.txt文件,输入以下内容,修改后缀为
.c
#include<stdio.h>
int main(void)
{
printf("hello world\n");
return 0;
}
- 预编译过程
这个过程处理宏定义和include,去除注释,不会对语法进行检查。
[root@localhost gcc-test]# cat hello.c | wc -l
6 // 可以看到hello.c文件目前是6行。
[root@localhost gcc-test]#
[root@localhost gcc-test]# gcc -E hello.c -o hello.i
[root@localhost gcc-test]# ls
hello.c hello.i // 预编译成功完成,生成hello.i文件
[root@localhost gcc-test]# cat hello.i | wc -l
843 // 可以看到预编译后,代码从6行扩展到了843行。
[root@localhost gcc-test]#
- 编译过程
这个阶段,检查语法,生成汇编代码。
[root@localhost gcc-test]# gcc -S hello.i -o hello.s
[root@localhost gcc-test]# ls
hello.c hello.i hello.s
[root@localhost gcc-test]# cat hello.s | wc -l
26
[root@localhost gcc-test]#
- 汇编过程
这个阶段,生成目标代码。
此过程生成ELF格式的目标代码。
[root@localhost gcc-test]# gcc -c hello.s -o hello.o
[root@localhost gcc-test]# ls
hello.c hello.i hello.o hello.s
[root@localhost gcc-test]# file hello.o
hello.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
[root@localhost gcc-test]#
- 链接过程
链接过程。生成可执行代码。链接分为两种,一种是静态链接,另外一种是动态链接。使用静态链接的好处是,依赖的动态链接库较少,对动态链接库的版本不会很敏感,具有较好的兼容性;缺点是生成的程序比较大。使用动态链接的好处是,生成的程序比较小,占用较少的内存。
[root@localhost gcc-test]# gcc hello.o -o hello
[root@localhost gcc-test]# ls
hello hello.c hello.i hello.o hello.s
程序运行:
[root@localhost gcc-test]# ./hello
hello world
[root@localhost gcc-test]#
无选项编译链接
gcc test.c
将test.c预处理、汇编、编译并链接形成可执行文件。这里未指定输出文件,默认输出为a.out。