gcc 编译过程

转载 2011年01月18日 16:52:00

详解GCC编译流程
    使用vi编写源文件hello.c。
 
 #include <stdio.h>
int main()
{
        int i;
        for(i=1;i<9;i++)
                printf("Hello World %d times!/n",i);
        return 0;
}
 
    1、预处理阶段
    该阶段的作用是把预处理文件,也就是头文件编译进来。在此例中,就是要把stdio.h编译进来。可使用-E选项查看,作用是让gcc在预处理结束后停止编译过程。
[armlinux@lqm program]$ gcc -E hello.c -o hello.i
[armlinux@lqm program]$ cat hello.i | less
 
# 1 "hello.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "hello.c"
# 1 "/usr/include/stdio.h" 1 3
# 28 "/usr/include/stdio.h" 3
# 1 "/usr/include/features.h" 1 3
# 291 "/usr/include/features.h" 3
# 1 "/usr/include/sys/cdefs.h" 1 3
# 292 "/usr/include/features.h" 2 3
# 314 "/usr/include/features.h" 3
# 1 "/usr/include/gnu/stubs.h" 1 3
# 315 "/usr/include/features.h" 2 3
# 29 "/usr/include/stdio.h" 2 3
 
...
 
extern void funlockfile (FILE *__stream) ;
# 679 "/usr/include/stdio.h" 3
# 2 "hello.c" 2
int main()
{
        int i;
        for(i=1;i<9;i++)
                printf("Hello World %d times!/n",i);
        return 0;
}
 
    由此可见,stdio.h的内容已经插入到hello.c中,即GCC完成了预处理过程。
    2、编译阶段
    GCC的工作是首先检查代码的规范性、是否有语法错误,以确定代码实际要做的工作。检查无误后,将之翻译为汇编语言。可用-S来查看,即只编译而不进入汇编阶段。
[armlinux@lqm program]$ gcc -S hello.i -o hello.s
[armlinux@lqm program]$ cat hello.s

        .file   "hello.c"
        .section        .rodata
.LC0:
        .string "Hello World %d times!/n"
        .text
.globl main
        .type   main,@function
main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $8, %esp
        andl    $-16, %esp
        movl    $0, %eax
        subl    %eax, %esp
        movl    $1, -4(%ebp)
.L2:
        cmpl    $8, -4(%ebp)
        jle     .L5
        jmp     .L3
.L5:
        subl    $8, %esp
        pushl   -4(%ebp)
        pushl   $.LC0
        call    printf
        addl    $16, %esp
        leal    -4(%ebp), %eax
        incl    (%eax)
        jmp     .L2
.L3:
        movl    $0, %eax
        leave
        ret
.Lfe1:
        .size   main,.Lfe1-main
        .ident  "GCC: (GNU) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)"
 
    3、汇编阶段
    GCC把编译生成的.s文件转换为目标文件.o。这时使用-c选项就可以看到汇编代码已经转换成.o的目标代码了。
[armlinux@lqm program]$ gcc -c hello.s -o hello.o
    4、链接阶段
    成功编译之后,就进入了链接阶段。这里首先要明白“库”的概念。这个程序中没有“printf”的函数实现,且在预处理阶段包含进来的“stdio.h”中只有该函数的声明,而没有定义函数的实现。如何实现“printf”?答案是:系统把这些函数的实现都做到名位libc.so.6的库文件里了,没有特别指定时,GCC会到默认的搜索路径“/usr/lib”下进行查找。也就是链接到libc.so.6库函数中去来实现函数“printf”,这就是链接的作用。
    在RedHat 9下的函数库如下:
    /lib:系统必备共享库
    /usr/lib:标准共享库和静态库
    /usr/X11R6/lib:X11R6的函数库
    /usr/local/lib:本地函数库
    头文件:
    /usr/include:系统头文件
    /usr/local/include:本地头文件
    在/etc/ld.so.conf中包含着共享库的搜索位置。我的libc.so.6在/lib下面,它是一个link,指向libc-2.3.2.so。这是因为我用的C库--glibc版本是2.3.2。
    函数库一般可分为静态库和动态库两种。静态库是指链接时把库文件的代码全部加到可执行文件中,因此生成的文件比较大,但是在运行时就不再需要库文件了。其后缀名一般为“.a”。动态库在链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”。GCC在编译时默认使用动态库。
 
