.PHONY------makefile中的伪目标

        转载地址:http://www.cnblogs.com/chenyadong/archive/2011/11/19/2255279.html


        

      我的理解:

  拿clean举例,如果make完成后,自己另外定义一个名叫clean的文件,再执行make clean时,将不会执行rm命令。 

  为了避免出现这个问题,需要.PHONY: clean

 

      所谓伪目标就是这样一个目标,它不代表一个真正的文件名,在执行make时可以指定这个目标来执行其所在规则定义的命令,有时我们将一个伪目标成为标签。

      那么到底什么是伪目标呢?可能作为初学者还不会在乎这个问题,下面我们来看下我们将在什么时候需要它。

      首先来看下面一个例子:

      当前目录下只有一个myls1.c,于是为了让程序让makefile来管理,写了一个如下的简单的makefile。

     id="iframe_0.6127046651672572" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://www.embedu.org/Column/images/column297-1.jpg?_=2255279%22%20style=%22border:none;max-width:987px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.6127046651672572',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no" style="margin: 0px; padding: 0px; border-style: none; border-width: initial; width: 249px; height: 120px;">

       执行:

     id="iframe_0.15967659559100866" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://www.embedu.org/Column/images/column297-2.jpg?_=2255279%22%20style=%22border:none;max-width:987px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.15967659559100866',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no" style="margin: 0px; padding: 0px; border-style: none; border-width: initial; width: 375px; height: 109px;">

      大家会发现,真的可以利用这个makefile管理当前的工程,也能如期按照我们的要求生成执行文件myls。执行make clean,这样就可以删除可执行程序。

     id="iframe_0.9820439731702209" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://www.embedu.org/Column/images/column297-3.jpg?_=2255279%22%20style=%22border:none;max-width:987px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.9820439731702209',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no" style="margin: 0px; padding: 0px; border-style: none; border-width: initial; width: 320px; height: 127px;">

     接着我做了个手脚,在当前目录下建立一个叫clean的文件,那么这样执行的效果是如何?

     id="iframe_0.23243134492076933" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://www.embedu.org/Column/images/column297-4.jpg?_=2255279%22%20style=%22border:none;max-width:987px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.23243134492076933',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no" style="margin: 0px; padding: 0px; border-style: none; border-width: initial; width: 522px; height: 187px;">

      那么这个时候为什么又不能执行了?在我的makefile中其实并没有修改任何东西,为什么这个时候已经能管理工程的makefile又不能来管理文件了。那要解决这个问题就是添加两行,修改后的makefile如下:

    id="iframe_0.836591485189274" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://www.embedu.org/Column/images/column297-5.jpg?_=2255279%22%20style=%22border:none;max-width:987px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.836591485189274',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no" style="margin: 0px; padding: 0px; border-style: none; border-width: initial; width: 398px; height: 138px;">

      再次返回执行:

     id="iframe_0.5719439359381795" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://www.embedu.org/Column/images/column297-6.jpg?_=2255279%22%20style=%22border:none;max-width:987px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.5719439359381795',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no" style="margin: 0px; padding: 0px; border-style: none; border-width: initial; width: 454px; height: 126px;">

      这样就解决了问题,那具体的原因是什么?

      在makefile中我们使用伪目标就可以解决上述的问题,那为什么要使用伪目标,一种就是如例题,为了避免在makefile中定义的只执行命令的目标和工作目录下的实际文件出现名字冲突,另一种是提交执行makefile时的效率

      第一种情况:

      如果我们需要书写这样的一个规则:规则所定义的命令不是去创建目标文件,而是通过make命令行明确指定它来执行一些特点的命令,就像例题中的clean。当文件夹中没有clean这个文件的时候,我们输入“make clean”能按照初衷执行,但是一旦文件夹中出现clean文件,我们再次输入“make clean”,由于这个规则没有任何依赖文件,所以目标被认为是最新的而不去执行规则所定义的命令。所以rm命令不会被执行。为了解决问题,我们将目标clean定义成伪目标。也就是添加:.PHONY:clean

      那么目录中不论是否有clean文件,只要输入“make clean”就能执行rm命令了。

      当一个目标被声明为伪目标后,make在执行规则时不会去试图去查找隐含规则来创建它。这样就提高了make的执行效率,也不用担心由于目标和文件名重名了。


      第二种情况:

      伪目标的另一种使用场合时在make的并行和递归执行过程中。给了例子:

SUBDIRS=foo bar baz
        Subdirs:
                for dir in $(SUBDIRS)
                do
                $(MAKE) –C $$dir
                done

     如果这样写,会出现几个问题:

     1、 当子目录执行make出现错误,make不会退出;

     2、 使用这种shell的循环方式时,没有用到make对目录的并行处理功能。

     有了伪目标就可以解决上面的两个问题。

SUBDIRS=foo bar baz
        .PHONY:subdirs $(SUBDIRS)
        subdirs: $(SUBDIRS)
        $(SUBDIRS):
                $(MAKE) –C $@

      一般情况下,一个伪目标不作为另一个目标的依赖。当一个伪目标没有作为任何目标的依赖时,我们只能通过make命令来明确指定它为make的终极目标,来执行它所在规则所定义的命令。

      还有一个特别的伪目标——all,如果我们在一个目录下创建多个可执行程序,我们可以将所有程序的重建规则在一个makefile中描述。

all: p1 p2 p3
        p1:p1.c
        p2:p2.c
        p3:p3.c




  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值