#井号键 pound key hash key
1.可以不是对整个工程编译,例如:make foo.c ,便于快速解决语法错误。
2.非真正执行make命令 make --just-print make -n 显示make的执行过程
3. target1,target2,target3:prequsites1,preqisites2
command1
command2
command3
如果右边没有依赖对象,则只当目标不存在时,才会去update
4.PHONY target(不代表文件的目标) 规则所相应的命令,总是会执行,因为它不存在。用.PHONY可以声明一个phony目标,这样可以避免和存在的同名文件冲突。另外,还有empty target,这个target可以作为一个时间戳吧。
还是理解的不深入。以下中有一段很深入的对于phony target的例子,很棒!
5.自动变量 automatic variables,还是比较常用的
$@ target---目标
$% The filename element of an archive member specification---依赖
$< The filename of the first prerequisite--第一个依赖
$? The names of all prerequisites that are newer than the target, separated by
spaces.所有比target新的依赖。
$^ The filenames of all the prerequisites, separated by spaces.
5.1 关于变量:以下是很好的讲解makefile的blog
http://blog.electric-cloud.com/2009/03/23/makefile-performance-shell/
FOO=abc
BAR_1:=$(FOO)
BAR_2 =$(FOO)
FOO=def
all:
@echo $(BAR_1)
@echo $(BAR_2)
输出:
abc def
|
上面的BAR_1为简单变量,它是立即替换为abc,
BAR_2
是recursive variable ,它是用到的时候替换的。
6. VPATH包含一系列的目录,这些目录是供target和prerequisites搜索的,而非命令行中的文件。make在当前目录找不到相关文件时会进入这些目录,会遍历vpath目录,会使用第一个找到的文件,
注意VPATH和vpath是不同的!!!!
VPATH的标准格式 :
vpath pattern directory-list
例如:
vpath %.c src
vpath %.h include
讲述VPATH和vpath区别的好文章!
http://hi.baidu.com/lavrock/blog/item/9baf607e97dd59310dd7da47.html
7.“%”的意思是匹配零或若干字符,类似于unix的*
8.查看依赖文件 gcc -M stdio.h,有时候需要加上-I 指令,否则无法
正确显示。
9.采用-l来链接库效率更好,移植性更好
对于.a和.so文件,makefile优先在通用路径中查找
-L选项可以重新定位搜索路径
10.两种方法链接库文件生成可执行文件
cc count_words.o libcounter.a /lib/libfl.a -o count_words
和
cc count_words.o -lcounter -lfl -o count_words
11.libname.a(module.o)库名(成员名),便于更新.a库的作用吧
libgraphics.a(bitblt.o): bitblt.o
$(AR) $(ARFLAGS) $@ $<
ar命令可以把一些.o文件集成到.a文件里。
-lfl 和usr/lib/libfl.a都可以通过链接,但是-lfl链接的是/usr/lib/libfl.so(测试环境ubuntu9.04),链接器首先查找shared library , 而后是archive library。
-L 可以链接指定的lib目录。
-l出现在prerequisites里面,make 查找这个库,倾向于shared library,然后替代为绝对路径。 ***对于由makfile自身编译生成的libraries,不能用-l
***库在命令行中的排列顺序也是很重要的!
the order of libraries on the command
line is of fundamental importance.
***circular references or circularities问题。
***p39库的相互依赖讲得很好,可以以后参考!
12.非常规范的makefile
/home/jacky/tstProject/example_make/ch02-cw5中的Makefile
VPATH = src include
CPPFLAGS = -I include
count_words: count_words.o counter.o lexer.o -lfl
gcc $^ -o $@
count_words.o: count_words.c counter.h
gcc $(CPPFLAGS) -c $< -o $@
counter.o: counter.c counter.h lexer.h
gcc $(CPPFLAGS) -c $< -o $@
lexer.o: lexer.c lexer.h
gcc $(CPPFLAGS) -c $< -o $@
lexer.c: lexer.l
flex -t $< > $@
13.CHAPTER2
13.1 Explicit rules:目标文件和依赖文件明确指定。
Pattern rules :利用通配符。
Implicit rules:既属于pattern rules 也属于suffix rules
13.2 规则rule对于同样的依赖,可以设置多个目标prequsite。注意规则rule的双向性。
13.3 注意makefile和shell对于通配符的执行点是不同的。makfile采取立即替换,而shell则是在执行时进行替换。
13.4 ch02-cw3 cw4编译时出现如下错误:14.函数:
$(patsubst search-pattern,replace-pattern,text)
等价于:
$(variable:search=replace)
variable是指代text的变量。
(words text) 返回text中的单词数,text中的单词以whitespace分割。
$(word n,text) 返回第n个单词,如果n大于text中单词数目,函数返回empty.
$(firstword text) 返回第一个单词.
$(wordlist start,end,text) 返回start到end之间的单词.
比较复杂的应用:
uid_gid = $(wordlist 3, 4, \
$(subst :, , \
$(shell grep "^jacky:" /etc/passwd)))
uid:
@echo $(uid_gid)
输出:
1000 1000
|
$(sort list) 对list中的单词进行排序。
$(shell command) 需要在subshell中执行。command命令的输出被读取作为shell函数的返回值。
以下函数用于判断字符串中有无重复的has-duplicates = $(filter \
$(words $1) , \
$(words $(sort $1)))
all:
@echo $(call has-duplicates, word dd dd ddddo)
|
15. chapter05 第五章:15.1 命令是一行shell脚本,make提取出每一行把它发给subshell去执行,
这一过程需要fork/exec,如果采用一些特殊的标识符,那么可以减少fork和exec.如果make发现了一些可以优化的因素(没有wildcard characters and i/o redirection),那么可以不用产生subshell.
在make的目标下一行,如果起始字符是tab键,那么这一行被认为是shell命令,除非前一行以"\"结尾.
15.2当make启动时,除了SHELL环境变量,其他的环境变量和系统的相同。
15.3 对于使用for循环的makefile,要注意使用';'和'\'来使语句一起执行。还有&&的使用。需要注意。
15.4 利用@可以避免打印命令本身,更简洁吧。
16 chapter06
16.1 如果我们添加了头文件注释,并且我们不想再编译相关的源文件,可以执行 make --touch命令。.PHONY文件不受--touch影响。
16.2 make通过MAKEFLAGS将参数传递给submake.
16.3 关于
%.d: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -M $< | \
$(SED) 's,\($(notdir $*)\.o\) *:,$(dir $@)\1 $@: ,' > $@.tmp
$(MV) $@.tmp $@
实际上最难懂的就是sed的操作了,sed操作的目的是什么?
jacky@JACKY:~/mydoc/srcForLearn/examples/ch06-non-recursive$ cc -I lib -I include -M lib/db/playlist.c playlist.o: lib/db/playlist.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.3/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.3/include/stdarg.h \ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
|
playerlist.d文件
lib/db/playlist.o lib/db/playlist.d: lib/db/playlist.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.3/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.3/include/stdarg.h \
/usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
|
读《跟我一起写 Makefile》摘录:
.PHONY : clean
clean :
-rm edit $(objects)
在rm命令前面加了一个小减号的意思就是,也许某些文件出现问题,但不要管,继续做后面的事。
引用其它的 Makefile
include
!!!如果你想让make不理那些无法读取的
文件,而继续执行,你可以在include前加一个减号“-”。如:
-include ;
其表示,无论include过程中出现什么错误,都不要报错继续执行。和其它版本make兼容的相关命令是sinclude,其作用和这一个是一样的。
如果你要让通配符在变量中展开,也就是让objects的值是所有[.o]的文件名的集合,那么,你可以这样:
objects := $(wildcard *.o) ,而不是:
objects = *.o
关于伪目标,文中提到可以同时编译多个可执行程序,可以利用。
多目标好用否?
1.5.7静态模式:
: :
还可以利用filter函数:
$(filter %.o,$(files)): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
$(filter %.elc,$(files)): %.elc: %.el
emacs -f batch-byte-compile $<
|
我认为也是用到了多目标吧。
阅读(2190) | 评论(0) | 转发(0) |