加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 钦州站长网 (https://www.0777zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

嵌入式linux运行编译器,嵌入式Linux编译器GCC编译流程

发布时间:2022-10-17 12:37:06 所属栏目:Linux 来源:
导读:  作为自由软件的旗舰项目,Richard Stallman在十多年前刚开始写作GCC的时候,还只是仅仅把它当作一个C程序语言的编译器,GCC的意思也只是GNU C Compiler而已。

  经过了这么多年的发展,嵌入式Linux编译器G
  作为自由软件的旗舰项目,Richard Stallman在十多年前刚开始写作GCC的时候,还只是仅仅把它当作一个C程序语言的编译器,GCC的意思也只是GNU C Compiler而已。
 
  经过了这么多年的发展,嵌入式Linux编译器GCC已经不仅仅能支持C语言,它现在还支持Ada语言、C++语言、Java语言、Objective C语言、PASCAL语言、COBOL语言,并支持函数式编程和逻辑编程的Mercury语言等。而GCC也不再单指GNU C语言编译器的意思了,而是变成了GNU编译器家族了。
 
  GCC的编译流程分为了4个步骤,分别如下。
 
  ·预处理(Pre-Processing)。
 
  ·编译(Compiling)。
 
  ·汇编(Assembling)。
 
  ·链接(Linking)。
 
  编译器通过程序的扩展名可分辨编写原始程序码所用的语言,由于不同的程序所需要执行编译的步骤是不同的,因此GCC根据不同的后缀名对它们进行分别处理,表1.1指出了不同后缀名的处理方式。
 
  GCC所支持后缀名解释
 
  d985f0ec14167fa3d0a4ab51ded2537d.png
 
  表1.1
 
  GCC使用的基本语法为:
 
  gcc [option | filename]
 
  这里的option是GCC使用时的一些选项,通过指定不同的选项GCC可以实现其强大的功能。这里的filename则是GCC要编译的文件,GCC会根据用户所指定的编译选项以及所识别的文件后缀名来对编译文件进行相应的处理。
 
  本节从编译流程的角度讲解GCC的常见使用方法。
 
  首先,这里有一段简单的C语言程序,该程序由两个文件组成,其中“hello.h”为头文件,在“hello.c”中包含了“hello.h”,其源文件如下所示。
 
  /*hello.h*/
 
  #ifndef _HELLO_H_
 
  #define _HELLO_H_
 
  typedef unsigned long val32_t;
 
  #endif
 
  /*hello.c*/
 
  #include < stdio.h>
 
  #include < stdlib.h>
 
  #include "hello.h"
 
  int main()
 
  {
 
  val32_t i = 5;
 
  printf("hello, embedded world %d\n",i);
 
  }
 
  1.预处理阶段
 
  GCC的选项“-E”可以使编译器在预处理结束时就停止编译,选项“-o”是指定GCC输出的结果,其命令格式为如下所示。
 
  gcc –E –o [目标文件] [编译文件]
 
  表2.6指出后缀名为“.i”的文件是经过预处理的C原始程序。要注意,“hello.h”文件是不能进行编译的,因此,使编译器在预处理后停止的命令如下所示。
 
  [[emailprotected] gcc]# gcc –E –o hello.i hello.c
 
  在此处,选项“-o”是指目标文件,由表2.6可知,“.i”文件为已经过预处理的C原始程序。以下列出了hello.i文件的部分内容。
 
  # 2 "hello.c" 2
 
  # 1 "hello.h" 1
 
  typedef unsigned long val32_t;
 
  # 3 "hello.c" 2
 
  int main()
 
  {
 
  val32_t i = 5;
 
  printf("hello, embedded world %d\n",i);
 
  }
 
  由此可见,GCC确实进行了预处理,它把“hello.h”的内容插入到hello.i文件中了。
 
  2.编译阶段
 
  编译器在预处理结束之后,GCC首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,就开始把代码翻译成汇编语言,GCC的选项“-S”能使编译器在进行完汇编之前就停止。由表1.1可知,“.s”是汇编语言原始程序,因此,此处的目标文件就可设为“.s”类型。
 
  [[emailprotected] gcc]# gcc –S –o hello.s hello.i
 
  以下列出了hello.s的内容,可见GCC已经将其转化为汇编了,感兴趣的读者可以分析一下这一行简单的C语言小程序用汇编代码是如何实现的。
 
  .file "hello.c"
 
  .section .rodata
 
  .LC0:
 
  .string "hello, embedded world %d\n"
 
  .text
 
  .globl main
 
  .type main, @function
 
  main:
 
  pushl%ebp
 
  movl%esp, %ebp
 
  subl$8, %esp
 
  andl$-16, %esp
 
  movl$0, %eax
 
  addl$15, %eax
 
  addl$15, %eax
 
  shrl$4, %eax
 
  sall$4, %eax
 
  subl%eax, %esp
 
  movl$5, -4(%ebp)
 
  subl$8, %esp
 
  pushl-4(%ebp)
 
  pushl$.LC0
 
  callprintf
 
  addl$16, %esp
 
  leave
 
  ret
 
  .size main, .-main
 
  .section .note.GNU-stack,"",@progbits
 
  . .ident "GCC: (GNU) 4.0.0 20050519 (Red Hat 4.0.0-8)"
 
  可以看到,这一小段C语言的程序在汇编中已经复杂很多了,这也是C语言作为中级语言的优势所在。
 
  3.汇编阶段
 
  汇编阶段是把编译阶段生成的“.s”文件生成目标文件,读者在此使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码了,如下所示。
 
  [[emailprotected] gcc]# gcc –c hello.s –o hello.o
 
  4.链接阶段
 
  在成功编译之后,就进入了链接阶段。在这里涉及一个重要的概念——函数库。
 
  在这个程序中并没有定义“printf”的函数实现,在预编译中包含进的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实现“printf”函数的呢?
 
  最后的答案是:系统把这些函数实现都已经被放入名为libc.so.6的库文件中去了,在没有特别指定时,GCC会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到libc.so.6库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用。
 
  完成了链接之后,GCC就可以生成可执行文件linux编译器,其命令如下所示。
 
  [[emailprotected] gcc]# gcc hello.o –o hello
 
  运行该可执行文件,出现正确的结果。
 
  [[emailprotected] gcc]# ./hello
 
  hello, embedded world 5。
 

(编辑:PHP编程网 - 钦州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!