1.makefile中支持条件判断语句
可以根据条件的值来决定make的执行
可以比较两个不同变量或者变量和常量值
ifxxx(arg1,arg2)
else
endif
注意事项:条件判断语句只能用于控制make实际执行的语句;但是,不能控制规则中命令的执行过程。
工程经验:
条件判断语句之前可以有空格,但不能有Tab字符(’\t’)
在条件语句中不要使用自动变量($@, $^, $<)
一条完整的条件语句必须位于同一个makefile中
条件判断类似C语言中的宏,预处理阶段有效,执行阶段无效
make在加载makefile时:
首先计算表达式的值(赋值方式不同,计算方式不同)
根据判断语句的表达式决定执行的内容
2.函数定义及调用
make解释器提供了一系列的函数供makefile调用
在makefile中支持自定义函数实现,并调用执行
通过define关键字实现自定义函数
自定义函数的语法:
函数定义:
define func1
@echo "My name is $(0)" //打印func1函数的第0个参数,本身
endef
define func2
@echo "My name is $(0)" //打印func1函数的第0个参数,本身
@echo "Param => $(1)"
endef
函数调用:
test :
$(call func1)
$(call func2, CKY)
深入理解自定义函数:
自定义函数是一个多行变量,无法直接调用
自定义函数是一种过程调用,没有任何的返回值
自定义函数用于定义命令集合,并应用于规则中
make解释器中的预定义函数:
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)"
3.变量与函数的综合实例
实战需求:
自动生成target文件夹存放可执行文件
自动生成objs文件夹存放编译生成的目标文件(*.o)
支持调试版本的编译选项
考虑代码的扩展性
工具原料:
$(wildcard _pattern):获取当前工作目录中满足_pattern的文件或目录列表
$(addprefix _prefix,_names):给名字列表_name中的每一个名字增加前缀_prefix
关键技巧:
(1)自动获取当前目录下的源文件列表(函数调用)
SRCS := $(wildcard *.c)
(2)根据源文件列表生成目标文件列表(变量的值替换)
OBJS := $(SRCS:.c=.o)
(3)对每一个目标文件列表加上路径前缀(函数调用)
OBJS :=
(
a
d
d
p
r
e
f
i
x
p
a
t
h
/
,
(addprefix path/,
(addprefixpath/,(OBJS))
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)
make DEBUG:=true