GCC | GCC编译器

 

gcc编译器

GCC(GNU Compiler Collection,GNU编译器套装)是一套由GNU开发的编程语言编译器。它是一套以GPL及LPGL许可证所发行的自由软件,也是GNU计划的关键部分,亦是自由的类UNIX及苹果电脑MAC Os X操作系统的标准编译器。GCC原名为GNU C语言编译器(GNU C Compiler),因为它原本只能处理C语言。GCC很快的扩展,变得可处理C++。之后可处理Fortrna、Pascal、Objecttive-c、java、Ada,以及Go与其他语言。GCC是一个交叉平台平台编译,能够在当前GPU平台上为多种不同体系结构的硬件平台开发软件,因此适合在嵌入式领域的开发编译。

以下是gcc支持编译的一些源文件的后缀及其解释:

  • .c,C语言源代码;

  • .h,程序所包含的头文件;

  • .i,已经预处理过的C源代码文件;

  • .s,汇编语言源代码文件;

  • .o,编译后的目标文件;

1.gcc编译流程及编译选项分析

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

  • 预处理(Pre-Processing);
  • 编译(Compiling);
  • 汇编(Assembing);
  • 链接(Linking);

源码:

#include <stdio.h>

int main(int argc, char* argv[])
{
   printf("Hello, wolrd.\n");
   return 0;
}

Make文件:

.PHONY:all clean
CC      = gcc

all:
       $(CC) -E hello.c -o hello.i
       $(CC) -S hello.i -o hello.s
       $(CC) -c hello.s -o hello.o
       $(CC) hello.o -o hello

clean:
       rm -rf *.i *.s *.o hello

GCC

1-1.预处理阶段

在该阶段,编译器将上述代码中的stdio.h编译进来,并且用户可以使用gcc的选项“-E”进行查看。该选项的作用是让gcc在预处理结束后停止编译过程。

1-2.编译阶段

接下来进行的是编译阶段。在这个阶段中,gcc首先检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作。在检查无误后,gcc把代码翻译成汇编语言。

用户可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。

1-3.汇编阶段

汇编阶段是把编译阶段生成的“.s”文件转成目标文件。

1-4.链接阶段

在成功编译后,就进入了链接阶段。这里涉及一个重要的概念:函数库。关于实现“printf”函数,在没有特别指定时,gcc会到系统默认的搜索路径“/usr/lib”下进行查找,从而链接到libc.so.6库函数,这样就实现函数printf。这就是链接的作用。

函数库一般分为静态库和动态库。

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

动态库:在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”。

gcc默认在编译时是哦那个动态库,完成链接后,gcc就可以生成可执行文件。

[fly@fly-vm hello]$ make
gcc -E hello.c -o hello.i
gcc -S hello.i -o hello.s
gcc -c hello.s -o hello.o
gcc hello.o -o hello
[fly@fly-vm hello]$ ./hello
Hello, wolrd.

 

2.gcc编译选项分析

gcc有超过100个的可用选项,主要包括总体选项、警告和出错选项、优化选项和体系结构相关选项。以下对每一类中最常用的选项分别进行讲解。

2-1.总体选项

gcc [选项] 文件

-E:使用此选项表示仅作预处理,不进行编译、汇编和链接。

-S:编译到汇编语言不进行汇编和链接。

-c:编译到目标代码。

-o:文件输出到文件。

-static:禁止使用动态库。

-share:尽量使用动态库。

-I dir:在头文件的搜索路径列表中添加dir目录。

-L dir:在库文件的搜索路径列表中添加dir目录。

-llibrary:链接名为library的库文件。

2-2.警告和出错选项

警告是针对程序结构的诊断信息,出现警告程序不一定有错误,而是表明有风险,或者可能存在错误。

-Wall:打开所有类型的语法警告。

-Wcomment:当"/"出现在“/......*/”注释中,或者“\”出现在“//...”注释结尾处时,给出警告。

-fsyntax-only:检查程序中的语法错误,但是不产生输出信息。

-w:禁止所有警告信息。

-Wno-import:禁止所有关于#import的警告信息。

-ansi:强制gcc生成标准语法所要求的告警信息。

-pedantic:打开完全服从ANSI C标准所需的全部警告诊断;拒绝接收采用了被禁止的语法扩展程序。

-predantic-errors:和-pedantic类似,但是显示错误而不是信息。

-g:生成调试信息。GNU调试器(GDB)可以利用该信息。

2-3:优化信息

-O0:无优化(默认)。

-O-O1:使用能减少目标文件大小及执行时间并且不会使编译时间明显增加的优化。在编译大型程序的时候会显著增加编译时内存的使用。

-O2:包含-O1的优化并增加了不需要在目标文件大小和执行速度上进行折衷的优化。编译器不执行循环展开以及内联函数。此选项将增加编译时间和目标文件的执行性能。

-Os:专门优化目标文件大小,执行所有的不增加目标文件大小的-O2优化选项,并且执行专门减少目标文件大小的优化选项。

-O3:打开所有-O2的优化选项并且增加-finline-functions、-funswitch-loops、-fpredictive-commoning、-fgcse-after-reload和-free-vectorize优化目标。

Tips:

虽然优化选项可以加速代码的运行速度,但对于调试而言将是一个很大的挑战。因为代码在经过优化后,原先在程序中声明和使用的变量很可能不再使用,控制流可能会突然跳转到意外的地方,循环语句也有可能因为循环展开而变得到处都有,这些对调试来讲都是一场噩梦。

因此,在调试的时候最好不要使用任何优化选项,只有当程序在最终发行的时候才考虑对其进行优化。

2-4:体系结构相关选项

-mcpu=type:针对不同CPU使用相应的CPU指令。type可选:i386、i486、pentium(i686)。

-mieee-fp:使用IEEE标准进行浮点数的比较。

-mno-ieee-fp:不使用IEEE标准进行浮点数的比较。

-msoft-float:输出包含浮点库调用的目标代码。

-mshort:把int类型作为16位处理,相当于short int。

-mrtd:强行将函数参数个数固定的函数用ret NUM返回,这样可以节省一条调用指令。

3.拓展

GCC参数详解 GCC Gitee仓库 GCC | Ubuntu下编译、安装gcc

https://gitee.com/c-program/mark-down-doc/blob/master/1-LinuxSys/gcc%20compiler.md

posted @ 2021-06-18 09:39  hello,123456  阅读(511)  评论(0编辑  收藏  举报