伪目标是这样一个目标:它不代表一个真正的文件名,在执行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=15,b=16; printf("a+b=%d\n",add(a,b)); return 0;
} 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中.PHNOY的用法的更多相关文章

  1. 通用 Makefile(及makefile中的notdir,wildcard和patsubst)

    notdir,wildcard和patsubst是makefile中几个有用的函数,以前没留意过makefile中函数的用法,今天稍微看看~ 1.makefile里的函数 makefile里的函数使用 ...

  2. Makefile中export分析

    在分析内核启动过程的./arch/arm/Makefile文件里碰到了这样字段 162 export TEXT_OFFSET GZFLAGS MMUEXT 然后在子目录arch/arm/kernel/ ...

  3. linux中make的用法

    一.linux中make的用法 目的:       基本掌握了make 的用法,能在Linux系统上编程.环境:       Linux系统准备:       准备三个文件:file1.c, file ...

  4. makefile中的wildcard 、patsubst、

    在Makefile规则中,通配符会被自动展开.但在变量的定义和函数引用时,通配符将失效. 这种情况下如果需要通配符有效,就需要使用函数“wildcard”,它的用法是:$(wildcard PATTE ...

  5. makefile中一些编译器选项

    Libraries Static Libraries a collection of ordinary object files (目标文件的集合) loaded at program link ti ...

  6. makefile中的shell编程注意点

    参考:http://blog.csdn.net/wanglang3081/article/details/49423105 (1)Makefile本质上来讲也是shell脚本,即每条command都是 ...

  7. makefile 中wildcard

    在Makefile规则中,通配符会被自动展开.但在变量的定义和函数引用时,通配符将失效.这种情况下如果需要通配符有效,就需要使用函数“wildcard”,它的用法是:$(wildcard PATTER ...

  8. Makefile中wildcard的介绍

    在Makefile规则中,通配符会被自动展开.但在变量的定义和函数引用时,通配符将失效.这种情况下如果需要通配符有效,就需要使用函数“wildcard”,它的用法是:$(wildcard PATTER ...

  9. [转] Makefile 基础 (7) —— Makefile 中 make 的运行

    该篇文章为转载,是对原作者系列文章的总汇加上标注. 支持原创,请移步陈浩大神博客:(最原始版本) http://blog.csdn.net/haoel/article/details/2886 我转自 ...

随机推荐

  1. MyBatis-CURD

    一.接口方法 /** * 删除.修改.添加操作都可以返回三种类型 * Integer.Long.Boolean */ public interface MyUserMapper { public My ...

  2. Linux记录-文件格式

    yum -y install dos2unix dos2unix filename

  3. jQuery中获取a标签的值

    如题,一组相同action的a标签,不同的是a标签的内容为搜索内容.点击页面显示不同的数据 刚开始试过在 a标签中添加 value值 和id 的值,结果在jQuery中获取值均失败! 后来发现,根本不 ...

  4. HDU 1064(求平均数 **)

    题意是求 12 个浮点数的平均数,这题不用读题,看到运行时间为 200 ms 再看下样例就能猜出题目的要求了,代码如下: #include <bits/stdc++.h> using na ...

  5. tmux用法【常用】

    类似各种平铺式窗口管理器,tmux使用键盘操作,常用快捷键包括: Ctrl+b 激活控制台:此时以下按键生效 系统操作 ? 列出所有快捷键:按q返回 d 脱离当前会话:这样可以暂时返回Shell界面, ...

  6. Kudu系列: Kudu主键选择策略

    每个Kudu 表必须设置Pimary Key(unique), 另外Kudu表不能设置secondary index, 经过实际性能测试, 本文给出了选择Kudu主键的几个策略, 测试结果纠正了我之前 ...

  7. spring注解第01课 @Configuration、@Bean

    一.原始的 xml配置方式 1.Spring pom 依赖 <dependency> <groupId>org.springframework</groupId> ...

  8. Ubuntu中安装python3.6(转)

    因为TensorFlow只支持到python3.6,所以安装python3.6版本 Python3.6的使用越来越普遍.Ubuntu16.04的版本中默认胸自带python2和python3.5的版本 ...

  9. [C++]最小生成元 (Digit Generator, ACM/ICPC Seoul 2005, UVa1583)

    Question 例题3-5 最小生成元 (Digit Generator, ACM/ICPC Seoul 2005, UVa1583) 如果x+x的各个数字之和得到y,就是说x是y的生成元.给出n( ...

  10. mysql每组前N条

    SELECT * from ( select end rownum, else @prov:=t.province end prov, t.* from ( money UNION all money ...