GCC的编译过程:
GCC编译分为四步,预处理、编译、汇编、链接。具体功能如上图所示,我们在稍微解释一下:
1.预处理:
实现过程:gcc -E xxx.c -o xxx.i
目的:我们的c程序中除了main函数以外,还会有头文件,也就是c最开始的#include ,也有可能会有宏定义#define,预处理就是将头文件展开,并将宏的内容进行替换,并且会将我们写的注释删掉,预处理后生成的文件是 .i 文件。
2.编译:
实现过程:gcc -S xxx.i -o xxx.s
目的:将预处理过后的程序编译为汇编代码,汇编就是用一个符号来代替一条机器码,不同的处理器汇编是不一样的,编译后生成的是 .s 汇编文件。
3.汇编:
实现过程:gcc -c xxx.s -o xxx.o
目的:将汇编文件编译成目标文件,此时的 .o 文件中的信息已经都变为二进制码。
4.链接
实现过程:gcc xxx.o -o xxx
目的:将目标文件与其所需要的库进行链接,最终生成可执行文件xxx。
交叉编译:
交叉编译指的是程序的编译和运行分别在不同的机器上实现,比如在Ubuntu上编译,在开发板上运行。而一个程序想在另一个机器上运行就要与他进行适配,就比如我们在linux中使用gcc 生成的文件就只能在X86下运行,如果将其烧到ARM上就无法运行,若想在ARM上运行就需要使用交叉编译工具,也就是编译时要使用arm-none-linux-guneabi-gcc来编译,此时编译的文件才能在ARM下运行。
由上图可见,使用gcc编译出的可执行文件实在Intel 80386下也就是x86下才可运行,而使用交叉编译出的可执行文件就是在ARM下运行的可执行文件,在x86下就无法运行了。
交叉编译工具是需要下载的,下载方式自行寻找。
五个重要的交叉编译命令
- size:列出目标文件每一段的大小以及总体的大小
- 使用:size + 文件名
- nm:列出目标文件中的符号表(标示符)
- 使用:nm + 文件名
- strip:丢弃目标文件中的符号
- 使用:strip + 文件名,此文件为gcc编译过后的可执行文件,因为这些符号对程序的运行没有影响,所以对于嵌入式开发,这个命令很重要,可以使得我们的代码更加轻量。
- objdump:从目标文件中显示信息
- eg: objdump -d + 文件名 将目标文件反汇编(机器码->汇编)
- objcopy:对目标文件进行复制和转换
- eg:objcopy --gap-fill=0xff -O binary a.out a.bin,将目标文件转换为bin格式