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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章