Makefile中包含五种内容:显式规则,隐式规则,变量定义,指令(directive)和注释。
1.显式规则――描述如何生成规则的目标,它列出了目标依赖的文件,指定了产生或更新目标的命令。
2.隐式规则――描述如何生成基于文件名的一类文件,说明目标可能依赖于和其文件名类似的文件,指定了相应的命令。
3.指令――类似于编译器的伪指令,包含:指示make读入另一个makefile; 决定是否忽略makefile中的一部分;
4.变量定义--定义一个变量;
5.注释―― 一行中‘#’开始是注释,直到行末,除非遇到续行符号。在define和命令中不能有注释,其它情况下注释可出现在任何地方。
Makefile的常见语法规则:
Target ... :dependencies...
(TAB) Command
(TAB)...
target一般为程序所生成的文件名。例如,是可执行文件名或目标文件名;一个目标也可以是一个将要执行的动作的名称,见下例中的clean。dependencies就是作为输入文件,被用来生成目标文件。一个目标文件可以由好几个输入文件编译而成。
command就是make所执行的动作,可以由好几个命令组成,每个命令独占一行。注意,每个命令行开头必须有一个Tab键,千万不要忘记。
通常,命令是用来编译输入文件以生成目标文件的。当然,命令也可以不需要任何依赖(dependencies)。除了上述语法规则模块,一个makefile文件可能还包含其他内容。
# 注释行
\ 续行符
$ Makefile中允许使用简单的宏指代源文件及其相关编译信息,在Linux中也称宏为变量。在引用宏时只需在变量前加$符号。但值得注意的是,如果变量名的长度超过一个字符,在引用时就必须加圆括号()。
下面都是有效的宏引用:
$(CFLAGS)
$2
$Z
$(Z)
其中最后两个引用是完全一致的。
举例:objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.o ,那么在makefile文件中,可用$(objects)代替上述八个.o文件。
$* 不包含扩展名的目标文件名称。
$+ 所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件。
$< 第一个依赖文件的名称。
$? 所有依赖文件,以空格分开,这些依赖文件的修改日期比目标文件的创建日期晚。
$@ 目标的完整名称。
$^ 所有的依赖文件,以空格分开,不包含重复的依赖文件。
$% 如果目标是归档成员,则该变量表示目标的归档成员名。
@ 命令如果以"@"起始,则@符号禁止打印输出它所在的命令行
### makefile 结束 ###
[ ] [ expression ] 相当于test expression。用于shell的逻辑判断。
要注意在[ 的后面和 ]符号的前面要有一个空格。
expression选项:
-r file 用户可读为真
-w file 用户可写为真
-x file 用户可执行为真
-f file 文件为正规文件为真
-d file 文件为目录为真
-c file 文件为字符特殊文件为真
-b file 文件为块特殊文件为真
-s file 文件大小非0时为真
-t file 当文件描述符(默认为1)指定的设备为终端时为真
条件测试:
-a 与
-o 或
! 非
exit 0或 exit 1 退出时的返回值主要用来判断程序进行的如何:区别是人为的,你可以自己定义退出值的含义。但是一般用 0 表示正常退出,>0 的表示各种含义的异常退出。
& & 使用& &的一般形式为:命令1 && 命令2
只有& &左边的命令(命令1)返回真(即返回0,成功被执行),& &右边的命令(命令2)才能够被执行;换句话说,“如果这个命令执行成功& &那么执行这个命令”。
举例:[ -f /bin/awk ] && exit 0 如果/bin/awk文件存在,则正常退出。
|| 使用 || 的一般形式为:命令1 || 命令2
如果 || 左边的命令(命令1)未执行成功,那么就执行 || 右边的命令(命令2);或者换句话说,“如果这个命令执行失败了|| 那么就执行这个命令”。
举例:[ -f /bin/awk ] || exit 1如果/bin/awk文件不存在,则异常退出。
| f1|f2表示将f1的输出通过管道送至f2作为输入
f1|f2|f3表示将f1的输出作为f2的输入,然后把f2的结果(输出)作为f3的输入,还可以继续将f3的输出定向到某一个文件如: f1|f2|f3>/tmp /file. out
for 循环
For语句的结构如下:
for variable in arg1 arg2 … argn ;
do
command
command
…
done
举例,如果要安装多个程序, 可以通过一个循环来完成:
PROGRAMS=cp ls rm
install:
for p in $(PROGRAMS); do \
$(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p | sed '$(transform)'`; \
done
uninstall:
for p in $(PROGRAMS); do \
rm -f $(bindir)/`echo $$p | sed '$(transform)'`; \
done
说明:
1、p表示从cp ls rm 其中的一个,直到for结束为止。
2、P代表cp ls rm 中的一个。
3、$$p,第二个$表示p所代表的变量的值,在这里是cp ls rm 中的一个。前面的$表示在这个变量的前面加上符号$。
xargs 通过缓冲方式并以前面命令行的输出作为参数,调用随后的命令。它可以使用户对前面命令所匹配到的文件执行几乎所有的系统命令。
举例:-find romfs -name CVS | xargs rm –rf 在romfs目录中查找名字为CVS的文件,并删除之。
If… …fi 条件判断,其中fi是用来判断一个if逻辑结构结束的标志。
if - then语句
格式: if command1
then
command2
command3
fi ### (if 语句结束) ###
command4
每个程序或命令执行结束后都有一个返回的状态,用户可以用Shell变量 $? 获得这一状态。if语句检查前面命令执行的返回状态,若该命令成功执行,那么在then和fi之间的命令都将被执行。在上面的命令序列中,command1和command4总要执行。若command1成功执行,command2和command3也将执行。