makefile(04)_函數
Makefile中支持函數的概念,make解析器提供了一系列函數供Makefile使用。同時可以自定義函數。
9.1.自定義函數
在Makefile中支持自定義函數的實現,並調用執行,通過define關鍵字來實現自定義函數。
函數定義的語法規則:
自定義函數的本質:
1.自定義函數其實是一個多行變量,無法直接調用;通過call 關鍵字來使用(call的作用就是將實參替換到函數體對應的位置)
2.自定義函數是一種過程調用,沒有任何的返回值;
3.用於定義命令集合,並應用於規則中。
示例:
.PHONY : test define func1 @echo "My name is $(0)" endef define func2 @echo "My name is $(0)" @echo "Param 1 => $(1)" @echo "Param 2 => $(2)" endef var := $(call func1) new := $(func1) test : @echo "new => $(new)" @echo "var => $(var)" $(call func1) #@echo My name is func1 $(call func2, D.T.Software, delphi_tang)
輸出結果:
9.2.預定義函數
Make的函數提供了處理文件名,變量和命令的函數,可以在需要的地方調用函數來處理指定的參數,函數再調用的地方被替換為處理結果。
預定義函數的調用:
為什麽自定義函數和預定義函數的調用形式完成不同?
本質上,Makefile不支持真正意義上的自定義函數,自定義函數本質上是多行變量,預定義的call函數在調用時將參數傳遞給多行變量,自定義函數時call函數的參數,並在call中被執行。
示例:
.PHONY : test define func1 @echo "My name is $(0)" endef define func2 @echo "My name is $(0)" endef var1 := $(call func1) var2 := $(call func2) var3 := $(abspath ./) var4 := $(abspath test.cpp) test : @echo "var1 => $(var1)" @echo "var2 => $(var2)" @echo "var3 => $(var3)" @echo "var4 => $(var4)"
輸出結果:
10.變量與函數的綜合運用
10.1.實戰需求:
自動生成target文件夾存放可執行程序,生成objs文件夾存放編譯生成的目標文件(*.o)
支持調試版本的編譯選擇(通過預編譯宏實現),考慮代碼的擴展性(自定義變量)
10.2.工具原料:
$(wildcard _pattern),獲取當前工作目錄中滿足_pattern的文件或者目錄
$(addprefix _prefix _name),給名字列表_name中的每一個名字增加前綴_prefix
10.3.關鍵技巧:
1.自動獲取當前目錄下的源文件列表(函數調用),SRCS := $(wildcard *.c)
2.根據文件列表生成目標文件列表(變量指定替換)OBJS := $(SRCS:.c=.o)
規則中的模式替換:
這兩種模式替換的區別在於,後者的模式替換目標來自於一個變量var,前者的目標來自一個指定的文件夾。
編譯規則的依賴:
最終程序:
CC := gcc
MKDIR := mkdir
RM := rm -fr
DIR_OBJS := objs
DIR_TARGET := target
DIRS := $(DIR_OBJS) $(DIR_TARGET)
TARGET := $(DIR_TARGET)/hello-makefile.out
# main.c const.c func.c
SRCS := $(wildcard *.c)
# main.o const.o func.o
OBJS := $(SRCS:.c=.o)
# objs/main.o objs/const.o objs/func.o
OBJS := $(addprefix $(DIR_OBJS)/, $(OBJS))
.PHONY : rebuild clean all
$(TARGET) : $(DIRS) $(OBJS)
$(CC) -o $@ $(OBJS)
@echo "Target File ==> $@"
$(DIRS) :
$(MKDIR) $@
# 針對當前文件下的工作目錄進行模式替換
$(DIR_OBJS)/%.o : %.c
ifeq ($(DEBUG),true)
$(CC) -o $@ -g -c $^
else
$(CC) -o $@ -c $^
endif
rebuild : clean all
all : $(TARGET)
clean :
$(RM) $(DIRS)
源文件main.c
extern void foo();
int main()
{
foo();
return 0;
}
源文件const.cconst char* g_hello = "hello makefile";
源文件func.c
#include "stdio.h"
extern char* g_hello;
void foo()
{
printf("void foo() : %s\n", g_hello);
}
輸出結果
makefile(04)_函數