日期:2014-05-16  浏览次数:20700 次

【Linux】linux下gcc编译器的使用

GCC介绍

?

在为Linux开发应用程序时,绝大多数情况下使用的都是C语言,因此几乎每一 位Linux程序员面临的首要问题都是如何灵活运用C编译器。目前Linux下最常用的C语言编译器是GCC(GNU Compiler Collection),它是GNU项目中符合ANSI C标准的编译系统,能够编译用C、C++和Object C等语言编写的程序。GCC不仅功能非常强大,结构也异常灵活。最值得称道的一点就是它可以通过不同的前端模块来支持各种语言,如Java、 Fortran、Pascal、Modula-3和Ada等。

?

开放、自由和灵活是Linux的魅力所在,而这一点在GCC上的体现就是程序员通过它能够更好地控制整个编译过程。在使用GCC编译程序时,编译过程可以被细分为四个阶段:

◆ 预处理(Pre-Processing)

◆ 编译(Compiling)

◆ 汇编(Assembling)

◆ 链接(Linking)

?

Linux程序员可以根据自己的需要让GCC在编译的任何阶段结束,以便检查或使用编译器在该阶段的输出信息,或者对最后生成的二进制文件进行控 制,以便通过加入不同数量和种类的调试代码来为今后的调试做好准备。和其它常用的编译器一样,GCC也提供了灵活而强大的代码优化功能,利用它可以生成执 行效率更高的代码。

?

GCC提供了30多条警告信息和三个警告级别,使用它们有助于增强程序的稳定性和可移植性。此外,GCC还对标准的C和C++语言进行了大量的扩展,提高程序的执行效率,有助于编译器进行代码优化,能够减轻编程的工作量。

?

?

?

?

GCC基本命令

?

(1) 单个源文件的编译运行

在学习使用GCC之前,下面的这个例子能够帮助用户迅速理解GCC的工作原理,并将其立即运用到实际的项目开发中去。首先用编辑器VI输入源代码1,并保存在用户目录下的hello.c文件中。

//源代码1
#include <stdio.h>
int main(void){
   printf ("Hello world, Linux programming!\n");
   return 0;
} 

?

然后执行下列命令编译hello.c成为Linux的可执行文件hello

命令:【gcc hello.c -o hello】 ? 此时 会在hello.c的当前目录下生成一个文件名为“hello”的可执行程序(Linux的可执行文件没有扩展名)。注意:如果命令行中没有-o hello,则gcc就给出预设的可执行文件a.out。

?

从程序员的角度看,只需简单地执行一条GCC命令就可以了,但从编译器的角度来看,却需要完成一系列非常繁杂的工作。 首先,GCC需要调用预处理程序cpp,由它负责展开在源文件中定义的宏,并向其中插入“#include”语句所包含的内容;

接着,GCC会调用ccl和as将处理后的源代码编译成目标代码;

最后,GCC会调用链接程序ld,把生成的目标代码链接成一个可执行程序。

?

为了更好地理解GCC的工作过程,可以把上述编译过程分成几个步骤单独进行,并观察每步的运行结果。

第一步是进行预编译,使用-E参数可以让GCC在预处理结束后停止编译过程:

命令:gcc -E hello.c -o hello.i

此时会在当前目录下生成一个hello.i文件,将头文件stdio.h的内容都插到此文件中,而其它应当被预处理的宏定义也都做了相应的处理。


第二步是编译过程,使用-c参数可以把上面生成的hello.i 编译为目标代码.

命令:gcc -c hello.i -o hello.o

此时会在当前目录下生成一个hello.o文件,这个文件就是被gcc编译器编译后形成的目标文件。

?

第三步是链接过程,将生成的目标文件链接成可执行文件。

命令: gcc hello.o -o hello

此时会在当前目录下生成一个hello的可执行文件。

?

(2) 多个源文件的编译运行

在采用模块化的设计思想进行软件开发时,通常整个程序是由多个源文件组成的, 相应地也就形成了多个编译单元,使用GCC能够很好地管理这些编译单元。假设有一个由foo1.c和foo2.c两个源文件组成的程序,为了对它们进行编 译,并最终生成可执行程序foo,可以使用下面这条命令:

命令:gcc foo1.c foo2.c -o foo

如果同时处理的文件不止一个,GCC仍然会按照预处理、编译和链接的过程依次进行。如果深究起来,上面这条命令大致相当于依次执行如下三条命令:

命令:gcc -c foo1.c -o foo1.o # gcc -c foo2.c -o foo2.o # gcc foo1.o foo2.o -o foo

在编译一个包含许多源文件的工程时,若只用一条GCC命令来完成编译是非常浪费时间的。假设项目中有100个源文件需要编译,并且每个源文件中都包含 10000行代码,如果像上面那样仅用一条GCC命令来完成编译工作,那么GCC需要将每个源文件都重新编译一遍,然后再全部连接起来。很显然,这样浪费 的时间相当多,尤其是当用户只是修改了其中某一个文件的时候,完全没有必要将每个文件都重新编译一遍,因为很多已经生成的目标文件是不会改变的。要解决这 个问题,关键是要灵活运用GCC,同时还要借助像Make这样的工具。

?

?

?

?

?

GCC 警告提示功能

?

GCC