马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
媒介:初学C语言的时候是在Linux环境下,那时候只知道需要通过GCC工具编译成可执行文件才可以在运行,厥后进入到了嵌入式行业发现需要IDE将一个C项目工程编译成一个固件包,那时候经常会产生一个疑问:一个C项目工程在IDE中是怎么一步步编译成一个固件包的呢?下面就解答一下这个疑问。时光荏苒,也算是给当年刚入行的本身一个答案。
1️⃣,流程简述
将一个 C 项目工程 从 源代码 编译成 固件包(hex、bin、elf 等) 的过程,涉及 编译工具链 和 IDE 的工作原理。一样寻常来说,固件编译流程分为以下关键步骤:
这个过程通常由 编译工具链(如 GCC、IAR、Keil、Clang 等)完成,而 IDE(如 Keil、STM32CubeIDE、IAR 等)负责调用这些工具链,并提供一个图形化的界面来简化开辟流程
- 源码 (C/ASM/头文件)
- ↓
- 预处理器 (Preprocessor)
- ↓
- 编译器 (Compiler)
- ↓
- 汇编器 (Assembler)
- ↓
- 链接器 (Linker)
- ↓
- 固件包 (HEX/BIN/ELF 文件)
复制代码 对应的执行流程框图如下:
2️⃣,预处理(Preprocessing)
预处理器会在编译前对源代码举行 文本更换和展开,重要包括:
- 处理 #include 头文件的引用。
- 更换宏定义(#define)。
- 处理条件编译指令(#ifdef、#ifndef、#endif 等)。
- 移除注释。
举个例子:下面的这个是源代码
- #include "my_header.h"
- #define LED_PIN 13
- void main() {
- int pin = LED_PIN;
- }
复制代码 当预处理之后:
- void main() {
- int pin = 13;
- }
复制代码 对应的预处理工具与命令:(最经典的就是GCC,当然如果是其他的芯片环境平台大概就需要用到交叉编译工具了)
GCC: gcc -E main.c -o main.i
3️⃣,编译(Compilation)
预处理完成的 .i 文件(纯文本 C 代码)会被编译器转换成 汇编代码。
- 编译器的任务:
- 语法分析,检查代码的语法和语义。
- 天生对应的汇编代码(.s 文件)
同样是上面的例子:编译后的汇编代码:
- mov r0, #13
- str r0, [sp, #4]
复制代码 编译工具:
- GCC: gcc -S main.i -o main.s
4️⃣,链接(Linking)
链接器的任务是将多个 目标文件(.o 文件)、库文件(.a 或 .lib 文件)、启动文件(startup 文件) 合并成一个 可执行的固件文件(.elf/.bin/.hex)。
- 链接的工作内容:
- 解析和解决函数、变量的外部引用。
- 合并不同模块的目标文件。
- 分配内存地址(根据链接脚本 linker script)。
- 天生可执行文件(如 .elf、.bin、.hex)。
链接工具:
- GCC: gcc main.o -o main.elf
-T linker_script.ld
示例:
如果有多个文件:
- main.o // 主程序
- startup.o // 启动代码
- libc.a // 标准库
复制代码 链接后的 ELF 文件:
|