文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>gnu make 学习

gnu make 学习

时间:2007-01-15  来源:kuaizaifeng

关于Makefile中的通配符

$? 的含义

通配符也可以用在规则的依赖文件名中。看看下面这个例子。执行“make print”,执行的结果是打印当前工作目录下所有的在上一次打印以后被修改过的“.c”文件。

print: *.c

    lpr -p $?

    touch print

  两点说明:1. 上述的规则中目标“print”时一个空目标文件。(不存在一个这样的文件,此目标不代表一个文件,它只是记录了一个所要执行的动作或者命令。参考 4.8 空目标文件 一节)。2. 自动环变量“$?”用在这里表示依赖文件列表中被改变过的所有文件。

4.4.3       函数wildcard

前边提到过,在规则中,通配符会被自动展开。但在变量的定义和使用函数是,通配符不会被自动的展开。这种情况下需要通配符有效,要用到函数“wildcard”,其用法:$(wildcard PATTERN...) ;在Makefile中,它被展开未已经存在的、空格分割的、匹配此模式的所有文件列表。如果不存在符合此模式的文件,那么函数会忽略模式并返回空。需要注意的是:这种情况下规则中通配符的展开和上一小节匹配通配符的区别。

一般我们可以使用“$(wildcard *.c)”来获取工作目录下的所有的.c文件列表。复杂一些用法;可以使用“$(patsubst %.c,%.o,$(wildcard *.c))”,首先使用“wildcard”函数获取工作目录下的.c文件列表;之后将列表中所有文件名的后缀.c替换为.o。这样我们就可以得到在当前目录可生成的.o文件列表。因此在一个目录下可以使用如下内容的Makefile来将工作目录下的所有的.c文件进行编译并最后连接成为一个可执行文件:

 
#sample Makefile

objects := $(patsubst %.c,%.o,$(wildcard *.c))

 

foo : $(objects)

cc -o foo $(objects)

 

这里我们使用了make的隐含规则来编译.c的源文件。对变量的赋值也用到了一个特殊的符号(:=)。 关于变量定义可参考 5.2 两种变量定义 一节。函数“patsubst”可参考 7.2 文本处理函数 一节

也可以用下面的方法来从相应的.c文件生成.o文件。
SOURCE_SIEVE_LDAP_TEST := $(SOURCES_LIBS) $(SRC)/sieve/sieve_lib.c  $(SRC)/sieve/ldap_test.c
OBJS_SIEVE_LDAP_TEST := $(SOURCE_SIEVE_LDAP_TEST:.c=.o)
ldap_test: $(OBJS_SIEVE_LDAP_TEST)
    $(CC) $(CFLAGS) $(OBJS_SIEVE_LDAP_TEST) -lexpat -lscew -lmiu -lcrypto -lldap -o $@


4.5.4 命令行和搜索目录

make在执行时,通过目录搜索得到的目标的依赖文件可能会在其它目录(此时依赖文件为文件的完整路径名),但是已经存在的规则命令却不能发生变化。因此,书写命令时我们必须保证当依赖文件在其它目录下被发现时规则的命令能够正确执行。

处理这种问题的方式就是使用“自动化变量”(可参考 9.5.3 自动化变量 一小节),诸如“$^”等。规则命令行中的自动化变量“$^”代表所有的是的通过目录搜索得到的依赖文件的完整路径名(目录+一般文件名)列表。“$@”代表规则的目标。所以对于一个规则我们可以进行如下的描述:

foo.o : foo.c

     cc -c $(CFLAGS) $^ -o $@

 
变量“CFLAGS”是编译.c文件时GCC的命令行选项,可以在Makefile中给它指定明确的值、也可以使用隐含的定义值。

规则的依赖文件列表中可以包含头文件,而在命令行不需要使用这些头文件(这些头文件的作用只有在make程序决定目标是否需要重建时才有意义)。我们可以使用另外一个变量来书代替“$^”,例如:

规则的依赖文件列表中可以包含头文件,而在命令行不需要使用这些头文件(这些头文件的作用只有在make程序决定目标是否需要重建时才有意义)。我们可以使用另外一个变量来书代替“$^”,例如:

 

