make的使用
索引:
1.并行make
调用make时指定-P选项,它将试图以并行方式一次创建多个目标(利用系统的多进程机制实现)。
并行创建的目标数由环境变量PARALLEL的值来决定,如果该变量没有设置,则并行的目标不会超过两个。
可以使用.MUTEX指令将对指定目标的更新操作串行化。当两个以上目标修改同一个输出文件时(如lex和yacc都有这种情况),这条指令非常有效。
使用方法举例。避免并行创建x.o和y.o:
.MUTEX: x.o y.o
2.宏定义
(1).形式
宏定义是后面接等号的标识符。如:
LIBS = -lm -ls
引用宏的方法:在前面加$,多于一个字符要用括号括起来。如:
$a、$(CFLAG)
(2).内部产生的宏
$*、$@、$?、$<是四个特别的宏,在命令执行过程中它们的值会因环境而改变:
- $@设置为当前目标的全名;
- $?设置为比目标更新的名称的字符串;
- $<是导致特定动作发生的相关文件的名称;
- $*是当前的以及相关的文件名称所共享的前缀。
$*、$@和$<的扩展:
$(@D)、$(@F)、$(*D)、$(*F)、$(<D)和$(<F)也是有效的宏。D指的是路径单字符宏,F指的是文件名称单字符宏。
3.执行命令
在脚本中命令行前加”@”符号,则命令不会打印出来。
包含在makefile中的命令通过调用系统shell并在其中运行,对于每个成功的命令分别调用一个shell。所以,如下的cd命令和ls命令处理的不是同一个目录:
target1: comp1 comp2 cd newdir ls
要得到希望的结果,要把命令放在一行,命令之间用”;”分隔,多行问题可以用反斜杆来处理。如:
test: echo “start”; \ echo “starring…”; \ echo “done”
4.输出转换
在运行时shell命令中的宏将被替换,格式如下:
$(macro:string1=string2)
在被求值的宏中每次出现的string1都被string2替换。在$(macro)中查找到的string1意味着被求值的$(macro)看成是一系列用分隔符(空格或tab)隔开的字符串。因此,在$(macro)中出现的string1表示找到了如下的正则表达式:
.*<string1>[TAB|BLANK]
由于make通常关心后缀问题,所以采用这种独特的方式。在转换归档库时这种转换很有用。
5.后缀和转换规则
make用内部规则表来确定如何从一种后缀的文件转换到另一种后缀的文件。如果在make命令行使用了-r选项,则不使用内部规则表。
转换规则名称是把转换前后的后缀连接而得的。将.r文件转换成.o文件的规则名称就是.r.o。
后缀列表是名称.SUFFIXES的依赖关系列表。该表是从左到右扫描的,所以顺序很重要。用户可以在makefile的.SUFFIXES中增加一个条目。没有任何依赖信息的.SUFFIXES行用于删除当前的后缀列表。
make默认的部分后缀表如下:
.o | 目标文件 |
.c | C源文件 |
.y | yacc C源文件 |
.l | lex C源文件 |
.s | 汇编源文件 |
.sh | shell文件 |
.h | 头文件 |
.C | C++源文件 |
.Y | yacc C++源文件 |
.L | lex C++源文件 |
.f | fortran源文件 |
通过宏名称可以改变默认状态下使用的编译程序及编译选项。AS、CC、CCC、F77、YACC和LEX都是make使用的编译程序的宏名称,通过改变它们可以选择使用哪个编译程序。
宏ASFLAGS、CFLAGS、CCFLAGS、F77FLAGS、YFLAGS和LFLAGS都是相应的编译程序的选项。
空后缀规则。如:
.c: $(cc) $(CFLAGS) $< $@
创建新的后缀规则。如:
.SUFFIXES: .q .w .t
删除当前识别的所有后缀:
.SUFFIXES
加入新的后缀规则。如:
.s.l: $(TBL) $< …
6.包含文件
如果在makefile中一行的前7个字符是include,并且后面是空格或tab,则本行后面的内容被解释为文件名,make将读取其内容,包含到自己的环境中。如:
include $(ESWTDIR)/etc/Make.defines
7.环境变量
make每次运行都读取环境变量加到宏定义中,环境变量与内部定义的宏以及命令行的优先顺序由小到大是:
- 内部定义
- makefile
- 环境
- 命令行
8.内部规则
以下是部分列表:
# .SUFFIXES: .o .c .c~ .y .y~ .l .l~ .s .s~ .h .h~ .sh .sh~ .f .f~ # AR=ar ARFLAGS=rv AS=as ASFLAGS= BUILD=build CC=cc CFLAGS=-O C++C=CC C++FLAGS=-O F77=f77 FFLAGS=-O GET=get GFLAGS= LEX=lex LFLAGS= LD=ld LDFLAGS= MAKE=make YACC=yacc YFLAGS= # # .c: $(CC) $(CFLAGS) $< $(LDFLAGS) -o $@ .sh: cp $< $@; chmod 0777 $@ # # .c.a: $(CC) -c $(CFLAGS) $< $(AR) $(ARFLAGS) $@ $*.o rm -f $*.o .c.o: $(CC) $(CFLAGS) -c $< .s.o: $(AS) $(ASFLAGS) -o $@ $< .l.c: $(LEX) $(LFLAGS) $< mv lex.yy.c $@ .l.o: $(LEX) $(LFLAGS) $< $(CC) $(CFLAGS) -c lex.yy.c rm lex.yy.c mv lex.yy.o $@ -rm -f $*.l .y.c: $(YACC) $(YFLAGS) $< mv y.tab.c $@ .y.o: $(YACC) $(YFLAGS) $< $(CC) $(CFLAGS) -c y.tab.c rm y.tab.c mv y.tab.o $@