分析一个Makefile的代码。主要是几个函数的使用
CROSS_COMPILE ?= arm-linux-gnueabihf-
TARGET ?= ledc
CC := $(CROSS_COMPILE)gcc
LD := $(CROSS_COMPILE)ld
OBJCOPY := $(CROSS_COMPILE)objcopy
OBJDUMP := $(CROSS_COMPILE)objdump
INCUDIRS := imx6u \
bsp/clk \
bsp/led \
bsp/delay
SRCDIRS := project \
bsp/clk \
bsp/led \
bsp/delay
INCLUDE := $(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
这个很简单,就是获取不带路径的文件名。