您好,登錄后才能下訂單哦!
Makefile中支持函數的概念,make解析器提供了一系列函數供Makefile使用。同時可以自定義函數。
在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)
輸出結果:
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)"
輸出結果:
自動生成target文件夾存放可執行程序,生成objs文件夾存放編譯生成的目標文件(*.o)
支持調試版本的編譯選擇(通過預編譯宏實現),考慮代碼的擴展性(自定義變量)
$(wildcard _pattern),獲取當前工作目錄中滿足_pattern的文件或者目錄
$(addprefix _prefix _name),給名字列表_name中的每一個名字增加前綴_prefix
1.自動獲取當前目錄下的源文件列表(函數調用),SRCS := $(wildcard *.c)
2.根據文件列表生成目標文件列表(變量指定替換)OBJS := $(SRCS:.c=.o)
3.對每一個目標文件列表加上路徑前綴(函數調用)OBJS := $(addprefix path/, $(OBJS))
規則中的模式替換:
這兩種模式替換的區別在于,后者的模式替換目標來自于一個變量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);
}
輸出結果
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。