GCC是GNU组织的免费C编译器,Linux的很多发布缺省安装的就是这种。很多流行的自由软件源代码基本都能在GCC编译器下编译运行。 所以掌握GCC编译器的使用无论是对于编译系统内核还是自己的应用程序都是大有好处的。
下面通过一个具体的例子,学习如何使用GCC编译器。
在Linux操作系统中,对一个用标准C语言写的源程序进行编译,要使用GNU的gcc编译器。
例如下面一个非常简单的Hello源程序(hello.c):
/*******************************************************
* Institute of Automation, Chinese Academy of Sciences
* File Name: hello.c
* Description:introduce how to compile a source file with gcc
* Author: Xueyuan Nie
* Date:
*******************************************************/
void main()
{
printf("Hello the world\n");
}
要编译这个程序,我们只要在Linux的bash提示符下输入命令:
$ gcc -o hello hello.c
gcc 编译器就会生成一个hello的可执行文件。在hello.c的当前目录下执行./hello就可以看到程序的输出结果,在屏幕上打印出“Hello the world”的字符串来。
命令行中 gcc表示是用gcc来编译源程序;
-o outputfilename选项表示要求编译器生成文件名为outputfilename的可执行文件,如果不指定-o选项,则缺省文件名是 a.out。在这里生成指定文件名为hello的可执行文件,而hello.c是我们的源程序文件。
gcc 是一个多目标的工具。gcc最基本的用法是:
gcc [options] file... ,
其中的option是以-开始的各种选项,file是相关的文件名。在使用gcc的时候,必须要给出必要的选项和文件名。gcc的整个编译过程,实质上是分四步进行的,每一步完成一个特定的工作,这四步分别是:预处理,编译,汇编和链接。它具体完成哪一步,是由gcc后面的开关选项和文件类型决定的。
清楚的区别编译和连接是很重要的。编译器使用源文件编译产生某种形式的目标文件(object files)。在这个过程中,外部的符号引用并没有被解释或替换,然后我们使用链接器来链接这些目标文件和一些标准的头文件,最后生成一个可执行文件。 在这个过程中,一个目标文件中对别的文件中的符号的引用被解释,并报告不能被解释的引用,一般是以错误信息的形式报告出来。
gcc编译器有许多选项,但对于普通用户来说只要知道其中常用的几个就够了。在这里为读者列出几个最常用的选项:
-o选项表示要求编译器生成指定文件名的可执行文件;
-c选项表示只要求编译器进行编译,而不要进行链接,生成以源文件的文件名命名但把其后缀由.c或.cc变成.o的目标文件;
-g选项要求编译器在编译的时候提供以后对程序进行调试的信息;
-E选项表示编译器对源文件只进行预处理就停止,而不做编译,汇编和链接;
-S选项表示编译器只进行编译,而不做汇编和链接;
-O选项是编译器对程序提供的编译优化选项,在编译的时候使用该选项,可以使生成的执行文件的执行效率提高;
-Wall 选项指定产生全部的警告信息。
如果你的源代码中包含有某些函数,则在编译的时候要链接确定的库,比如代码中包含了某些数学函数,在Linux下,为了使用数学函数,必须和数学库链接,为此要加入-lm 选项。也许有读者会问,前面那个例子使用printf函数的时候为何没有链接库呢?在gcc中对于一些常用函数的实现,gcc编译器会自动去链接一些常用库,这样用户就没有必要自己去指定了。有时候在编译程序的时候还要指定库的路径,这个时候要用到编译器的-L选项指定路径。比如说我们有一个库在 /home/hoyt/mylib下,这样我们编译的时候还要加上 -L/home/hoyt/mylib。对于一些标准库来说,没有必要指出路径。只要它们在起缺省库的路径下就可以了,gcc在链接的时候会自动找到那些库的。
GNU编译器生成的目标文件缺省格式为elf(executive linked file)格式,这是Linux系统所采用的可执行链接文件的通用文件格式。elf格式由若干段(section)组成,如果没有特别指明,由标准c源代码生成的目标文件中包含以下段:.text(正文段) 包含程序的指令代码,.data(数据段)包含固定的数据,如常量,字符串等,.bss(未初始化数据段) 包含未初始化的变量和数组等。
读者若想知道更多的选项及其用法,可以查看gcc的帮助文档,那里有许多对其它选项的详细说明。
当改变了源文件hello.c后,需要重新编译它:
$gcc -c hello.c
然后重新链接生成:
$gcc –o hello.o
对于本例,因为只含有一个源文件,所以当改动了源码后,进行重新的编译链接的过程显得并不是太繁琐,但是,如果在一个工程中包含了若干的源码文件,而这些源码文件中的某个或某几个又被其他源码文件包含,那么,如果一个文件被改动,则包含它的那些源文件都要进行重新编译链接,工作量是可想而知的。 幸运的是,GNU提供了使这个步骤变得简单的工具,就是下面要介绍给大家的GNU Make 工具。