STM32 裸机编程 04 - Makefile 构建自动化

Makefile:构建自动化

我们可以用 make 命令行工具替代手动敲入"编译"、"链接"、"烧写"这些命令,自动完成整个过程。make 工具使用一个名为 Makefile 的配置文件,从中读取执行动作的指令。这种自动化方式非常棒,因为这样可以把构建固件的过程、使用了哪些编译标记等也文档化。

在 https://makefiletutorial.com 上有一个非常好的给初学者的 Makefile 教程,强烈建议看一下。下面我将列出一些非常必要的概念以理解我们所使用的 Makefile。对于已经很熟悉 make 的朋友,可以跳过这一部分。

其实 Makefile 的格式并不复杂:

复制代码
action1:
	command ...     # Comments can go after hash symbol
	command ....    # IMPORTANT: command must be preceded with the TAB character

action2:
	command ...     # Don't forget about TAB. Spaces won't work!

现在我们可以跟动作名(也被称作目标)一起调用 make 来执行相应的动作:

复制代码
$ make action1

当然,也可以在命令中定义和使用变量,动作也可以是需要创建的文件名:

复制代码
firmware.elf:
	COMPILATION COMMAND .....

任何动作都可以有一个依赖列表。例如,firmware.elf 依赖源文件 main.c,当 main.c 改变时,make build 就会重新构建 firmware.elf:

复制代码
build: firmware.elf

firmware.elf: main.c
 COMPILATION COMMAND

我们已经准备好为固件编写 Makefile,定义一个 build 动作/目标:

复制代码
CFLAGS  ?=  -W -Wall -Wextra -Werror -Wundef -Wshadow -Wdouble-promotion \
            -Wformat-truncation -fno-common -Wconversion \
            -g3 -Os -ffunction-sections -fdata-sections -I. \
            -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 $(EXTRA_CFLAGS)
LDFLAGS ?= -Tlink.ld -nostartfiles -nostdlib --specs nano.specs -lc -lgcc -Wl,--gc-sections -Wl,-Map=$@.map
SOURCES = main.c

build: firmware.elf

firmware.elf: $(SOURCES)
	arm-none-eabi-gcc $(SOURCES) $(CFLAGS) $(LDFLAGS) -o $@

在这里我们定义了一些编译标记。?= 表示这是默认值,我们可以在命令行中覆盖它们,像这样:

复制代码
$ make build CFLAGS="-O2 ...."

上面的 Makefile 文件中定义了 CFLAGS、LDFLAGS、SOURCES 变量,然后我们告诉 make ,当要 build 时创建 firmware.elf 文件,它依赖 main.c 文件,使用 arm-none-eabi-gcc 编译器和给定的编译标记生成它。$@ 特殊变量会被展开成动作/目标名,在这个例子中是 firmware.elf。

现在调用 make 试一下:

复制代码
$ make build
arm-none-eabi-gcc main.c  -W -Wall -Wextra -Werror -Wundef -Wshadow -Wdouble-promotion -Wformat-truncation -fno-common -Wconversion -g3 -Os -ffunction-sections -fdata-sections -I. -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16  -Tlink.ld -nostartfiles -nostdlib --specs nano.specs -lc -lgcc -Wl,--gc-sections -Wl,-Map=firmware.elf.map -o firmware.elf

如果我们再次运行:

复制代码
$ make build
make: Nothing to be done for `build'.

make 会检查 firmware.elf 和依赖项 main.c 的修改时间,如果是它们是最新的,则什么都不做。如果我们修改下 main.c,则会重新构建:

复制代码
$ touch main.c # Simulate changes in main.c
$ make build

现在,还剩下"烧写"这个动作/目标:

复制代码
firmware.bin: firmware.elf
	arm-none-eabi-objcopy -O binary $< $@

flash: firmware.bin
	st-flash --reset write $(TARGET).bin 0x8000000

OK,现在从终端中执行命令 make flash 就会创建 firmware.bin 文件,然后通过 st-link 烧入板子。当 main.c 改变时,这个命令也会重新构建,因为 firmware.bin 依赖 firmware.elf,firmware.elf 又依赖 main.c。所以我们的开发循环就是这样的两步:

复制代码
# Develop code in main.c
$ make flash

还有一个良好实践就是在 Makefile 中添加 clean 动作,以删除构建生成的文件:

复制代码
clean:
 rm -rf firmware.*

完整工程源码可以在 step-0-minimal1 文件夹找到。

相关推荐
挨踢诗人8 分钟前
玄讯CRM集成金蝶云星空解决方案
自动化
赵大仁16 分钟前
开源清单怎么维护才不烂掉?GitHub Actions 每周查死链 + 软 404 检测实录
python·ci/cd·自动化·开源项目·踩坑·github actions·json schema
学心理学的程序员26 分钟前
腾讯开源 BrowserSkill:让 AI 直接接管你登录好的真实浏览器,自动化再也不用重新登录一遍
人工智能·开源·自动化
ccbw1636 分钟前
CH32M007K8U7:集成48V三相预驱的RISC-V电机MCU
单片机·嵌入式硬件
xixiaoyunya1 小时前
实验室检测数据内网自动化备份方案:满足合规可追溯的落地实践
服务器·网络·自动化
编程圈子2 小时前
I.MX6U 裸机开发 24. 电容触摸屏与 I2C 驱动
单片机·嵌入式硬件
天远数科2 小时前
零信任架构实战:基于天远风控经营异常预警构建自动化电子签章前置合规网关
运维·人工智能·架构·自动化
FakeOccupational3 小时前
【电路笔记 STM32】Cortex-M7 UART 中断模式(串口接收中断+串口空闲中断)
笔记·stm32·单片机
小李不想当小白3 小时前
USART串口协议(STM32标准库学习笔记)
经验分享·笔记·stm32·单片机·嵌入式硬件·学习
YH行业报告分析4 小时前
2026电缆铺设设备市场:自动化敷设与电网升级驱动增长
运维·自动化