1128 字
6 分钟
Linux下规范性Makefile规则
文件目录
- bsp
- clk (时钟驱动)
- bsp_clk.c
- bsp_clk.h
- delay (延时驱动)
- bsp_delay.c
- bsp_delay.h
- led (LED驱动)
- bsp_led.c
- bsp_led.h
- clk (时钟驱动)
- imx6ul
- cc.h (变量类型声明)
- fsl_common.h (NXP官方SDK通用宏定义文档)
- fsl_iomuxc.h (NXP官方SDK寄存器地址定义文档)
- imx6ul.h (常用头文件)
- MCIMX6Y2.h (NXP官方SDK寄存器结构体和相关位定义文档)
- obj .o文件目标地址
- project
- main.c (主函数)
- start.S (启动文件)
Makefile
CROSS_COMPILE ?= arm-linux-gnueabihf-TARGET ?= bsp
CC := $(CROSS_COMPILE)gccLD := $(CROSS_COMPILE)ldOBJCOPY := $(CROSS_COMPILE)objcopyOBJDUMP := $(CROSS_COMPILE)objdump
INCDIRS := imx6ul \ bsp/clk \ bsp/led \ bsp/delay
SRCDIRS := project \ bsp/clk \ bsp/led \ bsp/delay
INCLUDE := $(patsubst %, -I %, $(INCDIRS))
SFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))
SFILENDIR := $(notdir $(SFILES))CFILENDIR := $(notdir $(CFILES))
SOBJS := $(patsubst %, obj/%, $(SFILENDIR:.S=.o))COBJS := $(patsubst %, obj/%, $(CFILENDIR:.c=.o))OBJS := $(SOBJS) $(COBJS)
VPATH := $(SRCDIRS)
.PHONY: clean
$(TARGET).bin : $(OBJS) $(LD) -Timx6ul.lds -o $(TARGET).elf $^ $(OBJCOPY) -O binary -S $(TARGET).elf $@ $(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis
$(SOBJS) : obj/%.o : %.S $(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<
$(COBJS) : obj/%.o : %.c $(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<
clean: rm -rf $(TARGET).elf $(TARGET).dis $(TARGET).bin $(COBJS) $(SOBJS)细节
工具配置
CROSS_COMPILE ?= arm-linux-gnueabihf- # 交叉编译工具前缀(ARM架构)TARGET ?= bsp # 目标程序名称,默认输出文件名为 `bsp`
CC := $(CROSS_COMPILE)gcc # C 编译器LD := $(CROSS_COMPILE)ld # 链接器OBJCOPY := $(CROSS_COMPILE)objcopy # 二进制转换工具OBJDUMP := $(CROSS_COMPILE)objdump # 反汇编工具目录与文件管理
INCDIRS := imx6ul \ # 头文件搜索目录列表,"\"为换行符 bsp/clk \ bsp/led \ bsp/delay
SRCDIRS := project \ # 源码搜索目录列表,"\"为换行符 bsp/clk \ bsp/led \ bsp/delay
INCLUDE := $(patsubst %, -I %, $(INCDIRS)) # 将 INCDIRS 转换为 gcc 的 `-I` 选项patsubst:
-
函数用法:
$(patsubst <pattern>,<replacement>,<text> -
名称:模式字符串替换函数——patsubst。
-
功能:查找
<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式<pattern>,如果匹配的话,则以<replacement>替换。这里,<pattern>可以包括通配符“%”,表示任意长度的字串。如果<replacement>中也包含“%”,那么<replacement>中的这个“%”将是<pattern>中的那个“%”所代表的字串。(可以用“\”来转义,以“%”来表示真实含义的“%”字符) -
返回:函数返回被替换过后的字符串。
-
示例:
$(patsubst %.c,%.o, a.c b.c),把字串“a.c b.c”符合模式[%.c]的单词替换成[%.o],返回结果是“a.o b.o”
源码文件收集
SFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S)) # 所有 .S 汇编文件CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c)) # 所有 .c C 文件
SFILENDIR := $(notdir $(SFILES)) # 去除路径,保留文件名(如 `start.S`)CFILENDIR := $(notdir $(CFILES)) # 去除路径,保留文件名(如 `main.c`)
SOBJS := $(patsubst %, obj/%, $(SFILENDIR:.S=.o)) # 汇编文件对应的 .o 文件(放在 obj 目录)COBJS := $(patsubst %, obj/%, $(CFILENDIR:.c=.o)) # C 文件对应的 .o 文件(放在 obj 目录)OBJS := $(SOBJS) $(COBJS) # 所有目标文件
VPATH := $(SRCDIRS) # 指定源码搜索路径,Make 会在这些目录中查找依赖文件foreach:
-
用法:
$(foreach <var>, <list>, <expr>) -
功能:遍历
<list>中的每个元素,将元素赋值给<var>,然后展开<expr>,最终将所有展开结果合并成一个空格分隔的字符串。 -
示例中的用法:遍历
SRCDIRS中的每个目录,收集所有.S和.c文件的完整路径。dir依次取SRCDIRS中的值(如project,bsp/clk等)$(wildcard $(dir)/*.S)展开为dir目录下所有.S文件的路径(如project/start.S, bsp/clk/clk.S)。- 最终
SFILES是所有.S文件的路径列表,CFILES是所有.c文件的路径列表。
wildcard:
- 用法:
$(wildcard <pattern>) - 功能:匹配符合
<pattern>的文件路径,支持通配符 * 和 ?。 - 示例中的用法:在
foreach循环中,为每个dir目录生成文件列表。
生成二进制文件
$(TARGET).bin : $(OBJS) # 依赖所有 .o 文件 $(LD) -Timx6ul.lds -o $(TARGET).elf $^ # 1. 链接生成 ELF 文件 $(OBJCOPY) -O binary -S $(TARGET).elf $@ # 2. 提取二进制文件 $(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis # 3. 生成反汇编文件编译规则
$(SOBJS) : obj/%.o : %.S # 编译 .S 汇编文件(需预处理的汇编) $(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<-nostdlib:不链接标准库,适用于裸机程序-O2:优化等级为2$(INCLUDE):包含头文件目录的-I选项
$(COBJS) : obj/%.o : %.c # 编译 .c C 文件 $(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<清理规则
clean: rm -rf $(TARGET).elf $(TARGET).dis $(TARGET).bin $(COBJS) $(SOBJS)完整流程:
- 收集源码路径:
SFILES = project/start.S bsp/clk/clk.SCFILES = project/main.c bsp/clk/clk.c
- 提取文件名:
SFILENDIR = start.S clk.SCFILENDIR = main.c clk.c
- 生成目标文件列表
SOBJS = obj/start.o obj/clk.oCOBJS = obj/main.o obj/clk.oOBJS = obj/start.o obj/clk.o obj/main.o obj/clk.o
- 编译时
- Make 根据
VPATH在project和bsp/clk目录中查找start.S和clk.c等文件。
- Make 根据
Linux下规范性Makefile规则
https://arkmostima.pages.dev/posts/linux下规范性makefile规则/