makefile(二)makefile规则

原创
2016/10/29 16:49
阅读数 951

一、基本规则

makefile规则的基本写法为:

targets : prerequisites
    command

其中:

  • targets:表示目标,目标有两种,第一种是在执行过程中产生的文件名,例如.o文件或者可执行文件。第二种是某个动作的名称,在执行过程中没有实际的文件与之对应,这种情况称为PHONY目标。
  • command:表示命令,如果其不与目标文件和文件依赖规则依赖在同一行,则必须以tab键开头。
  • prerequisites:表示生成目标文件所依赖的文件。如果其中的某个文件比目标文件要新,make工具会认为目标文件“需要更新”,make工具会重新生成新的目标文件。如果命令太长,可以使用“\”作为换行符。

对于“更新”这个概念,make工具没有明确的定义,如果规则的目标满足以下之一,就称为需要更新:

  • 目标文件没有生成
  • 某个条件中的文件修改时间比目标文件晚
  • 某个条件中的文件需要更新

下面是一个程序的makefile文件,演示了基本规则的用法:

edit: main.o kdb.o command.o display.o \
    insert.o serach.o files.o utils.o
    gcc -o edit main.o kdb.o command.o display.o \
    insert.o serach.o files.o utils.o

main.o: main.c defs.h                       #生成 main.o
    gcc -c main.c
kdb.o: kdb.c defs.h command.h               #生成 kdb.o
    gcc -c kdb.c
command.o: command.c defs.h command.h       #生成 command.o
    gcc -c command.c
display.o: display.c defs.h buffer.h        #生成 display.o
    gcc -c display.c
insert.o: insert.c defs.h buffer.h          #生成 insert.o
    gcc -c insert.c
serach.o: serach.c defs.h buffer.h          #生成 serach.o
    gcc -c serach.c
files.o: files.c defs.h buffer.h command.h  #生成 files.o
    gcc -c files.c
utils.o: utils.c defs.h                     #生成 utils.o
    gcc -c utils.c

clean:
    rm edit main.o kdb.o command.o display.o \
    insert.o serach.o files.o utils.o

二、使用隐式规则

makefile文件支持隐式规则,这里只介绍最基本的隐含规则,这些隐式规则是最常用的。

make工具会自动使用gcc -c命令,将一个扩展名为 .c的C语言源程序文件编译成一个同名的.o的目标文件。因此当编译一个单独的.c文件到.o文件时,可以使用隐含规则。

在使用隐式规则时,与目标同名的 .c文件自动被添加为条件,因此条件中的.c文件可以省去。

在上面的makefile文件使用隐式规则:

edit: main.o kdb.o command.o display.o \
    insert.o serach.o files.o utils.o
    gcc -o edit main.o kdb.o command.o display.o \
    insert.o serach.o files.o utils.o

main.o: defs.h                      #生成 main.o
    
kdb.o: defs.h command.h             #生成 kdb.o
    
command.o: defs.h command.h         #生成 command.o
    
display.o: defs.h buffer.h          #生成 display.o
   
insert.o: defs.h buffer.h           #生成 insert.o
    
serach.o: defs.h buffer.h           #生成 serach.o
    
files.o: defs.h buffer.h command.h  #生成 files.o
    
utils.o: defs.h                     #生成 utils.o
    

clean:
    rm edit main.o kdb.o command.o display.o \
    insert.o serach.o files.o utils.o

三、使用伪目标

在上面的例子中的clean,就是一个伪目标:

clean:
    rm edit main.o kdb.o command.o display.o \
    insert.o serach.o files.o utils.o

使用clean目标,执行其后的命令:清除所生成的目标文件,为下次的编译该工程做准备。因此make工具并不生成clean这个目标文件。这个伪目标更像是C语言中的一个标号,只执行命令,并不生成任何文件。由于伪目标不是真正的文件,所以make工具无法生成其依赖关系,并且决定该目标是否需要执行。

