wildcard
1、wildcard : 扩展通配符
2、notdir : 去除路径
3、patsubst :替换通配符
例子:
建立一个测试目录,在测试目录下建立一个名为sub的子目录
$ mkdir test
$ cd test
$ mkdir sub
在test下,建立a.c和b.c2个文件,在sub目录下,建立sa.c和sb.c2 个文件
建立一个简单的Makefile
src=$(wildcard *.c ./sub/*.c)
dir=$(notdir $(src))
obj=$(patsubst %.c,%.o,$(dir) )
all:
@echo $(src)
@echo $(dir)
@echo $(obj)
@echo "end"
执行结果分析:
第一行输出:
a.c b.c ./sub/sa.c ./sub/sb.c
wildcard把 指定目录 ./ 和 ./sub/ 下的所有后缀是c的文件全部展开。
第二行输出:
a.c b.c sa.c sb.c
notdir把展开的文件去除掉路径信息
第三行输出:
a.o b.o sa.o sb.o
在$(patsubst %.c,%.o,$(dir) )中,patsubst把$(dir)中的变量符合后缀是.c的全部替换成.o,
任何输出。
或者可以使用
obj=$(dir:%.c=%.o)
效果也是一样的。
这里用到makefile里的替换引用规则,即用您指定的变量替换另一个变量。
它的标准格式是
$(var:a=b) 或 ${var:a=b}
它的含义是把变量var中的每一个值结尾用b替换掉a
今天在研究makefile时在网上看到一篇文章,介绍了使用函数wildcard得到指定目录下所有的C语言源程序文件名的方法,这下好了,不用手工一个一个指定需要编译的.c文件了,方法如下:
SRC = $(wildcard *.c)
等于指定编译当前目录下所有.c文件,如果还有子目录,比如子目录为inc,则再增加一个wildcard函数,象这样:
SRC = $(wildcard *.c) $(wildcard inc/*.c)
也可以指定汇编源程序:
ASRC = $(wildcard *.S)
这样一来,makefile模板可修改的基本就是AVR名称和时钟频率了,其它的一般不用动
SUFFIXES
.SUFFIXES:
.SUFFIXES: .g .o ----------->关心的文件的后缀类型
.g.o: ---------> 凡是.g结尾的文件,均编译成对应名字的.o的目标文件,相当于 xx.o: xx.g
gcc -c $^
这个规则表示所有的 .o文件都是依赖与相应的.c文件的
Makefile示例:
CFILES = $(wildcard *.c)
#$(CFILES:*.c=*.o)(有星号) 和 $(CFILES: .c=.o)(有空格) 均错误
OBJS = $(CFILES:.c=.o)
PICFLAG := $(shell if [ `uname -o` != 'Cygwin' ]; then echo '-fPIC'; fi)
INCS = $(PICFLAG) -I<path1> -I<path2> ...
#INCS = $(PICFLAG) -I/you/libhome -I../me
LIBS = -L<mypath1> -l<libname1> -L<mypath2> -l<libname2> ...
#LIBS = -L/you/libhome -ldoit -L../me -ljust doit maybe libdoit.a or libdoit.so
CFLAGS = $(FLAG) -Wall -Werror $(INCS)
MYNAME = xxname
SUFFIX := $(shell if [ `uname -o` == 'Cygwin' ]; then echo dll; else echo so; fi)
TARGET = $(MYNAME).$(SUFFIX)
CC = gcc
.PHONY: all clean cleanall dll dynamic static debug
$(TARGET): $(OBJS)
$(CC) -shared $(CFLAGS) -o $(TARGET) $(OBJS) $(LIBS)
debug:
$(CC) -g -Wall -shared $(INCS) -o $(TARGET) $(SRCFILES) $(LIBS)
static: $(OBJS)
ar cr $(MNAME).a $(OBJS)
clean:
rm -rf *.o $(TARGET) $(MYNAME).a $(MYNAME).so $(MYNAME).dll *.output *.stackdump
.PHONY目标并非实际的文件名,只是在显式请求时执行命令的名字,后面接的命令总会执行
举例说明:
.PHONY all aa bb
all: aa bb
<command>
.PHONY all aa bb 表明all是伪目标,aa、bb也均为显式伪目标, 当下面没有对aa、bb做定义时,那么all: aa bb冒号后的aa bb无任何操作(不会将其当文件检测),
就继续执行<command>
.PHONY all
all: aa bb
<command>
.PHONY all表明all是伪目标,aa、bb不是显式伪目标,aa: aa bb 会优先把aa bb当做一个目标查看:检查makefile内有无aa和bb做目标的规则,有则执行找到的规则,没有则将aa和bb当做文件查看