[armlinux@lqm program]$ gcc hello.o -o hello1
[armlinux@lqm program]$ ls -l hello1
-rwxrwxr-x    1 armlinux armlinux    11582  8月 28 17:42 hello1
[armlinux@lqm program]$ file hello1
hello1: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not sd
[armlinux@lqm program]$ gcc -static hello.o -o hello2
[armlinux@lqm program]$ ls -l hello2
-rwxrwxr-x    1 armlinux armlinux   423442  8月 28 17:43 hello2
[armlinux@lqm program]$ file hello2
hello2: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, statically linked, not stripped
[armlinux@lqm program]$ ./hello1
Hello World 1 times!
Hello World 2 times!
Hello World 3 times!
Hello World 4 times!
Hello World 5 times!
Hello World 6 times!
Hello World 7 times!
Hello World 8 times!
[armlinux@lqm program]$ ./hello2
Hello World 1 times!
Hello World 2 times!
Hello World 3 times!
Hello World 4 times!
Hello World 5 times!
Hello World 6 times!
Hello World 7 times!
Hello World 8 times!
    hello2是静态编译,大小423442,是动态编译的36.56倍。利用file可以看出此文件statically linked,还是dynamically linked (uses shared libs)。
 
    至此,GCC的整个编译链接过程就完成了。

Linux中gcc编译过程分解

GCC编译过程分解 以helloworld为例分析gcc编译过程: #include int main() {          printf(“Hello World\n”); ...
  • fighting_kangle
  • fighting_kangle
  • 2016年07月07日 19:14
  • 439

一个C程序的编译过程(Linux环境下Gcc)

一 以下是C程序一般的编译过程:  从图中看到:      将编写的一个c程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译阶段  和链接这两个阶段。      其中,      ...
  • gengyichao
  • gengyichao
  • 2011年06月14日 17:03
  • 13337

gcc程序的编译过程和链接原理

一、C/C++文件的编译过程:先来看一下gcc的使用方法和常用选项 提示:gcc --help Ⅰ、使用方法:gcc [选项] 文件名Ⅱ、常用选项: 选项 含义 -v 查看gc...
  • czg13548930186
  • czg13548930186
  • 2017年10月24日 17:02
  • 525

Gcc的编译流程分为了四个步骤:

Gcc的编译流程分为了四个步骤:     1.预处理,生成预编译文件(.文件):         Gcc –E hello.c –o hello.i     2.编译,生成汇编代码(.s...
  • xiaohouye
  • xiaohouye
  • 2016年08月01日 13:11
  • 17838

Linux下Gcc 的编译过程

在linux下开发难免会用到gcc编译,GCC(GNU Compiler Collection,GNU编译器套装),是由 GNU 开发的编程语言编译器。它是GNU编译器套装以GPL许可证所发行的自由软...
  • wdxin1322
  • wdxin1322
  • 2014年10月27日 13:50
  • 1215

GCC 显示程序详细编译-链接过程

很多时候,我们对于程序的编译和链接过程很少关注。特别是使用强大的IDE之后,更多人只是会使用IDE进行编程。这样,一旦出现编译或者链接问题,有时候会很难找到编译或者链接问题。理解编译和链接的过程,对于...
  • faithzzf
  • faithzzf
  • 2016年06月21日 10:10
  • 2414

gcc命令及编译过程

1简介 2简单编译 2.1预处理 2.2编译为汇编代码(Compilation) 2.3汇编(Assembly) 2.4连接(Linking) 3多个程序文件的编译 4检错 5库文件连...
  • swqqcs
  • swqqcs
  • 2012年09月04日 17:01
  • 538

gcc编译器中编译阶段的四个过程

 编译阶段的四个过程 1.预处理 gcc -E 文件名.c 经过预处理形成.i文件 预处理阶段三个过程:头文件展开;宏替换;条件编译; 2.编译 gcc -c 文件名.c ...
  • hunter233666
  • hunter233666
  • 2016年10月30日 23:59
  • 251

GCC 编译过程

GNU CC(简称为Gcc)是GNU项目中符合ANSI C标准的编译系统,能够编译用C、C++和Object C等语言编写的程序。Gcc不仅功能强大,而且可以编译如C、C++、Object C、Jav...
  • struggle6688
  • struggle6688
  • 2016年04月01日 21:08
  • 218

GCC编译过程

gcc的编译流程分为四个步骤,分别为: · 预处理(Pre-Processing) · 编译(Compiling) · 汇编(Assembling) · 链接(Linking) 以hello...
  • xiazailushang
  • xiazailushang
  • 2013年09月29日 14:57
  • 493
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:gcc 编译过程
举报原因:
原因补充:

(最多只允许输入30个字)