记性不好,多写博客 $@ 表示目标文件 $% 仅当目标是函数库文件中,表示规则中的目标成员名。例如,如果一个目标是“foo.a(bar.o)”,那么,“$%”就是“bar.o”,“$@”就是“foo.a”。如果目标不是函数库文件(Unix下是[.a],Windows下是[.lib]),那么,其值为空。 $+ 这个变量很像“$^”,也是所有依赖目标的集合。只是它不去除重复的依赖目标。
/***********************************************************************************************************************************************************************/ 现在我们的Makefile写成这样: all: main main: main.o stack.o maze.o gcc $^ -o $@ main.o: main.h stack.h maze.h stack.o: stack.h main.h maze.o: maze.h main.h clean: -rm main *.o .PHONY: clean 按照惯例,用 $ gcc -M main.c main.o: main.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h /usr/lib/gcc/i486-linux-gnu/4.3.2/include/stddef.h /usr/include/bits/types.h /usr/include/bits/typesizes.h /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h /usr/lib/gcc/i486-linux-gnu/4.3.2/include/stdarg.h /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h main.h stack.h maze.h
$ gcc -MM *.c main.o: main.c main.h stack.h maze.h maze.o: maze.c maze.h main.h stack.o: stack.c stack.h main.h 接下来的问题是怎么把这些规则包含到Makefile中,GNU all: main main: main.o stack.o maze.o gcc $^ -o $@ clean: -rm main *.o .PHONY: clean sources = main.c stack.c maze.c include $(sources:.c=.d) %.d: %.c set -e; rm -f $@; $(CC) -MM $(CPPFLAGS) $< > $@.$$$$; sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; rm -f $@.$$$$
include main.d stack.d maze.d 类似于C语言的 $ make Makefile:13: main.d: No such file or directory Makefile:13: stack.d: No such file or directory Makefile:13: maze.d: No such file or directory set -e; rm -f maze.d; cc -MM maze.c > maze.d.$$; sed 's,\(maze\)\.o[ :]*,\1.o maze.d : ,g' < maze.d.$$ > maze.d; rm -f maze.d.$$ set -e; rm -f stack.d; cc -MM stack.c > stack.d.$$; sed 's,\(stack\)\.o[ :]*,\1.o stack.d : ,g' < stack.d.$$ > stack.d; rm -f stack.d.$$ set -e; rm -f main.d; cc -MM main.c > main.d.$$; sed 's,\(main\)\.o[ :]*,\1.o main.d : ,g' < main.d.$$ > main.d; rm -f main.d.$$ cc -c -o main.o main.c cc -c -o stack.o stack.c cc -c -o maze.o maze.c gcc main.o stack.o maze.o -o main 一开始找不到 set -e; rm -f maze.d; cc -MM maze.c > maze.d.$$; sed 's,\(maze\)\.o[ :]*,\1.o maze.d : ,g' < maze.d.$$ > maze.d; rm -f maze.d.$$ 注意,虽然在Makefile中这个命令写了四行,但其实是一条命令,
不管是Makefile本身还是被它包含的文件,只要有一个文件在 main.o main.d: main.c main.h stack.h maze.h maze.o maze.d: maze.c maze.h main.h stack.o stack.d: stack.c stack.h main.h 如果我在 1、 main.o: main.c main.h stack.h maze.h %.o: %.c # commands to execute (built-in): $(COMPILE.c) $(OUTPUT_OPTION) $< 第一条是把规则 main.d: main.c main.h stack.h maze.h %.d: %.c set -e; rm -f $@; $(CC) -MM $(CPPFLAGS) $< > $@.$$$$; sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; rm -f $@.$$$$ 因此 2、由于 /***********************************************************************************************************************/ 由于GNU Make中文手册触发深入理解sedhttp://mp.blog.csdn.net/postedit?ref=toolbar最近由于要分析Uboot的代码。 于是乎,再一次开始复习《GNU Make中文手册》() 第一次看这本手册是在快一年前的事情了,当时是啥都不懂。一头雾水。 这次细细品味的时候,发现收获颇多。建议初学者去多看看。 今天看到 《4.14 自动产生依赖》的时候,一段代码在一次让我郁闷了。同样的地方,同样的不理解。 今天偶就要好好揭开这个惑! 代码如下:
其实这里主要是为每个C文件建立一个同名的后缀为.d。该文件的作用是使用gcc的-M属性来自动生成.o文件的头文件依赖关系。 第1,2,4都好理解。 第2行解释: 使用gcc -M 的属性将 $<(第1行的第一个依赖文件,就是%.c。 查看静态模式)的C文件的依赖关系输出到一个临时文件。 这里有点疑惑。 书里面说 . 是当前进程好。 然到Makefile这个脚本将 当成进程号了。姑且这么认为吧。 第4行解释:将第2行产生的临时文件删除。 对于第3行, 我知道sed的s命令是一个替换命令。但是里面的用到了太多高深的匹配规则了。 sed命令果真如传闻中的那么强大,对于现在的我来说还真的很陌生。不管咋样, 要把它解决。 首先,我们先要知道sed是什么概念。 sed是一个非交互式的流编辑器。所谓非交互式,是指使用sed只能在命令行下输入编辑命令来编辑文本,然后在屏幕上查看输出;而流编辑器是指sed每次只从文件(或输入)读入一行,然后对该行进行指定的处理,并将结果输出到屏幕,接着读入下一行。 为了简化的阐述,下面将静态模式用一个特例代替---main.c 。 通过第2行,针对main.c编译器生成了如下的依赖关系: main.o:main.c defs.h 而通过第三行将会被替换成main.o:main.d:main.c defs.h, 并且把这个依赖关系输出到文件main.d中。 OK,大致知道了它的意思,接下在,就细细的分析第三行命令的整个执行过程,如下: 1:将($@. )的临时文件中的字符串信息(main.o:main.c defs.h)通过 “<” 输送到sed命令中. 2:sed中的s符号告诉sed命令,这次要做一个替换的任务。s符号的格式为:[address[,address]] s/pattern-to-find/replacement-pattern/[g p w n]。 下面来匹配上面的示例: [address[,address]]:是指要处理的行的范围,在这次的操作中采用的是默认值。 pattern-to-find等价于$∗$∗\.o[ :]* replacement-pattern等价于\1.o $@ : 3:Makefile使用%=main进行替换后,命令变成了sed 's,mainmain\.o[ :]*,\1.o main.d : ,g' < main.pid > main.d ; 接下来就比较好分析了,主要是正则表达式的知识了。 pattern-to-find使用到了4个正则表示式的知识点。 first, mainmain为创建一个字符标签,给后边的replacement-pattern使用。如\1.o,展开后就是main.o second, \. 在正则表达式中‘.’作用是匹配一个字符。所以需要使用转义元字符‘\’来转义。 third, [ :] 匹配一组字符里的任意字符 。 forth, *匹配0个或多个前一字符 4 : 通过sed的正则表达式,输入的main.o:main.c defs.h被替换成了main.o main.d : main.c defs.h。 这里还有个有趣的东西,平时我们对命令s符号使用‘/’作为参数分割符,其实‘/’只是一种默认的习惯罢了。你也可以使用','来作为分割符号,只要前后统一就OK。这里就是使用了','来作为分割符。 以上是个人的理解, 在一个复习了一下正则表达式与sed, 感觉挺好。学到了不少东西。
http://blogold./u/29916/showart_2096163.html /**********************************************************************/ Makefile中的wildcard用法 http://blog.csdn.net/liangkaiming/article/details/6267357在Makefile规则中,通配符会被自动展开。但在变量的定义和函数引用时,通配符将失效。这种情况下如果需要通配符有效,就需要使用函数“wildcard”,它的用法是:$(wildcard PATTERN...) 。在Makefile中,它被展开为已经存在的、使用空格分开的、匹配此模式的所有文件列表。如果不存在任何符合此模式的文件,函数会忽略模式字符并返回空。需要注意的是:这种情况下规则中通配符的展开和上一小节匹配通配符的区别。 一般我们可以使用“$(wildcard *.c)”来获取工作目录下的所有的.c文件列表。复杂一些用法;可以使用“$(patsubst %.c,%.o,$(wildcard *.c))”,首先使用“wildcard”函数获取工作目录下的.c文件列表;之后将列表中所有文件名的后缀.c替换为.o。这样我们就可以得到在当前目录可生成的.o文件列表。因此在一个目录下可以使用如下内容的Makefile来将工作目录下的所有的.c文件进行编译并最后连接成为一个可执行文件: #sample Makefile objects := $(patsubst %.c,%.o,$(wildcard *.c)) foo : $(objects) cc -o foo $(objects) 这里我们使用了make的隐含规则来编译.c的源文件。对变量的赋值也用到了一个特殊的符号(:=)。 1、wildcard : 扩展通配符 2、notdir : 去除路径 例子: 在test下,建立a.c和b.c2个文件,在sub目录下,建立sa.c和sb.c2 个文件 建立一个简单的Makefile all: wildcard把 指定目录 ./ 和 ./sub/ 下的所有后缀是c的文件全部展开。 第二行输出: 第三行输出: 在$(patsubst %.c,%.o,$(dir) )中,patsubst把$(dir)中的变量符合后缀是.c的全部替换成.o, 这里用到makefile里的替换引用规则,即用您指定的变量替换另一个变量。 今天在研究makefile时在网上看到一篇文章,介绍了使用函数wildcard得到指定目录下所有的C语言源程序文件名的方法,这下好了,不用手工一个一个指定需要编译的.c文件了,方法如下: SRC = $(wildcard *.c) 等于指定编译当前目录下所有.c文件,如果还有子目录,比如子目录为inc,则再增加一个wildcard函数,象这样: SRC = $(wildcard *.c) $(wildcard inc/*.c) 也可以指定汇编源程序: |
|
来自: goodwangLib > 《MakeFile》