伪目标是这样一个目标:它不代表一个真正的文件名,在执行make时可以指定这个目标来执行所在规则定义的命令,有时也可以将一个伪目标称为标签。伪目标通过   PHONY来指明。

PHONY定义伪目标的命令一定会被执行,下面尝试分析这种优点的妙处。

1、如果我们指定的目标不是创建目标文件,而是使用makefile执行一些特定的命令,例如:

clean:
rm *.o temp

我们希望,只要输入”make clean“后,”rm *.o temp“命令就会执行。但是,当当前目录中存在一个和指定目标重名的文件时,例如clean文件,结果就不是我们想要的了。输入”make clean“后,“rm *.o temp” 命令一定不会被执行。

解决的办法是,将目标clean定义成伪目标就成了。无论当前目录下是否存在“clean”这个文件,输入“make clean”后,“rm *.o temp”命令都会被执行。

注意:这种做法的带来的好处还不止此,它同时提高了make的执行效率,因为将clean定义成伪目标后,make的执行程序不会试图寻找clean的隐含规则。

2、PHONY可以确保源文件(*.c *.h)修改后,对应的目标文件会被重建。倘若缺少了PHONY,可以看到情况会很糟。

现在做一个实验,实验的目录是/work,在这个目录中,包含了四个目录test、add、sub、include 和一个顶层目录makefile文件。test、add、sub三个目录分别包含了三个源程序test.c、add.c、sub.c和三个子目录makefile,目录include的是头文件heads.h的目录,分别展开四个目录的内容如下。

test目录
test.c
#include <stdio.h>
#include "../include/heads.h"
int main()
{
int a=,b=; printf("a+b=%d\n",add(a,b)); return ;
} makefile
test.o:test.c ../include/heads.h
gcc -c -o $@ $<
.PHONY: clean
clean:
  rm -f *.o

add目录

add.c
#include "../include/heads.h"
int add(int a,int b)
{
return (a+b);
} makefile
add.o :add.c ../include/heads.h
    gcc -c -o $@ $< 

.PHONY: clean 
clean:
rm -f *.o

sub目录

sub.c
#include "../include/heads.h"
int sub(int a,int b)
{
return a-b;
} makefile
sub.o:sub.c ../include/heads.h
      gcc -c -o $@ $< 

.PHONY: clean 
clean:
rm -f *.o

inlcude目录

heads.h
#ifndef _HEAD_H_
#define _HEAD_H_ extern int add(int,int);
extern int sub(int,int); #endif

顶层makefile文件

OBJS = ./add/add.o ./sub/sub.o ./test/test.o
program: $(OBJS)
gcc ./test/test.o ./add/add.o ./sub/sub.o -o program
$(OBJS):
make -C $(dir $@) .PHONY: clean
clean:
make -C ./add clean
make -C ./sub clean
make -C ./test clean
rm -f program

