使用条件判断可让make根据运行时的不同情况选择不同的执行分支
libs_for_gcc = -lgnu
normal_libs =
foo : $(objects)
ifeq ($(CC), gcc)
$(CC) -o foo $(objects) $(libs_for_gcc)
else
$(CC) -o foo $(objects) $(normal_libs)
endif
也可以写的更简洁点
ifeq($(CC), gcc)
libs = $(libs_for_gcc)
else
libs = $(normal_libs)
foo : $(objects)
$(CC) -o foo $(objects) $(libs)
使用到了三个关键字:ifeq else endif
如果要比较make的命令行参数可以使用
ifeq(< arg1>, < arg2>)
foo =
var = $(foo)
ifdef var
bozz = yes
else
bozz = no
endif
foo =
ifdef foo
bozz = yes
else
bozz = no
endif
则我们知道,第一个$ (bozz)为yes,第二个$(bozz)为no
特别注意,make是在读取makefile时就计算条件表达式的值,所以最好不要把自动化变量$@放入条件表达式中,因为自动化变量是在运行时才有的
函数的调用与变量的使用方法类似,都是通过$来标识
$(< function> < arguments, arguments, arguments>)
参数之间以“,”分隔,函数名和参数之间以空格分隔
函数中的参数可以使用变量 eg:$ (subst a,b,$(x))
将字符串中的字符替换函数
comma := ,
empty :=
space := $ (empty)$(empty)
string := a b c
bar := $(subst $ (space),$ (comma),$(string))
将a b c替换成为a,b,c
模式字符串替换函数,查找text中的单词(单词以空格、Tab、回车、换行分隔)是否符合模式< pattern>,如果匹配的话,则以< replacement>替换
pattern可以包含通配符 %,表示任意长度的字串
bar := $(patsubst %.c,%.o,x.c.c foo.c)
得到的$(bar) = x.c.o foo.o
去空格函数,去掉字符串开头或者结尾的空字符
bar := $(strip a b c )
得到的$(bar) = a b c
查找字符串函数,在字符串in中查找find字串,如果找到就返回find,否则返回空字符串
$(findstring a,a b c)
$(findstring a, b c)
第一个函数返回字符串a,第二个函数返回空字符串
过滤函数,以pattern模式过滤text中的字符串中的单词,只保留符合pattern的单词,返回符合模式的pattern的字串
sources := 1.c 2.c 3.o 4.s
foo : $(sources)
gcc $ (filter %.c %.s,$(sources)) -o foo
反过滤函数,按照pattern的要求过滤text的内容,返回过滤后不存在pattern的单词
objects = main1.o foo.o main2.o bar.o
mians = mian1.o main2.o
$(filter-out $ (mians),$(objects))的返回值就是 foo.o bar.o
排序函数,给字符串list中的单词首字母排序(升序),并且会去除重复的单词
$(sort foo bar lose)返回的就是bar foo lose
取单词函数,从text中取第n个单词,从1开始数;如果n比text中的单词数要大,那么返回空字符串
$(word 2, foo bar baz)返回的值为bar
取单词串函数,从text中取从s到e的单词串,s和e是数字
如果s比e大,则返回的是空字符串
如果e比text的单词数大,则返回的是text
$(wordlist 2,3,foo bar baz)返回的就是 bar baz
统计text中的单词数量
$(words foo bar baz)返回的值就是3
取text中第一个单词
$(firstword foo bar baz)返回值就是foo
也可以使用
$(word 1,foo bar baz)返回值也是foo
假设搜索路径的特殊变量VPATH = src : …/header
修改为cc 或gcc 搜索头文件路径的参数是多少,并且如何修改
参数是目录前面加上-I,因为有两个目录,所以分别要加上-I,分隔符冒号也要修改为空格
为-Isrc , -I…/header
使用subst和patsubst修改:
$ (patsubst %,-I%, ( s u b s t : , , (subst :, , (subst:,,(VPATH)))
最后修改为:-Isrc -I…/header
override CFLAGS += $ (patsubst %,-I%, ( s u b s t : , , (subst :, , (subst:,,(VPATH)))
这里的函数主要是处理文件名,每个函数的参数字符串都会被当做一个或者一系列的文件名来对待,最重要是文件名
取出目录部分,所谓的目录部分就是最后一个 / 之前的内容
如果没有/,则返回 “./”
$(dir src/foo.c hacks)的返回值是 “src/”加上 “./”
因为这是两个路径:src/foo.c 、hacks
取出文件函数,从路径中取出非目录部分,指最后一个反斜杠 “/” 之后的部分
$(notdir src/foo.c hacks)的返回值就是 foo.c hacks
取后缀函数,从文件名序列names中取出各个文件名的后缀,如果没有后缀则返回空字符串
$(suffix src/foo.c src-1.0/bar.c hacks)的返回值是.c .c
取前缀函数,从文件名序列names中取出各个文件名的前缀,如果没有前缀则返回空字符串
$(basename src/foo.c src-1.0/bar.c hacks)的返回值是 src/foo src-1.0/bar hacks
加后缀函数,将suffix加到每个names中的每个单词后面
$(addsuffix .c,foo bar)返回值是 foo.c bar.c
加前缀函数,将prefix加到每个names中的每个单词前面
$(addprefix src/,foo bar)的返回值是src/foo src/bar
连接函数,将list2单词对应连接到每个list1的单词的后面
如果list1的单词数大于list2的单词数,则list1的单词就会保持原样
如果list1的单词数小于list2的单词数,则list2的单词就会保持原样连接
$(join aaa bbb,111 222 333)的返回值为 aaa111 bbb222 333
foreach主要用于循环
$(foreach < var>,< list>,< text>)
表示将list中的单词逐个取出放入var指定的容器中,每放一次就会执行一次text中的表达式,得到结果就会返回一个字符串,每次返回的字符串都会用空格分隔开,最后当整个循环结束时,< text>所返回的每个字符串所组成的整个字符串(以空格分隔)将会是 foreach 函数的返回值
list := a b c d
$ (foreach n,$ (list),$(n).o)则返回的值为a.o b.o c.o d.o
var只是一个局部变量作用域只会存在于foreach中
call用来创建新的参数化的函数
你可以写一个复杂的表达式,定义很多参数,并用call来依次传递参数
$(call < expression>,< parm1>,< parm2>,< parm3>…)
例如我定义了一个表达式:reverse = $(1) $(2)
foo = $(call reverse,a,b)
a和b依次覆盖了1和2,同时得到的返回值foo的值就是a b
reverse = $(2) $(1)
foo = $(call reverse,a,b)
a和b依次覆盖了1和2,同时得到的返回值foo的值就是b a
origin函数不同于其他函数,其他函数都是去操作参数的值,而这个函数通过返回值告诉你参数的来源
$(origin < variable>)
此时variable是变量的名字,而不是变量的引用,所以不要去加$
origin函数的返回值 | 解析 |
---|---|
“undefined” | 如果< variable>从来没有定义过,origin 函数返回这个值“undefined”。 |
“default” | 如果< variable>是一个默认的定义,比如“CC”这个变量 |
“environment” | 如果< variable>是一个环境变量,并且当 Makefile 被执行时,“-e”参数没有被打开。 |
“file” | 如果< variable>这个变量被定义在 Makefile 中。 |
“command line” | 如果< variable>这个变量是被命令行定义的。 |
“override” | 如果< variable>是被 override 指示符重新定义的。 |
“automatic” | 如果< variable>是一个命令运行中的自动化变量。 |