VPATH = src:../headers

foo.o : foo.c defs.h hack.h

cc -c $(CFLAGS) $< -o $@

 

自动化变量“$<”代表规则中通过目录搜索得到的依赖文件列表的第一个依赖文件。关于自动化变量我们在后续有专门的讨论。

4.14 自动产生依赖

Makefile中,可能需要书写一些规则来描述一个.o目标文件和头文件的依赖关系。例如,如果在main.c中使用“#include defs.h”,那么我们可能需要如下那样的一个规则来描述当头文件“defs.h”被修改以后执行make,目标“main.o”应该被重建。

 

main.o: defs.h

 

这样,在一个比较大型的工程中。就需要在Makefile中书写很多条类似于这样的规则。并且,当在源文件中加入或删除头文件后,也需要小心地去修改Makefile。这是一件很费力、也很费时并且容易出错误的工作。为了避免这个令人讨厌的问题,现代的c编译器提供了通过查找源文件中的“#include”来自动产生这种依赖的功能。“GCC”支持一个“-M”的选项来实现此功能。“GCC”将自动找寻源文件中包含的头文件,并生成一个依赖关系。例如,如果“main.c”只包含了头文件“defs.h”,那么在Linxu下执行下面的命令:

 

gcc -M main.c

 

其输出是:

 

    main.o : main.c defs.h

 

既然编译器已经提供了自动产生依赖关系的功能,那么我们就不需要去动手写这些规则的依赖关系了。但是需要明确的是:在“main.c”中包含了其他的标准库的头文件,其输出的依赖关系中也包含了标准库的头文件。当不需要依赖关系中不考虑标准库头文件时,需要使用“-MM”参数。

需要注意的是,在使用“GCC”自动产生依赖关系时,所产生的规则中明确的指明了目标是“main.o”文件。一次在通过.c文件直接产生可执行文件时,作为过程文件的“main.o”的中间过程文件在使用完之后将不会被删除。


第五章:规则的命令

5.1      命令回显

通常,make在执行命令行之前会把要执行的命令行进行输出。我们称之为“回显”,就好像我们输入命令执行一样。

如果要执行的命令行以字符“@”开始,则make在执行时这个命令就不会被回显。典型的用法是我们在使用“echo”命令输出一些信息时。如:
     @echo 开始编译XXX模块......

当make执行时,将输出“开始编译XXX模块......”这个信息。如果在命令行之前没有字符“@”,那么,make的输出就是:

             echo编译XXX模块......

编译XXX模块......

另外,如果使用make的命令行参数“-n”或“--just-print”,那么make执行时只显示所要执行的命令,但不会真正的去执行这些命令。只有在这种情况下make才会打印出所有make需要执行的命令,其中也包括了使用“@”字符开始的命令。这个选项对于我们调试Makefile非常有用,使用这个选项我们可以按执行顺序打印出Makefile中所有需要执行的命令。

而make参数“-s”或“--slient”则是禁止所有执行命令的显示,就好像所有的命令行均使用“@”开始一样。在Makefile中使用没有依赖的特殊目标“.SILENT”也可以禁止命令的回显,但是它的缺点是不如“@”灵活。因此我们在书写Makefile时,推荐使用“@”来控制命令的回显。

5.5      中断make的执行

make在执行命令时如果收到一个致命信号(结束make),make将会删除命令重建的规则目标文件。其依据是此目标文件的当前时间戳是否和make开始时的时间戳相同。


关于$^和$<的区别

test: t1 t2

    @echo $^

    @echo $<

分别输出: t1 t2

                      t1

即$^代表所有的依赖文件;而$<仅仅代表第一个依赖文件

相关阅读 更多 +
排行榜 更多 +
山雾搜剧 1.0.0

山雾搜剧 1.0.0

系统软件 下载
布鲁伊一起玩吧2025年

布鲁伊一起玩吧2025年

休闲益智 下载
最后的试炼

最后的试炼

策略塔防 下载