1. 程式人生 > >makefile(04)_函數

makefile(04)_函數

makefile 函數

9.函數定義及調用

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)

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.c
const 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)_函數