Makefile学习3

  1. addprefix函数

函数名称:加前缀函数—addprefix
返回值:以单空格分割的添加了前缀“PREFIX”的文件名序列。
示例:
$(addprefix src/,foo bar)
回值为“src/foo src/bar”

  1. wildcard即通配符,通常包括?以及*

$(wildcard PATTERN)
src=main.
chap-dir=chapters
tmp-suffix = aux log out toc
tmp-files = $(addprefix ${src}, ${tmp-suffix})
tmp-files += $(wildcard $(addprefix ${chap-dir}/, ${tmp-suffix}))
倒数第二句将 main. 作为前缀分别添加到aux log out toc,于是展开得到 main.aux main.log main.out main.toc。
最后一句首先将 chapters/
添加到 aux log out toc 前,展开后得到 chapters/*aux chapters/*log chapters/*out chapters/*toc。之后 wildcard 函数将得到匹配此模式的所有文件列表,即得到 chapters 目录下所有满足上述四种文件类型的文件名。
参考

  1. patsubst: 替换通配符(pattern substitute)
src=$(wildcard *.c */*.c */*/*.c)
dir=$(notdir $(src))
obj=$(patsubst %.c, %.o, $(src))

all:
	@echo $(src)
	@echo $(dir)
	@echo $(obj)
	@echo "end"
#第一句话获取了当前目录及子目录下所有的匹配 .c 的文件名(包括路径)。如果目录深度增加的话,加 */ 即可。
#第二句去除了或者文件名的路径信息。
#第三句则是从第一句匹配到的字符串里将 .c 换成了 .o
  1. call函数是唯一一个可以用来创建新的参数化的函数。
$(call <expression>;,<parm1>;,<parm2>;,<parm3>;...)
reverse =  $(1) $(2)
foo = $(call reverse,a,b)
那么,foo的值就是“a b”。当然,参数的次序是可以自定义的,不一定是顺序的,如:
reverse =  $(2) $(1)
foo = $(call reverse,a,b)
此时的foo的值就是“b a”。

参考

  1. foreach作为makefile中的函数,相当于一个循环函数。
 $(foreach  var, list, text)
  前两个参数var和list,参数中的单词逐一取出放到参数所指定的变量中,然后再执行所包含的表达式。每一次会返回一个字符串,循环过程中,的所返回的每个字符串会以空格分隔,最后当整个循环结束时,所返回的每个字符串所组成的整个字符串(以空格分隔)将会是foreach函数的返回值。
所以,最好是一个变量名,可以是一个表达式,而中一般会使用这个参数来依次枚举中的单词。
       names := a b c d
       files := $(foreach n,$(names),$(n).o)
上面的例子中,$(name)中的单词会被挨个取出,并存到变量“n”中,“$(n).o”每次根据“$(n)”计算出一个值,这些值以空格分隔,最后作为foreach函数的返回,所以,$(files)的值是“a.o b.o c.o d.o”。

参考

  1. eval函数
eval函数可以通过其他变量或函数的结果来定义新的makefile结构。Eval的参数被按照makefile的语法格式展开。展开的结果可以用来构造新的变量、目标、隐式或者显式规则。
PROGRAMS    = server client

server_OBJS = server.o server_priv.o server_access.o
server_LIBS = priv protocol

client_OBJS = client.o client_api.o client_mem.o
client_LIBS = protocol

# Everything after this is generic

.PHONY: all
all: $(PROGRAMS)

define PROGRAM_template =
 $(1): $$($(1)_OBJS) $$($(1)_LIBS:%=-l%)
 ALL_OBJS   += $$($(1)_OBJS)
endef

$(foreach prog,$(PROGRAMS),$(eval $(call PROGRAM_template,$(prog))))

$(PROGRAMS):
        $(LINK.o) $^ $(LDLIBS) -o $@

clean:
        rm -f $(ALL_OBJS) $(PROGRAMS)
  1. 自动变量
$@:$@指代当前目标
$<:$< 指代第一个前置条件。
$?:$? 指代比目标更新的所有前置条件,之间以空格分隔。
$^:$^ 指代所有前置条件,之间以空格分隔。
$*:$* 指代匹配符 % 匹配的部分, 比如% 匹配 f1.txt 中的f1 ,$* 就表示 f1。
$(@D)$(@F):$(@D)$(@F) 分别指向 $@ 的目录名和文件名。比如,$@是 src/input.c,那么$(@D) 的值为 src ,$(@F) 的值为 input.c。
$(<D)$(<F):$(<D)$(<F) 分别指向 $< 的目录名和文件名
例子:
dest/%.txt: src/%.txt
    @[ -d dest ] || mkdir dest
    cp $< $@
上面代码将 src 目录下的 txt 文件,拷贝到 dest 目录下。首先判断 dest 目录是否存在,如果不存在就新建,然后,$< 指代前置文件(src/%.txt), $@ 指代目标文件(dest/%.txt)
  1. 模式匹配
%.o: %.c
相当于:
f1.o: f1.c
f2.o: f2.c
  1. 变量
调用Shell变量,需要在美元符号前,再加一个美元符号,这是因为Make命令会对美元符号转义。
test:
    @echo $$HOME
  1. if函数
#if 函数的语法是:
#$(if <condition>,<then-part> )
#或
#$(if <condition>,<then-part>,<else-part> )
#<condition>参数是if的表达式,如果其返回的为非空字符串,那么这个表达式就相当于返回真,于是,<then-part>会被计算,否则<else-part>会被计算
#
  1. FORCE
clean: FORCE
        rm $(objects)
FORCE:

As you can see, using ‘FORCE’ this way has the same results as using ‘.PHONY: clean’.
Using ‘.PHONY’ is more explicit and more efficient. However, other versions of make do not support ‘.PHONY’; thus ‘FORCE’ appears in many makefiles. See Phony Targets.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值