终于有时间把makefile写完了,金工实习真的太累了
一个完整的Makefile文件由5部分构成:显式规则、隐含规则、使用变量、文件指示和注释;
本篇主要讨论显式规则和变量
显式规则:一条显式规则指明了目标文件、目标文件的依赖文件、生成或更新目标文件所使用的命令(上篇博客里有详细写过Makefile的显示规则);
隐含规则:由make根据目标文件(典型的是根据目标文件的后缀名)而自动推导出的规则;make根据目标文件的文件名,自动产生目标文件的依赖文件和生成目标文件的命令;
例如:make根据目标文件名select.o的后缀名.o,自动产生目标文件的依赖文件select.c和生成目标文件的命令gcc - c select.c -o select.o
它就等价于
select.o:select.c head.h
gcc -c select.c -o select.o
规则的主要思想是:目标文件的内容由依赖文件决定,依赖文件的任何一处改动,将导致已经存在的目标文件过时;规则的命令为重新生成目标文化提供了方法,这些命令都是shell命令;
依赖的类型:Makefile中有两种依赖,一种是前面介绍显式规则时提到的依赖文件,对于这种依赖类型,依赖文件中任何一个文件的时间比目标文件的时间晚都将导致规则中的命令被执行,从而生成新的目标文件;
还有一种依赖,如下所示:
main:main.c | somelib
gcc -o main main.c somelib
'|‘前面的文件是普通依赖文件,如果main.c过时,将导致main重新生成,而如果’|'后面的文件过时,main不会被重新生成,也就是第二行的命令不会被执行;
命令行属性:一条规则中可以有一个或多个命令行,每个命令行以Tab键开头,可以在Tab键后先写上一个加号+、减号-、或者@,然后再写上命令;如果在Tab键后没有加上这3个符号中的一个,make使用缺省的命令行属性时:执行该命令时打印出命令,执行命令时遇到错误就退出make
各符号的意义如下:
-:执行命令时如果遇到错误,继续执行而不退出make;
+:命令始终被执行,即使运行make命令时使用了参数选项(前提是本行命令所在规则的目标文件已经过时),需要执行命令以更新目标文件;
@:执行命令时在屏幕上不打印命令的内容;
例如,在一个Makefile文件中有如下判断:
file.o : file.c head.h
-mv file.o /tmp
gcc -c file.c
这个规则的含义是:如果发现file.o过时,先将过时的file.o文件备份到/tmp下,然后再生成新的目标文件,但是在第一次执行Makefile文件中的命令时,file.o文件不存在,mv命令就会出错,刚刚说了,在默认情况下,make遇到错误就会停止运行;但是当在mv命令前加上减号’-'后,make忽略错误继续执行;
使用变量:一般在具有一定规模的项目中,编写Makefile文件时通常会使用到变量,定义变量的形式一般为:
变量名 赋值符 变量值
变量名习惯上只使用字母、数字和下划线,并且不以数字开头,不可以用":"
、"#"、"="和空白符;赋值符主要有4个:=、:=、+=、?=
使用一个变量代表一个文本穿,当定义了一个变量以后,在Makefile被make解释执行时,其中的字符串都会替换为相应的文本穿;Makefile中的变量类似于C语言中的宏
select.o : select.c head.h
gcc -c select.c
使用变量将其改为:
select.o : select.c head.h
$(CC) = gcc
$(CC) -c select.c
还有一些变量是系统预定义的,如CC,上述的规则可改为:
select.0 : select.c head.h
$(CC) -c select.c
# 变量CC是系统预先定义的变量,可以直接使用
还有系统预定义的自动变量,它们的值在make 运行过程中可以动态的改变:
$@: 表示一个规则中的目标文件名
$<: 表示规则中的第一个依赖文件名
$?: 所有比目标文件新的依赖文件列表
$^: 表示规则中的所有依赖
例如一个规则:
file1.o file2.o : head.h
cp $@ /backup
这条规则的功能是当目标文件过时时。将原来的目标文件备份到/backup目录下,然后重新生成新的目标文件;当需要更新的是file1.o时(此时file.c比file.o新),$@
等于file1.o;当需要更新的是file2.o时,$@
等于file2.o;
这个规则是一个多目标规则,由于隐含规则的作用,它相当于以下两条规则:
file1.o : file1.c head.h
cp $@ /backup
gcc -c file1.c -o file1.o
file2.o : file2.c head.h
cp $@ /backup
gcc -c file2.c -o file2.o