宁睿 发表于 2025-1-14 20:43:32

【嵌入式常识篇】一个C项目工程在IDE中是怎么一步步编译成一个固件包的

媒介:初学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 文件)
对应的执行流程框图如下: 
https://i-blog.csdnimg.cn/direct/d5ed7532096f4974a35ed8097af9a5c4.png
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,
    编译工具:


[*]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 文件:
main.elf
   
页: [1]
查看完整版本: 【嵌入式常识篇】一个C项目工程在IDE中是怎么一步步编译成一个固件包的