gcc编译器

gcc编译器


  • GNU CC(简称gcc),是GUN项目中符合ANSI C标准的编译系统。
  • GCC不仅仅能支持 C 语言;它现在还支持 Ada 语言、C++ 语言、Java 语言、Objective C 语言、Pascal 语言、COBOL语言,以及支持函数式编程和逻辑编程的 Mercury 语言,等等。
  • 而且gcc是一个交叉平台编译器,它能够在当前CPU平台上为多种不同体系结构的硬件平台开发软件,因此尤其适合在嵌入式领域的开发编译。

gcc编译流程分为4个步骤:

  • 预处理(gcc -E)、编译(gcc -S)、汇编(gcc -c)、链接, gcc 选项可以简记为“ESc”,相应的产出文件的后缀可以简记为“iso”

下面具体看一下gcc是如何完成以上4个步骤的:

//test.c

#include 
int main(void)
 {
printf("Hello World!\n");
return 0;
}

这个程序,一步到位的编译指令是:

gcc test.c -o test

预处理

运行预处理命令:

gcc -E test.c -o test.i 或 gcc -E test.c

gcc的-E选项,可以让编译器在预处理后停止,并输出预处理结果。

gcc的-o选项,用于输出处理结果到文件中。

在本例中,预处理结果就是将stdio.h 文件中的内容插入到test.c中了。

编译

预处理之后,可直接对生成的test.i文件编译,生成汇编代码:

gcc -S test.i -o test.s

gcc的-S选项,表示在程序编译期间,在生成汇编代码后,停止,-o输出汇编代码文件。

汇编

gcc -c test.s -o test.o

链接

链接阶段,这里涉及一个重要的概念:函数库

  • 在这个程序中并没有定义“printf”的函数实现,且在预编译中包含进的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实现“printf”函数的呢?

  • 最后的答案是:系统把这些函数的实现都放到名为libc.so.6的库文件中去了,在没有特别指定时,gcc会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到libc.so.6函数库中去,这样就能调用函数“printf”了,而这也正是链接的作用

函数库有静态库和动态库两种

静态库是指编译链接时,将库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了,其后缀名通常为“.a”。

动态库与之相反,在编译链接时并没有将库文件的代码加入到可执行文件中,而是在程序执行时加载,这样可以节省系统的开销。一般动态库的后缀名为“.so”,如前面所述的libc.so.6就是动态库。gcc在编译时默认使用动态库。

对于上一小节中生成的test.o,将其与C标准输入输出库进行连接,最终生成程序test:

gcc test.o -o test

多个程序文件的编译

通常整个程序是由多个源文件组成的,相应地也就形成了多个编译单元,使用GCC能够很好地管理这些编译单元。假设有一个由test1.c和 test2.c两个源文件组成的程序,为了对它们进行编译,并最终生成可执行程序test,可以使用下面这条命令:

gcc test1.c test2.c -o test

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

gcc -c test1.c -o test1.o
gcc -c test2.c -o test2.o
gcc test1.o test2.o -o test
posted @ 2015-10-04 14:21  adacn  阅读(858)  评论(0编辑  收藏  举报