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)