Makefile书写注意事项--个人择记(一)

 

 1 #sample Makefile
 2 edit : main.o kbd.o command.o display.o \
 3 insert.o search.o files.o utils.o
 4     cc -o edit main.o kbd.o command.o display.o \
 5         insert.o search.o files.o utils.o
 6 main.o : main.c defs.h
 7     cc -c main.c   
 8 kbd.o : kbd.c defs.h command.h
 9     cc -c kbd.c
10 command.o : command.c defs.h command.h
11     cc -c command.c
12 display.o : display.c defs.h buffer.h
13     cc -c display.c
14 insert.o : insert.c defs.h buffer.h
15     cc -c insert.c
16 search.o : search.c defs.h buffer.h
17     cc -c search.c
18 files.o : files.c defs.h buffer.h command.h
19     cc -c files.c
20 utils.o : utils.c defs.h
21     cc -c utils.c
22 clean :
23     rm edit main.o kbd.o command.o display.o \
24     insert.o search.o files.o utils.o
View Code

示例Makefile如上

1、将一个较长的行使用反斜线(\)来分解多行,这样可以使我们的Makefile书写清晰、容易阅读理解。但需要注意:反斜线之后不能有空格(这也是大家最容易犯的错误,错误比较隐蔽)。

2、命令行定义了规则的动作(如何根据依赖文件来更新目标文件)。命令行必需以[Tab]字符开始,以和Makefile其他行区别。就是说所有的命令行必需以[Tab]字符开始,但并不是所有的以[Tab]键出现行都是命令行。但make程序会把出现在第一条规则之后的所有以[Tab]字符开始的行都作为命令行来处理。(记住:make程序本身并不关心命令是如何工作的,对目标文件的更新需要你在规则描述中提供正确的命令。 “make”程序所做的就是当目标程序需要更新时执行规则所定义的命令)

 3、目标”clean“不是一个文件,它仅仅代表执行一个动作标识。正常情况下,不需要执行这个规则所定义的动作,因此目标”clean“没有出现在其它任何规则的依赖列表中。因此在执行make时,它所指定的动作不会被执行。除非在执行make时明确指定它。而且目标”clean“没有任何依赖文件,它只有一个目的,就是通过这个目标名来执行它所定义的命令。Makefile中把那些没有任何依赖只有执行动作的目标称为”伪目标“(Phony targets)。需要执行"clean"目标所定义的命令,可在shell下输入make clean

4、自动推导规则

在使用make编译.c源文件时,编译.c源文件规则的命令可以不用明确给出。这是国 为make本身存在一个默认的规则,能够自动完成对.c文件的编译并生成对应的.o文件。它执行命令"cc -c"来编译.c源文件。在makefile中我们只需要要给出需要重建的目标文件名(一个.o文件),make会自动为这个.o文件寻找合适的依赖文件(对应.c文件。对应是指:文件名除后缀外,其余都相同的两个文件),而且使用正确的命令来重建这个目标文件。对于上国这的例子,此默认规则就使用命令"cc -c main.c -o main.o"来创建文件"main.o"。对一个目标文件是"N.o",依赖文件是"N.c"的规则,完全可以省略其规则的命令行,而由make 自身决定使用默认命令。此默认规则称为make的隐含规则。

  这样,在书写Makefile时,我们就可以省略掉描述.c文件和.o依赖关系的规则,而只需要给出那些特定的规则描述(.o目标所需要的.h文件)。因此上边的例子就可以以更加简单书写,我们同样使用变量”OBJ“。Makefile内容如下:

OBJ=main.o kbd.o command.o display.o insert.o search.o files.o utils.o

edit : $(OBJ)
    cc -o edit $(OBJ)
main.o : def.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h
insert.o : defs.h buffer.h
search.o : defs.h command.h
files.o : defs.h buffer.h command.h
utils.o : defs.h

.PHONY : clean
clean :
    -rm edit ${OBJ}
View Code

清除工作目录过程文件

 

规则除了完成源代码编译之外,也可以完成其他任务。例如:前边提到的为了实现清除当前目录中编译过程中产生的临时文件(edit和哪些.o文件)的规则:

clean:
    rm edit $(OBJ)
View Code

在实际应用时,我们把这个规则写成如下稍微复杂一些的样子。以防止出现始料未及的情况

.PHONY:clean
    clean:
        -rm edit $(OBJ)
View Code

这两个实现有两点不同:1.通过“.PHONY”特殊目标将“clean”目标声明为伪目标。避免当磁盘上存在一个名为“clean”文件时,目标“clean”所在规则的命令无法执行。2.在命令行之前使用“-”,意思是忽略命令“rm”的执行错误。

posted @ 2015-05-10 14:22  tkid  阅读(604)  评论(0编辑  收藏  举报