曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 3604|回复: 0
打印 上一主题 下一主题

伪目标

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34397
跳转到指定楼层
楼主
发表于 2011-4-19 10:43:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一般情况下,一个伪目标不作为另外一个目标文件的依赖。这是因为当一个目标文件的依赖包含伪目标时,每一次在执行这个规则时伪目标所定义的命令都会被执行(因为它是规则的依赖,重建规则目标文件时需要首先重建它的依赖)。伪目标作为另外一个目标的依赖这种情况,常见与 FORCE 的应用。


当伪目标没作为任何目标(此目标是一个可被创建或者已经存在的文件)的依赖时,一般上只能通过 make 的命令行选项明确的指定这个伪目标来执行它所定义的命令,如经常所用的 "make clean" 。但是,如果将伪目标作为第一个目标时,仍然只会执行伪目标,而底下的其它目标是不会执行的,比如:
clean:  
        @echo "always be executed"


helloworld:file1.o file2.o
        gcc file1.o file2.o -o helloworld


file1.o:file1.c file2.h
        gcc -c file1.c -o file1.o


file2.o:file2.c file2.h
        gcc -c file2.c -o file2.o


PHONY   += clean
.PHONY: $(PHONY)

运行输出:
[beyes@SLinux Makefile]$ make
always be executed

clean 伪目标被放在第 1 行,默认 make 时,它总是被执行,执行完后整个 make 也就退出了。而底下所定义的 helloworld 目标,如果你想生成它,那就要显示的去执行:
[beyes@SLinux Makefile]$ make helloworld
gcc -c file1.c -o file1.o
gcc -c file2.c -o file2.o
gcc file1.o file2.o -o helloworld

从这般的用法看来,helloworld 倒是像是伪目标了。


综合起来,不论是明确声明了的伪目标,还是可以生成实际文件的目标,它们都只是个标签,谁在最前就执行谁。在后面的要想被执行,得显示的去指出。


说到标签,那么同一个 Makefile 中,还可以有多个同名的标签,看起来是有多个同名的目标,在这种情况下会是怎么样的呢?一个 Makefile 文件内容为:

PHONY := __build
.PHONY: $(PHONY)


__build:


obj-y := timesheet
obj-m := hello


__build:
lib-y := world


__build:
        @echo $(obj-y)

        @echo $(lib-y)
上面,__build 被声明为一个伪目标。这里有多处它的标签,但实际上在运行时会看到:
$ make
timesheet
world

如果将下面含有 echo 命令的 __build 都注释掉,再运行时看到:
$ make
make: Nothing to be done for `__build'.
这时候提示,对于 __build 没啥可做。由此可以知道,标签在 Makefile 中的地位仅仅是标签而已,不论它是真实的目标标签,还是被当成是伪目标的标签,最终起主要作用的还是“依赖”或者“命令” 。


再比较一个特殊的情况,现在将上面的 Makefile 修改为:
PHONY := __build
.PHONY: $(PHONY)


__build:


obj-y := timesheet
obj-m := hello


temp:
@echo "--------------------------"


__build:
    @echo "i am here"

我们在中间插入了另外一个伪目标 temp,但是最后得到执行的不是 temp 下的命令,而是 __build 下的命令。因为在 temp 的上面已经对 __build 做了预先的声明,它等于告诉 make,它是先来的,并已经占据座位。同理,如果 temp 被先声明在 __build 之前,那么被执行的是 temp 下面的命令。

在 Makefile 中,伪目标也可以有自己的依赖。如果希望在一个目录下生成多个可执行程序,我们也可以用一个 Makefile 来实现。在 Makefile 中,第 1 个目标是“终极目标”(像上面的例子中,伪目标放在第 1 位时,它也一样成为终极目标),约定的做法是使用一个称为 "all" 的伪目标来作为终极目标(其它名字也可以)。这时,它的依赖文件就是那些需要创建的程序。比如一个 Makefile 文件的内容如下:
all: hello world ok
.PHONY:all


hello : hello.o
        gcc hello.o -o hello


hello.o: hello.c
        gcc -c hello.c -o hello.o


world : world.o
        gcc world.o -o world




world.o : world.c
        gcc -c world.c -o world.o


ok : ok.o
        gcc ok.o -o ok
ok.o : ok.c
        gcc -c ok.c -o ok.o


clean:
        -rm -f *.o hello world ok

执行 make 时,因为 all 有  3 个依赖,所以这 3 个依赖所表示的可执行文件都会被生成。如果需要单独的生成某 1 个程序,那么需要使用 make 来明确指定(如 "make hello") 。如果这些可执行文件都已经生成,且它们的各个依赖都已经是最新,再次 make 时啥也不做:
[beyes@SLinux temp2]$ make
make: Nothing to be done for `all'.

在这一点上,倒不像 GNU MAKE 中文译本(翻译时间为 2004 年)里说的 ”重建已存在目标 all 的所有依赖文件" 。


伪目标也可以作为另外一个伪目标的依赖,这时候 make 会将它作为另外一个伪目标的子例程来处理。比如有下面一个 Makefile 文件:

PHONY += all


all: hello world ok


hello : hello.o
        gcc hello.o -o hello


hello.o: hello.c
        gcc -c hello.c -o hello.o


world : world.o
        gcc world.o -o world




world.o : world.c
        gcc -c world.c -o world.o


ok : ok.o
        gcc ok.o -o ok
ok.o : ok.c
        gcc -c ok.c -o ok.o


PHONY += cleanall clwanobj cleanexe


cleanall:cleanobj cleanexe
        
cleanobj:
rm *.o

cleanexe:
rm hello world ok
        
.PHONY: $(PHONY)
在 make 后,接着执行 make cleanall ,就会看到 Makefile 分别执行了 cleanobj 和 cleanexe 这两个目标下的命令。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-6-18 02:42 , Processed in 0.084979 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表