Linux-开发与管理 P2 GCC编译器
文章目录
Linux-开发与管理 P2 GCC编译器
编译器简介
简介
GCC(GNU Compiler Collection)是一套由GNU开发的编程语言编译器,原本它只能处理C语言,原名GNU C语言编译器(GNU C Compiler)。但GCC很快的扩展,支持更多的编程语言,如Java、Go、Fortran、Objective-C,所以才改成现在的名字。
GCC是一个交叉平台编译器,能够在当前CPU平台上为多种不同体系结构的硬件平台开发软件,非常适合嵌入式的开发
支持编译的源文件类型
GCC支持编译的一些源文件的后缀及其解释
后缀 | 功能 |
---|---|
.c | C语言程序源代码 |
.a | 由目标文件构成的文件库 |
.C .cc .cpp | C++语言程序源码 |
.h | C/C++源码的头文件 |
.i | 经过预处理的C源码 |
.ii | 经过预处理的C++源码 |
.s | 汇编语言文件源码 |
.o | 目标文件 |
.so | 动态库文件 |
GCC编译流程
对C文件进行编译的基本过程由四部分组成
1.预处理(Pre-Processing)
2.编译(Compiling)
3.汇编(Assembling)
4.链接(Linking)
举个栗子
一个hello.c文件,经过预处理过程,将会生成hello.i的预处理文件
hello.i预处理文件通过编译,生成hello.s的汇编文件
hello.s汇编文件通过汇编过程,生成目标文件hello.o
最后hello.o会通过链接过程进行链接,最终生成hello.out可执行文件
GCC指令一般格式
gcc [选项] 要编译的文件 [选项] [目标文件]
[ ]里的都是可选内容
所以最简单的写法是gcc+要编译的文件,可以直接生成a.out可执行文件
举个栗子
#include <stdio.h>
int main(int argc, const char *argv[])
{
printf("Hello Cage\n");
return 0;
}
但是有时候需要用到中间的文件,也为了更好的理解编译的过程,下面将依次讲解GCC编译的四个过程
预处理(Pre-Processing)
对编写好的hello.c进行预处理编译生成hello.i文件
gcc -E hello.c -o hello.i
-E 是对文件仅做预处理而不做其他后续处理的选项,将会在后面的编译选项里详细讲解
可以来看看hello.i预处理文件里的内容
上面都是一些外部调用的内容,只有最后几句是我们自己编写的内容
编译(Compiling)
然后对预处理文件进行编译,编译的过程中会对代码的规范性、是否有语法错误等进行检测,如果没有问题将其翻译成汇编语言
gcc -S hello.i -o hello.s
接下来看看汇编语言里的内容
.file "hello.c"
.section .rodata
.LC0:
.string "Hello Cage"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $16, %esp
movl $.LC0, (%esp)
call puts
movl $0, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
.section .note.GNU-stack,"",@progbits
这里如果大家学过汇编语言还是看的懂一些的,虽然不同的嵌入式设备汇编语言会有区别
后期也会专门开个讲解汇编语言的系列
汇编(Assembling)
好的,接下就是将汇编程序转换为目标文件,也就是hello.o,hello.o是二进制目标代码
gcc -c hello.s -o hello.o
好的,来看看生成的hello.o目标文件
链接(Linking)
接下来进入最后一步,链接阶段,链接部分会自动链接到/usr/lib地址下查找头文件,从而链接了函数库里的函数进行调用,以实现程序里调用函数的功能,最终实现程序
gcc hello.o -o hello.out
你就会发现它跟之前生成的a.out具有相同的输出结果,说明成功通过GCC编译的基本四个步骤获得可想要的可执行文件
编译选项
GCC有超过100个的可用选项,主要包括总体选项、警告和出错选项以及优化选项等
这里对经常和主要用到的可用选项进行讲解
总体选项
可用选项 | 功能 |
---|---|
-E | 进对文件进行预处理,不进行编译、汇编和链接 |
-S | 编译到汇编语言不进行汇编和链接 |
-c | 编译到目标代码 |
-o | 文件输出到文件 |
-static | 禁止使用动态库,编译出来的东西一般都很大,也不需要什么动态链接库即可运行 |
-share | 尽量使用动态库,所以生成文件较小,但是需要系统有动态库 |
-I dir | 在头文件的搜索路径列表中添加dir目录 |
-L dir | 在库文件的搜索路径列表中添加dir目录 |
-llibrary | 链接名为library的库文件 |
-ansi | 只支持ANSI标准的C语法 |
-g | 生成调试信息,GNU调试器可利用该信息 |
-m486 | 针对486进行代码优化 |
-shared | 生成共享目标文件,通常用在建立共享库时 |
警告和出错选项
对于警告和出错选项
主要是**-Wall**
打开所有类型语法警告,建议在编译的时候最好用上