因此只有通过显示地指明这个目标才能对其进行执行。为了避免和以存在的文件重名,可以使用一个特殊的标记 .PHONY来显式地指明一个目标是伪目标,如:

.PHONY : clean

表示不管是否有clean这个文件存在,都将其声明为一个伪目标。只要使用这个声明,不管makefile文件中是否有clean文件,要运行clean这个目标时,只有在启动make工具时指定运行运行该目标才行。如下面,运行clean伪目标:

make clean

目标也可以成为依赖,因此伪目标同样也可成为依赖。如下:

.PHONY: cleanall cleanobj cleanmk

cleanall : cleanobj cleandiff
    rm app
cleanobj : 
    rm *.o
cleanmk :
    rm *mk

执行cleanobj和cleanmk这两个伪目标有点像“子程序”调用。用户可以分别执行这3个目标,每次清理指定的文件。

四、使用通配符

makefile文件允许在规则中使用通配符。make工具支持3种通配符“*”、“?”、“[...]”。

~ 表示用户的根目录,该目录通常是由$HOME环境变量所保存。makefile种使用~和一个相对路径,生成一个完整的路径,如下:

~/download

表示home目录下的download目录。

通配符 * :匹配所有文件

app : *.c *.h
    gcc *.c -o app

五、搜索源文件

在一些大的工程中,源代码往往分配在大量的源文件中,通常这些源代码分别在不同的目录中。

当使用make工具去推导文件的依赖关系时,用户可以在文件前加上路径,也可以把一个路径告诉make工具,让make工具自动寻找源文件并且推断其依赖关系。设置make工具搜索文件路径的方法有两种。

1.设置vpath变量

makefile文件中使用特殊变量vpath实现搜索源文件的功能。如果没有指明该变量,makefile工具默认在当前目录中寻找依赖文件和目标文件。如果定义了该变量,make工具就会在当前目录找不到所需源文件的情况下,到所指定的目录中寻找:

vpath = src:../include

vpath变量的值被定义为2个目录,分别是src和../inlcude,表示make工具顺序搜索当前目录、当前目录下的src目录以及父目录下的include目录。每个目录由“:”分割。

2.使用vpath关键字

makefile文件的vpath关键字和vpath变量很相似,但是它更灵活。该关键字可以指定不同的文件在不同的搜索目录下,有三种方法:

1)指定特定模式的文件搜索目录

vpath <pattern> <directories>

该形式表示指定符合模式<pattern>的文件搜索目录为<directories>。

2)指定文件的模式

vpath <pattern>

该形式清除符合模式<pattern>的文件搜索目录

3)清除所有的文件搜索目录

vpath

清除所有已被设置好的文件搜索目录。

vpath使用方法中的<pattern>需要包含%字符。%的意思是匹配若干个字符(字符数大于等于0).例如,%.h表示所有以.h结尾的文件。<pattern>指定了要搜索文件的模式,而<dirextories>则指定了搜索文件的目录,如下所示:

vpath %.h ../include

该语句表示如果在当前目录下没有找到所需要的文件时,在父目录下的include目录下搜索所有以.h结尾的文件。

用户可以使用vpath关键字指定多个不同的搜索策略。如果连续的vpath语句中出现了相同的<pattern>,或者是被重复了的<pattern>,make工具则会按照vpath关键字声明的先后顺序来执行搜索,如下所示:

vpath %.c /src
vpath %.c /backup
vpath %.c /home/admin

其表示搜索所有的C语言源程序,搜索目录的顺序为:当前工作目录、/src目录、/backup目录及/home/admin目录,也可以将两个目录写在一行,并且以“:”分隔,如下:

vpath %.c /src : /backup : /home/admin

 

展开阅读全文
打赏
0
3 收藏
分享
加载中
更多评论
打赏
0 评论
3 收藏
0
分享
返回顶部
顶部