编译调试:当在/work目录中,执行make后,编译出了program应用程序。修改了任意一个源文件(test.c、sub.c、add.c、heads.h)例如test.c,重新在/work目录中执行make,发现一直提示“make: `program' is up to date.” ,而不能重建test.o,更不用说重建program。

修改顶层makefile文件,添加红色的一行

OBJS = ./add/add.o ./sub/sub.o ./test/test.o
program: $(OBJS)
gcc ./test/test.o ./add/add.o ./sub/sub.o -o program .PHONY : $(OBJS)
$(OBJS):
make -C $(dir $@) .PHONY: clean
clean:
make -C ./add clean
make -C ./sub clean
make -C ./test clean
rm -f program

加上伪目标修改后,问题就会解决。修改了任意一个源文件,执行make对应的目标文件就会重建,最后重建program。即使不修改源文件,执行make也会进入源文件目录中执行子make,但不会更新目标文件,最后还要重建program。

原因分析:由于(*.c *.h)- - > (*.o)- - > (program),修改前的顶层目标(program)依赖于(*.o)。执行make时,检查 (program)的依赖(*.o)是否比(program)新,而不会检查(*.h *.c)是否比(program)新,(*.h *.c)不是(program)的依赖。显然,(*.o)没有program新,所以不用重建。

注意修改后的makefile,把./add/add.o ./sub/sub.o ./test/test.o当做三个伪目标,所以不会再检查 (program)的依赖(*.o)是否比(program)新。而原来的makefile中把./add/add.o ./sub/sub.o ./test/test.o当做三个依赖文件。可以说加上“PHONY”后,make程序对./add/add.o ./sub/sub.o ./test/test.o的看法已经完全不一样了。

修改后的makefile,强制执行./add/add.o ./sub/sub.o ./test/test.o这三个伪目标的命令,即进入相应的子目录执行make,从而调用相应的子目录makefile。由于子目录中的makefile目标是(*.o),目标的依赖是(*.c heads.h),会检查(*.c heads.h)是否比(*.o)新,从而有可能重建(*.o)。而在跳回到顶层makefile后,还要执行“ gcc ./test/test.o ./add/add.o ./sub/sub.o -o program”。

总结:PHONY伪目标可以解决源文件不是最终目标直接依赖(实际上可以认为是间接依赖)带来的不能自动检查更新规则。

makefile中PHONY的重要性的更多相关文章

  1. Makefile中.PHONY的作用

    单词phony (即phoney)的意思是:伪造的,假的.来自collins的解释是: If you describe something as phoney, you disapprove of i ...

  2. makefile中.PHNOY的用法

    makefile中PHONY的重要性 伪目标是这样一个目标:它不代表一个真正的文件名,在执行make时可以指定这个目标来执行所在规则定义的命令,有时也可以将一个伪目标称为标签.伪目标通过   PHON ...

  3. Makefile 中的.PHONY

    PHONY 目标并非实际的文件名:只是在显式请求时执行命令的名字.有两种理由需要使用PHONY 目标:避免和同名文件冲突,改善性能. 所谓的PHONY这个单词就是伪造的意思,makefile中将.PH ...

  4. .PHONY makefile中的伪目标

    我的理解: 拿clean举例,如果make完成后,自己另外定义一个名叫clean的文件,再执行make clean时,将不会执行rm命令. 为了避免出现这个问题,需要.PHONY: clean === ...

  5. Makefile中 的 phony target,empty target

    phony target Makefile的语法很简单 <target> : <prerequisites> [tab] <commands> 目标.先决条件.命令 ...

  6. Makefile 中会在多处地方看到 FORCE

    转载:http://blog.csdn.net/wzw88486969/article/details/11739737 在内核的 Makefile 中会在多处地方看到 FORCE ,比如: # vm ...

  7. makefile中伪目标的理解

    1. 我们知道Makefile中的语法是这样: target ... : prerequisites ... command - - 2. 假如编译两个文件可以这么写: a.o:a.c  gcc -c ...

  8. 关于makefile中自动产生依赖的理解

    本博文是在学习了<GNU Make中文手册>后记录下来的自己的关于自动产生makefile依赖的语句的理解,向大家分享. <GNU make中文手册>中的相关章节见一下链接: ...

  9. makefile里PHONY的相关介绍

      Phony Targets PHONY 目标并非实际的文件名:只是在显式请求时执行命令的名字.有两种理由需要使用PHONY 目标:避免和同名文件冲突,改善性能. 如果编写一个规则,并不产生目标文件 ...

随机推荐

  1. zTree实现地市县三级级联DAO接口实现

    zTree实现地市县三级级联DAO接口实现 ProvinceDaoImpl.java: /** * @Title:ProvinceDaoImpl.java * @Package:com.gwtjs.d ...

  2. android中利用实现二级联动的效果

    按照惯例,首先上一张效果图. 本篇文章实现的效果就是如图中所圈的那样,实现类似于HTML中的二级联动的效果. 对于第一个选项我们读取的是本地xml文件来填充数据的, 对于第二个选项我们读取的是通过中央 ...

  3. Redis学习手册(Hashes数据类型)

    一.概述: 我们可以将Redis中的Hashes类型看成具有String Key和String Value的map容器.所以该类型非常适合于存储值对象的信息.如Username.Password和Ag ...

  4. JAVA Web 之 struts2文件上传下载演示(一)(转)

    JAVA Web 之 struts2文件上传下载演示(一) 一.文件上传演示 1.需要的jar包 大多数的jar包都是struts里面的,大家把jar包直接复制到WebContent/WEB-INF/ ...

  5. 适用于cocos2dx的编辑器:Texture,Tilemap,Particle,Action,Level etc

    原文:http://www.cocos2d-x.org/wiki/Editors_for_cocos2d-x_TextureTilemapParticleActionLevel_etc Action ...

  6. linux 修改文件时间

    1.ls -l *.sh 2.touch -d "10/13/2013" *.sh [我想把所以的.sh文件修改到三个月前(2013年10月13)的时间.]3.ls -l *.sh ...

  7. MVC架构杂谈

    来源:伯乐在线专栏作者 - 林欣达 链接:http://ios.jobbole.com/86895/ 点击 → 了解如何加入专栏作者 前言 MVC是软件工程中的一种软件架构模式,它把软件系统分为三个基 ...

  8. c# 枚举基础有[flags]和没有的的区别

    枚举提供成组的常数值,它们有助于使成员成为强类型以及提高代码的可读性.在 C# 中,使用 enum 来声明枚举. 枚举分为简单枚举和标志枚举两种. 基本语法示例 enum Day { Sun, Mon ...

  9. Hessian

    一.远程通讯协议的基本原理 网络通信需要做的就是将流从一台计算机传输到另外一台计算机,基于传输协议和网络 IO 来实现,其中传输协议比较出名的有 http . tcp . udp 等等, http . ...

  10. Eclipse下使用Hadoop单机模式调试MapReduce程序

    在单机模式下Hadoop不会使用HDFS,也不会开启任何Hadoop守护进程,所有程序将在一个JVM上运行并且最多只允许拥有一个reducer 在Eclipse中新创建一个hadoop-test的Ja ...