分析一个Makefile的代码。主要是几个函数的使用
CROSS_COMPILE ?= arm-linux-gnueabihf-
TARGET ?= ledcCC := $(CROSS_COMPILE)gcc
LD := $(CROSS_COMPILE)ld
OBJCOPY := $(CROSS_COMPILE)objcopy
OBJDUMP := $(CROSS_COMPILE)objdumpINCUDIRS := imx6u \bsp/clk \bsp/led \bsp/delaySRCDIRS := project \bsp/clk \bsp/led \bsp/delayINCLUDE := $(patsubst %, -I %, $(INCUDIRS))SFILES := $(foreach dir, $(SRCDIRS),$(wildcard $(dir)/*.S))
CFILES := $(foreach dir, $(SRCDIRS),$(wildcard $(dir)/*.c))SFILESNDIR :=$(notdir $(SFILES))
CFILESNDIR :=$(notdir $(CFILES))SOBJS := $(patsubst %, obj/%, $(SFILESNDIR:.S=.o))
COBJS := $(patsubst %, obj/%, $(CFILESNDIR:.c=.o))OBJS := $(SOBJS)$(COBJS)VPATH := $(SRCDIRS).PHONY:clean$(TARGET).bin : $(OBJS)$(LD) -Timx6u.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).bin $(TARGET).dis $(OBJS)print:@echo INCLUDE = $(INCLUDE)@echo SFILES = $(SFILES)@echo CFILES = $(CFILES)@echo SFILESNDIR = $(SFILESNDIR)@echo CFILESNDIR = $(CFILESNDIR)@echo SOBJS = $(SOBJS)@echo COBJS = $(COBJS)@echo OBJS = $(OBJS)
代码比较容易,就是用变量代替一些需要重复输入的部分,这里详细解释一下使用的几个函数。
patsubst
模式字符串替换函数。基本形式:
$(patsubst<pattern>,<replacement>,<text>)
功能:查找<text>
里面的字符串(单词用空格、tab、回车、换行分隔),如果有符合<pattern>
的部分,就使用<replacement>
代替。注意,text
可以是表达式。
看一下例子:
INCLUDE := $(patsubst %, -I %, $(INCUDIRS))
这里定义了一个INCLUDE
变量,然后在变量INCUDIRS
里每个单词前面加-I
。
通过echo打印,结果就是:
INCLUDE = -I imx6u -I bsp/clk -I bsp/led -I bsp/delay
后面的
SOBJS := $(patsubst %, obj/%, $(SFILESNDIR:.S=.o))
其中,$(SFILESNDIR:.S=.o)
的意思是把SFILESNDIR
这个变量中的.S
改为.o
wildcard和foreach
看一下代码:
SFILES := $(foreach dir, $(SRCDIRS),$(wildcard $(dir)/*.S))
先说wildcard。这个函数的形式:
$(wildcard <pattern>)
wildcard函数是针对通配符在函数或变量定义中展开无效情况下使用的,用于获取匹配该模式下的所有文件列表。其实就是通配符的展开。
然后是foreach:
$(foreach<var>,<list>,<text>)
把参数<list>
里的单词逐一取出,放到<var>
所指定的变量里,然后执行<text>
。这是一个循环函数。
看例子里的,结合这两个函数,结果就是把SRCDIRS
里所有的单词取出来,放到dir
里面去,然后执行通配符展开。那么SFILES
其实就是定义了项目里所有的.S
文件的路径。
echo之后结果就是:
SFILES = project/start.S
notdir
这个很简单,就是获取不带路径的文件名。