gcc的简单使用

1 概述

══════


  GNU编译工具集(即GCC)包含一个编译器和一套将高层源码生成二进制文件的工具
  集。GCC不仅是GNU/Linux上事实上的编译器,还是嵌入式系统开发的标准编译器。
  这里只是简单的了解下GCC的基本特点和一些高级特点(如优化),GCC的全部功能
  还需要去看官方的文档。[http://gcc.gnu.org/]




2 编译简介

══════════


  阶段:预编译—>编译—>汇编—>链接各编译阶段的输入与输出:
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   阶段    输入  输出  GCC示例                 
   预编译  *.c   *.i   gcc -E test.c -o test.i 
   编译    *.i   *.s   gcc -S test.i -o test.s 
   汇编    *.s   *.o   gcc -c test.s -o test.o 
   链接          *.o   gcc test.o -o test      
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


  在预处理阶段,源文件和包含的头文件一起处理。在这一些阶段,对#ifdef这类
  的预编译指令进行解析,然后通过编译阶段的编译为汇编做准备,在汇编阶段,
  文件转化为相应的机器指令,生成目标文件。最后将这些机器码链接起来(有可
  能与其他机器码链接)形成可执行的二进制文件。




3 GCC的格式

═══════════


  将源文件编译成可执行文件:$ gcc test.c -o test这样就生成了一个test的可
  执行文件(-o 就是输出选项)。如果希望生成源文件的目标文件,可以使用-c选
  项$ gcc -c test.c这样生成的目标文件默认为test.o,也可以强制要求生成其他
  名字。$ gcc -c test.c -o newtest.o当有多个源文件时, 使用下面的命令能
  够将三个源文件编译并链接为一个名为 goal的可执行文件$ gcc -o goal
  first.c second.c third.c注意:如果只是把一个源文件编译为目标文件,那么
  因为链接还没有开始,所以源文件不需要一定有main函数。




4 有用的选项

════════════


  1.在很多情况下,保存头文件的目录与保存源文件的目录不是同一个。如:源程
  序保存在./src中,头文件在./inc中。我们可以在./src目录中编译程序,告诉
  gcc头文件在./inc中。$ gcc test.c -I ../inc -o test可以重复使用I格式来
  指定包含多个子目录: $ gcc test.c -I ../inc —I ../../inc2 -o test 2.为
  了配置软件,可以在编译的时候指定符号常量如在源文件或头文件中定义符号常
  量:#define TEST可以在命令行中使用-D定义:$ gcc -D TEST test.c -o test
  3.用于汇编而不用于源码编译阶段的选项,如:$ gcc -c -g -Wa, -ahl, -L
  test.c -Wa选项将后续选项直接传递到汇编阶段供汇编器使用。




5 编译警告

══════════


  最常用的检查普通警告的选项是-Wall,它打开经常遇到问题的警告。$ gcc
  -Wall test.c -o test -Wall 有一个含义相同的命令:-all-warings -Wall选
  项打开的警告选项
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   选项名称                       用途                                                
   unused-function                无定义但有声明的静态函数时警告                      
   unused-label                   声明但未使用的符号警告                              
   unused-parameter               声明但未使用的函数参数警告                          
   unused-variable                未使用的本地声明的变量                              
   unused-value                   计算机得到却没有被使用的值警告                      
   format                         检验printf等,确认参数一致                          
   implicit-int                   没有规定类型的声明时警告                            
   implicit-function-declaration  调用未经声明的函数时警告                            
   char-subscripts                数组以char类型做下标时警告                          
   missing-braces                 聚合初始化两边缺少括号时警告                        
   parentheses                    缺少的()可能导致意义含混时警告                      
   return-type                    函数声明不指定返回值类型或指明了没有return          
   sequence-point                 存在可疑的代码元素(如 a[i] = c[i++])                
   switch                         对于没有default的switch语句,如果在case中未列出警告 
   strict-aliasing                对变量别名进行严格检查                              
   unknown-pragmas                不可识别的#pragma指令时警告                         
   uninitialized                  使用未初始化的变量警告(仅在-o2优化下生效)           
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


  大多数的选项都有一个否定形式,用来将他们关掉。如你打开了-Wall选项,想
  要关闭unused警告集,可以输入下面的命令。$ gcc -Wall -Wno -unused
  test.c -o test除了-Wall打开的警告,还有一些其他有用的警告。


  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   选项名称               用途                                                             
   cast-align             只要有指针被强制类型转换而导致需要的地址对其边界扩展时,发出警告 
   sign-compare           有符号类型与无符号类型进行比较,可能导致错误的结果时,发出警告   
   missing-prototypes     没有预先声明函数就使用全局函数时,发出警告                       
   Packed                 结构体带有packed属性而实际上并没有用到紧缩式时,发出警告         
   Unreachable-code       存在根本不会被执行的代码时,发出警告                             
   Inline                 标记为inline的函数不能内联时警告                                 
   Disabled-optimization  优化器不能优化某项指定的优化时(优化时间太长或资源太多),发出警告 
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


  最后有一个-Werror选项,使编译器把所有的警告当做错误处理。这样编译可以
  确保代码高质量。




6 GCC优化器

═══════════


  实际上,优化工作有三个各不相容的方向:1.速度更快,文件更小2.速度更快,
  允许文件变大3.减小文件,允许程序变慢


  优化设置及其说明:
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   优化等级  说明                                                                                       
   -O0       不进行优化(默认等级)                                                                       
   -O, -O1   尝试同时缩短编码时间和减小映像文件                                                         
   -O2       比O1更多的优化,只在不导致文件增大时进行加快速度的优化,只在不导致速度变慢时减小文件的优化 
   -Os       以减小结果文件为优化目标                                                                   
   -O3       更多的优化                                                                                 
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


  $ gcc -Os test.c -o test




6.1 -O0优化

─────


  在这个等级,编译器只生成简单的代码,能够保证得到预期的结果,易于采用调
  试工具进行调试,编译的速度会快很多。




6.2 -O1优化

─────


  这个等级的目标是尽可能快的编译,让结果文件代码尽量小,运行速度尽量
  快。-O1的各项优化选项
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   优化选项                  说明                                                   
   defer-pop                 推迟从堆栈中弹出函数参数,知道该参数确实被使用时才弹出 
   thread-jumps              执行线程跳转优化(避免从一个跳转跳到另一个跳转)         
   branch-probabilities      采用分支整形来优化分支结构                             
   cprop-register            采用复制生成的方式来优化寄存器之间的传值               
   guess-branch-probability  打开分支预测功能                                       
   omit-frame-pointer        不产生栈帧(如果可以的话)                               
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


  如果需要安全的调整结果镜像,-O1优化是一个安全的优化等级可以使用-f选项
  明确指出具体的优化功能。如可以用-f-defer-pop打开该优化选项,如果要关掉,
  可以使用否定格式:-fno-defer-pop




6.3 -O2优化

─────


  这个优化等级包括了更多的优化(包括-O1的优化) -O2的优化
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   优化选项                    说明                                        
   align-loops                 对齐循环的起点                              
   align-jumps                 对齐仅通过跳转可达的标签                    
   align-labels                对其所有标签                                
   align-function              对其所有函数的起点                          
   optimize-sibling-calls      优化兄弟和尾部递归调用                      
   cse-follow-jumps            执行CSE时跟随跳转至其目标                   
   cse-skip-blocks             执行CSE时,跟随条件跳转                     
   gcse                        执行全局公共子表达式的消除                  
   expensive-optimizations     执行一套高成本的优化                        
   strength-reduce             执行降低强度的优化                          
   rerun-cse-after-loop        在循环优化后再运行CSE                       
   caller-saves                在调用函数前保存寄存器,在返回时恢复它们    
   force-mem                   在使用前将内存中的操作数复制到寄存器中      
   peepole2                    在sched2之前激活一个与机器相关的深度优化rt1 
   regmove                     打开寄存器迁移优化                          
   strict-aliasing             认为源代码遵守了严格命名规则                
   delete-null-pointer-checks  删除无用的空指针检查                        
   reorder-blocks              对基本块进行重排序以改善代码的布局          
   schedule-insns              对寄存器分配之前重新安排指令                
   schedule-insns2             在寄存器分配之后重新安排指令                
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━




6.4 -Os优化

─────


  这个等级就是-O2的优化,除去那些可能增大结果映像的选项-Os关闭的选项
  为:-falign-loops, -falign-jumps, -falign-labels, -falign-functions。




6.5 -O3优化

─────


  这个等级在O2的优化上新增了优化
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   优化选项            说明                                                       
   -finline-functions  把简单函数内联到调用函数中                                 
   -frename-registers  为拥有大量寄存器的架构优化寄存器的分配(这将加大调试的难度) 
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━




7 架构相关优化

══════════════


  -mcpu选项告诉编译器生成针对特定CPU类型的指令。




8 调试选项

══════════


  如果想用符号调试器来调试代码,可以用-g来指定在映像中为GDB调试信息。-g
  可以带一个参数,用来指定调试信息的格式。如想要生成dwarf-2的调试信息,
  可以使用下面的命令:$ gcc -gdwarf-2 test.c -o test




9 其他工具

══════════


9.1 size工具

──────


  size工具给出text大小(指令数),data段,bss段




9.2 objdump工具

───────


  能够得到有关映像的更详尽的细节,使用–syms参数可以得到符号列表$ objdump
  –syms test.o使用–disassemble参数可以反汇编文件




9.3 mm工具

─────


  有助于理解在目标文件中出现的符号


有关GCC的更全面的介绍,请看官方文档:http://gcc.gnu.org/

有关GNU/Linux的介绍:https://www.gnu.org/

你可能感兴趣的:(学习笔记,Linux)