Makefile语法归纳汇总

Makefile语法汇总


一、下面是一个最简单的Makefile的编译规则,编译的文件有main.c和input.c文件。
main : main.o input.o
	gcc -o main main.o input.o

main.o : main.c
	gcc -c main.c
input.o : input.c
	gcc -c input.c
clean :
	rm *.o main
二、语法

1、makefile的变量

#Makefile 变量的使用
2 objects = main.o input.o calcu.o
3 main: $(objects)
4 gcc -o main $(objects)

2、赋值符

  • 赋值符号 = 只是取决于最后一次赋值的值。
  • 赋值符号 := 不会使用后面定义的,只会只用前面定义好的。
  • 赋值符号 ?= 表示变量前面没有被赋值,那么变量就被后面赋值,如果前面已经赋值过了,就使用前面赋的值。
  • 变量追加 +=
    objects = main.o inpiut.o
    objects += calcu.o
    

3.模式规则
使用%为通配符,可以表示所有的.o文件和.c文件

%.o : %.c
命令 

4.Makefile自动化变量

自动化变量 描述
$@ 规则中的目标集合,在模式规则中,如果有多个目标的话,“$@”表示匹配模式中定义的目标集合。
$% 当目标是函数库的时候表示规则中的目标成员名,如果目标不是函数库文件,那么其值为空。
$< 依赖文件集合中的第一个文件,如果依赖文件是以模式(即“%”)定义的,那么“$<”就是符合模式的一系列的文件集合。
$? 所有比目标新的依赖目标集合,以空格分开。
$^ 所有依赖文件的集合,使用空格分开,如果在依赖文件中有多个重复的文件,“$^”会去除重复的依赖文件,值保留一份。
$+ 和“$^”类似,但是当依赖文件存在重复的话不会去除重复的依赖文件。
$* 这个变量表示目标模式中"%"及其之前的部分,如果目标是 test/a.test.c,目标模式为 a.%.c,那么“$*”就是 test/a.test。

5、伪目标
当工程文件中有clean的文件,make clean命令将失效,这时定义clean为伪目标可以避免该类问题的出现。

.PHONY : clean
clean:
	rm *.o
	rm main
三、Makefile进阶

通过上面的语法介绍,第一节中的Makefile可以修改成如下

objects = main.o input.o calcu.o
main: $(objects)
	gcc -o main $(objects)

%.o : %.c
	gcc -c $<
	
.PHONY : clean
clean:
	rm *.o
	rm main
四、Makefile函数的使用

一、subst
函数功能为字符串text中的from内容替换为to。

$(subst <from>,<to>,<text>)
#使用方法如下
$(subst lidong,LIDONG,my name is lidong)

二、patsubst
此函数查找text是否符合pattern的模式,如果符合就全部替换成replacement。

$(patsubst <pattern>,<replacement>,<text>)
#使用方法如下
$(patsubst  %.c, %.o , a.c b.c c.c)

将字符串“a.c b.c c.c”中的所有符合“%.c”的字符串,替换为“%.o”,替换完成以后的字符串为“a.o b.o c.o”
三、dir
函数 dir 用来获取目录。

$(dir <names…>)
#使用方法如下,提取出来的就是“/src”。
$(dir </src/a.c>)

四、notdir
去除文件中的目录部分,也就是提取文件名。

$(notdir <names…>)
#使用方法如下,提取出来的就是“a.c”。
$(notdir </src/a.c>)

五、foreach
函数循环,把参数list中的单词逐一取出来放到参数var中,然后执行text表达式,text中所包含的每个字符串会以空格隔开。

$(foreach <var>,<list>,<text>)

#如下可以依次将文件名替换成.o文件
names := a b c d
files := $(foreach n,$(names),$(n).o)

六、wildcard
获取当前目录的xx文件。

$(wildcard PATTERN…)

#获取当前目录下的所有.c文件
$(wildcard *.c)

七、通用型具备BSP代码管理的Makefile模板

#定义交叉编译器名字变量
CROSS_COMPILE 	?= arm-linux-gnueabihf-
TARGET		  	?= bsp

#gcc编译器
CC 				:= $(CROSS_COMPILE)gcc

#连接器
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 

#头文件路径前加-I		 
INCLUDE			:= $(patsubst %, -I %, $(INCDIRS))

#获取所有带路径.S文件
SFILES			:= $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))

#获取所有带路径.C文件
CFILES			:= $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))

#获取所有.S文件
SFILENDIR		:= $(notdir  $(SFILES))

#获取所有.C文件
CFILENDIR		:= $(notdir  $(CFILES))

#汇编文件编译生成的.o文件放入obj/文件夹下
SOBJS			:= $(patsubst %, obj/%, $(SFILENDIR:.S=.o))

#c文件编译生成的.o文件放入obj/文件夹下
COBJS			:= $(patsubst %, obj/%, $(CFILENDIR:.c=.o))

#所有包含路径的.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

#静态模式的写法,将所有的.s文件编译成.o放到obj目录下去
$(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)

你可能感兴趣的:(嵌入式系统)