makefile中的函数
字符处理函数
函数说明:
wildcard
: 扩展通配符。notdir
: 去除路径 。patsubst
:替换通配符。
示例
目录结构:
tree /F /A test
D:\WL\TEST\T1\TEST_MAKEFILE\TEST
| a.c
| b.c
| Makefile
|
\---sub
sa.c
sb.c
Makefile
src=$(wildcard *.c ./sub/*.c)
dir=$(notdir $(src))
obj=$(patsubst %.c,%.o,$(dir) )
all:
@echo $(src)
@echo $(dir)
@echo $(obj)
@echo "end"
输出:
b.c a.c ./sub/sb.c ./sub/sa.c
b.c a.c sb.c sa.c
b.o a.o sb.o sa.o
end
说明:
- wildcard把指定目录
./
和./sub/
下的所有后缀是c的文件全部展开。 - notdir 把展开的文件去除掉路径信息
- 在
$(patsubst %.c,%.o,$(dir) )
中,patsubst把$(dir)
中的变量符合后缀是.c
的全部替换成.o
。 或者可以使用obj=$(dir:%.c=%.o)
效果也是一样的。
obj=$(dir:%.c=%.o)
用到makefile里的替换引用规则,即用您指定的变量替换另一个变量。
它的标准格式是: $(var:a=b) 或 ${var:a=b}
它的含义是把变量var中的每一个值结尾用b替换掉a
wildcard
使用函数wildcard得到指定目录下所有的C语言源程序文件名的方法,这下好了,不用手工一个一个指定需要编译的.c文件了,方法如下:
SRC = $(wildcard *.c)
等于指定编译当前目录下所有.c文件,如果还有子目录,比如子目录为inc,则再增加一个wildcard函数,像这样:
SRC = $(wildcard *.c) $(wildcard inc/*.c)
也可以指定汇编源程序:ASRC = $(wildcard *.S)
patsubst
这是个模式替换函数
格式:$(patsubst <pattern>,<replacement>,<text> )
名称:模式字符串替换函数patsubst。
功能:查找<text>
中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式<pattern>
,如果匹配的话,则以替换。这里,<pattern>
可以包括通配符“%”,表示任意长度的字串。如果<replacement>
中也包含“%”,那么,<replacement>
中的这个“%”将是<pattern>
中的那个“%”所代表的字串。(可以用“\”来转义,以\%
来表示真实含义的“%”字符)。
返回:函数返回被替换过后的字符串。
示例:$(patsubst %.c,%.o,x.c.c bar.c)
把字串x.c.c bar.c
符合模式[%.c]
的单词替换成[%.o]
,返回结果是x.c.o bar.o
变量替换引用 $(VAR:A=B)
对于一个已经定义的变量,可以使用“替换引用”将其值中的后缀字符(串)使用指定的字符(字符串)替换。
格式为: $(VAR:A=B)(或者 ${VAR:A=B} )
意思是: 替换变量“VAR”中所有“A”字符结尾的字为“B”结尾的字。“结尾”的含义是空格之前(变量值多个字之间使用空格分开)。而对于变量其它部分的“A”字符不进行替换。
例如:
foo := a.o b.o c.o
bar := $(foo:.o=.c)
在这个定义中,变量“bar”的值就为“a.c b.c c.c”。 使用变量的替换引用将变量“foo”以空格分开的值中的所有的字的尾字符“o”替换为“c”, 其他部分不变。如果在变量“foo”中如果存在“o.o”时,那么变量“bar”的值为“a.c b.c c.c o.c”而不是“a.c b.c c.c c.c”。
示例
获取当前执行的Makefile所在路径
参考文档: https://blog.csdn.net/codingcs/article/details/79055009
Linux下我们可以用pwd命令来获取当前所执行命令的目录,在Makefile中对应可用PWD := $(shell pwd)
来获取。但是如果子Makefile 文件是从别处执行的(通过make -f .../Makefile
执行),那么$(shell pwd)
得到的目录即为执行make -f
命令的当前目录。在这种情况下, Makefile本身里面的命令不能对当前目录作出假设。那么如何获取被调用的Makefile文件所在目录呢?
根据gnu make定义,gnu make 会自动将所有读取的makefile路径都会加入到MAKEFILE_LIST
变量中,而且是按照读取的先后顺序添加。所以可以通过:
$(abspath $(lastword $(MAKEFILE_LIST)))
返回当前正在被执行的Makefile的绝对路径。mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
获取当前正在执行的makefile的绝对路径。cur_makefile_path := $(patsubst %/Makefile, %, $(mkfile_path))
获取当前正在执行的makefile的绝对目录。
示例:
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
cur_makefile_path := $(patsubst %/Makefile, %, $(mkfile_path))
#window / transe to \
cur_path := $(patsubst %/, %\,$(cur_makefile_path))
export GOPATH:= ${cur_path}
BUILDTAGS=debug
all: test
test:
@echo ${mkfile_path} "111"
@echo ${cur_makefile_path} "222"
@echo ${cur_path} "333"
GOOS="" GOARCH="" go get github.com/jteeuwen/go-bindata/go-bindata
输出:
D:/wl/Test/t1/test_makefile/Makefile 111
D:/wl/Test/t1/test_makefile 222
D:/wl/Test/t1/test_makefile 333
GOOS="" GOARCH="" go get github.com/jteeuwen/go-bindata/go-bindata
说明:在window 下直接设置 export GOPATH:= ${cur_makefile_path}
会报下面错误:
GOOS="" GOARCH="" go get github.com/jteeuwen/go-bindata/go-bindata
go: GOPATH entry is relative; must be absolute path:
" D:/wl/Test/t1/test_makefile".
For more details see: 'go help gopath'
make: *** [Makefile:15: test] Error 2
解决方法:
# 执行替换,将/替换为\。
cur_path := $(patsubst %/, %\,$(cur_makefile_path))
export GOPATH:= ${cur_path}