伪目标是这样一个目标:它不代表一个真正的文件名,在执行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. xml配置和基于java类的bean配置搭配使用

    如果同时使用了xml配置,和java类的bean配置(当然估计项目中一般不会这样), 在初始化容器指定资源文件的时候可能会比较麻烦 此时我们可以把基于java类的bean配置整合到xml中,或xml的 ...

  2. 谈谈Javascript线程

          其实,大家都知道Javascript的语言执行环境是单线程的,浏览器无论在什么时候都有且只有一个线程在运行Javascript程序.那Ajax发送异步请求怎么解释,setTimeout/s ...

  3. Enable SPI 1.0 and 1.1 with device tre overlays on BeagleBone

    For most people the above image means absolutely nothing, but for that one guy that has been searchi ...

  4. Java基础知识强化之IO流笔记38:字符流缓冲流之BufferedWriter / BufferedReader使用

    1. 字符流缓冲流: 字符流为了高效读写,也提供了对应的字符缓冲流. BufferedWriter:字符缓冲输出流 BufferedReader:字符缓冲输入流 2. BufferedWriter使用 ...

  5. 初识jsp

    复习: 1.servlet生命周期: (1)默认是以第一次请求的时候创建并初始化Servlet,而且只做一次.(构造函数 init()) web.xml(配置后,是可以达到在服务启动后,立刻进行ser ...

  6. 【排障】每次打开word都提示要安装配置

    为什么每次打开word都提示要安装配置?很多人在打开word时,总是提示要安装配置一遍,花去不少时间,这是由于电脑里有两个不同版本的office软件,产生的原因可能是原来的卸载了没卸载干净,或是安装了 ...

  7. openwrt chinadns

    opkg update opkg install ip ipset resolveip iptables-mod-tproxy resolveip libopenssl luci-i18n-base- ...

  8. WinForm界面(一)

    一:Form对象 属性: 设计中的Name:窗体类的类名AcceptButton:窗口的确定按钮CancelButton:窗口按ESC的取消按钮 1.外观 Backcolor:背景颜色Forecolo ...

  9. linux学习记录(第六章、Linux 的文件权限与目录配置)

    书看的是鸟哥的私房菜,系统用的是centos.被微软坑了N年才发现linux才是王道. 在这里记录些学习的记录.备忘

  10. Netbeans7.0完美中文+Consolas字体显示配置(亲测可用)

    最近把开发环境从Eclipse迁移到了Netbeans上面.因为Netbeans已经相当优秀,速度快功能也不必Eclipse差,但是一只有 一个问题一直让我对eclipse非常纠结:如果把字体选择为C ...