Linux gcc 编译过程

来源:互联网 发布:中银淘宝校园卡 年费 编辑:程序博客网 时间:2024/05/14 05:06

Linux GCC 编译过程  

 

目前Linux下最常用的C语言编译器是GCC(GNU Compiler Collection),它是GNU项目中符合ANSI C标准的编译系统,能够编译用C、C++和Object C等语言编写的程序.GCC不仅功能非常强大,结构也异常灵活.最值得称道的一点就是它可以通过不同的前端模块来支持各种语言,如Java、Fortran、Pascal、Modula-3和Ada等.

Linux系统下的gcc(GNU C Compiler)是GNU推出的功能强大、性能优越的多平台编译器,是GNU的代表作品之一。gcc是可以在多种硬体平台上编译出可执行程序的超级编译器,其执行效率与一般的编译器相比平均效率要高20%~30%。

使用GCC编译程序时,编译过程可以被细分为四个阶段:
◆ 预处理(Pre-Processing)
◆ 编译(Compiling)
◆ 汇编(Assembling)
◆ 链接(Linking)

.c为后缀的文件,C语言源代码文件;
.a为后缀的文件,是由目标文件构成的档案库文件;
.C,.cc或.cxx 为后缀的文件,是C++源代码文件;
.h为后缀的文件,是程序所包含的头文件;
.i 为后缀的文件,是已经预处理过的C源代码文件;
.ii为后缀的文件,是已经预处理过的C++源代码文件;
.m为后缀的文件,是Objective-C源代码文件;
.o为后缀的文件,是编译后的目标文件;
.s为后缀的文件,是汇编语言源代码文件;
.S为后缀的文件,是经过预编译的汇编语言源代码文件。

命令gcc首先调用cpp进行预处理,在预处理过程中,对源代码文件中的文件包含(include)、预编译语句(如宏定义define等)进行分析。接着调用cc1进行编译,这个阶段根据输入文件生成以.o为后缀的目标文件。汇编过程是针对汇编语言的步骤,调用as进行工作,一般来讲,.S为后缀的汇编语言源代码文件和汇编、.s为后缀的汇编语言文件经过预编译和汇编之后都生成以.o为后缀的目标文件。当所有的目标文件都生成之后,gcc就调用ld来完成最后的关键性工作,这个阶段就是连接。在连接阶段,所有的目标文件被安排在可执行程序中的恰当的位置,同时,该程序所调用到的库函数也从各自所在的档案库中连到合适的地方。

例程1:hello.c
#include
int main(void)
{
printf ("Hello world, Linux programming!/n");
return 0;
}

然后执行下面的命令编译和运行这段程序:

# gcc hello.c -o hello
# ./hello
Hello world, Linux programming!

首先,GCC需要调用预处理程序cpp,由它负责展开在源文件中定义的宏,并向其中插入“#include”语句所包含的内容;接着,GCC会调用ccl和as将处理后的源代码编译成目标代码;最后,GCC会调用链接程序ld,把生成的目标代码链接成一个可执行程序.

◆ 预处理(Pre-Processing)
使用-E参数可以让GCC在预处理结束后停止编译过程:
# gcc -E hello.c -o hello.cpp

◆ 编译(Compiling)
下一步是将hello.i编译为目标代码,这可以通过使用-c参数来完成:
# gcc -x cpp-output hello.cpp -o hello.o
或者
# gcc -c hello.cpp -o hello.o

◆ 汇编(Assembling)
◆ 链接(Linking)
# gcc hello.o -o hello
汇编应该调用as,这里应该是一起完成了

gcc主要参数:

-o 定义输出文件
-E 完成预处理/预编译停止
-c 只编译生成.o,不连接
-x 指定编译步骤
-g gdb调试用,在可执行程序中包含标准调试信息
-O,O1,O2,O3,O4,O5 优化级别
-w 关闭所有警告
-Wall 允许所有有用的警告
-DFOO=BAR 定义预处理宏FOO的值为BAR
-IDIRNAME 将DIRNAME加入到包含文件的搜索目录中去
-LDIRNAME 将DIRNAME加入到库文件文件的搜索目录中去
-static 静态链接库
-lFOO 动态连接库,名为libFOO.o/libFOO.so(2.4/2.6)
-mcpu=CPU TYPE 针对不同CPU作不同的优化,比如-m386,-mpentiumpro

转自:http://www.xxlinux.com/linux/article/development/soft/20070102/6759.html

 

 

  gcc编译过程概述
     

本文对gcc编译器如何工作做一个概要描述.更为详细的信息请参考编译器手册。

当我们进行编译的时候,要使用一系列的工具,我们称之为工具链.其中包括:预处理器CPP,编译器前端gcc/g++,汇编器as,连接器ld.一个编译过程包括下面几个阶段:
(1)预处理。预处理器CPP将对源文件中的宏进行展开。
(2)编译。gcc将c文件编译成汇编文件。
(3)汇编。as将汇编文件编译成机器码。
(4)连接。ld将目标文件和外部符号进行连接,得到一个可执行二进制文件。

下面以一个很简单的test.c来探讨这个过程。
        #defineNUMBER(1+2)
        int main()
        {
                int  x = NUMBER;
                return  0;
        }

(1)预处理:
        gcc会首先调用CPP进行预处理:CPP test.c > test.i
        预处理的输出为文件test.i。
        我们用cat test.i查看test.i的内容如下:
        int main()
        {
                int x = (1+2);
                return  0;
        }
        我们可以看到,文件中宏定义NUMBER出现的位置被(1+2)替换掉了,其它的内容保持不变。

(2)gcc将c文件编译成汇编文件。
        接下来gcc会执行gcc -S test.i得到的输出文件为test.s.

(3)as将汇编文件编译成机器码。
        as test.s -o test.o
        得到输出文件为test.o.
        test.o中为目标机器上的二进制文件.
        用nm查看文件中的符号:nm test.o
        输出如下:
                00000000 b .bss
                00000000 d .data
                00000000 t .text
                U ___main
                U __alloca
                00000000 T _main

        既然已经是二进制目标文件了,能不能执行呢?试一下./test.o,提示cannot execute binaryfile.
        原来___main前面的U表示这个符号的地址还没有定下来,T表示这个符号属于代码段。ld连接的时候会为这些带U的符号确定地址。

(4)连接。
        连接需要指定库的位置。通常程序中会有很多的外部符号,因此需要指定的位置就会很多。
        不过,我们之需要调用gcc即可,ld会自己去找这些库的位置。
        gcc test.o > test
        就得到了最终的可执行程序了。

 

 

 原文地址 http://blog.csdn.net/xdxiaofeng/archive/2008/07/11/2640013.aspx

GCC编译过程分解

############################################
$ ls
crt1.o      crtend.o  crtn.o  main.c  main.o
crtbegin.o  crti.o    main    main.i  main.s
$ cpp -o main.i main.c
$ cc1 -o main.s -quiet main.i
$ as -o main.o main.s
$ ld -o main -dynamic-linker /lib/ld-linux.so.2 crt1.o crti.o crtbegin.o main.o -lc crtend.o crtn.o
$ ./main
Hello Debian GNU/Linux!
$ echo "gcc=cpp+cc1+as+ld"
gcc=cpp+cc1+as+ld
$

cpp    预处理
cc1    编译
as    汇编
ld    链接

unix中
cc=cpp+comp+as+ld

linux
gcc=cpp+cc1+as+ld

转自:http://blog.linuxeden.com/index.php/196616/viewspace-7391.html

原创粉丝点击