首页 > 其他分享 >makefile中PHONY的重要性

makefile中PHONY的重要性

时间:2023-03-01 11:56:39浏览次数:36  
标签:sub make makefile PHONY add program 重要性 test clean

     伪目标是这样一个目标:它不代表一个真正的文件名,在执行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伪目标可以解决源文件不是最终目标直接依赖(实际上可以认为是间接依赖)带来的不能自动检查更新规则。

标签:sub,make,makefile,PHONY,add,program,重要性,test,clean
From: https://www.cnblogs.com/kn-zheng/p/17167665.html

相关文章

  • APP定制开发的重要性及流程
    APP定制开发是一种根据客户需求开发个性化移动应用的服务。在当今移动应用市场日益竞争的环境下,定制化开发已经成为企业获得竞争优势的关键之一。以下是APP定制开发的流程:......
  • Makefile入门(超详细一文读懂)
    原文:https://blog.csdn.net/ZBraveHeart/article/details/123187908 1、Makefile编译过程在这里插入图片描述  Makefile文件中的命令有一定规范,一旦该文件编写好以......
  • 低代码选型,论协同开发的重要性
    Git是一款用于分布式版本控制的免费开源软件:它可以跟踪到所有文件集中任意的变更,通常用于在软件开发期间,协调配合程序员之间的代码程序开发工作。Git最初诞生的原因源......
  • 【IMX6ULL学习笔记】三、U-BOOT Makefile详解
    00、通识版本号VERSION=2016//主版本号PATCHLEVEL=03 //补丁版本号SUBLEVEL= //次版本号EXTRAVERSION=//附加版本信息NAME= //名字有关的,一般......
  • Python实现随机森林RF并对比自变量的重要性
      本文介绍在Python环境中,实现随机森林(RandomForest,RF)回归与各自变量重要性分析与排序的过程。  其中,关于基于MATLAB实现同样过程的代码与实战,大家可以点击查看MATLA......
  • Makefile Tab键
    https://blog.csdn.net/weixin_44980842/article/details/123167307MakefileTab键 MakefileTab键 MakefileTab键 MakefileTab键......
  • 数据字典标准与统一的重要性(码表&枚举值)
    在日常的软件开发当中,开发者经常会听到“公共代码、编码、码表、枚举值”这样的名词,对这些概念可能会有些混淆和认知不透彻,那么这篇文章会详细论述一下关于数据字典的相关概......
  • Makefile 注释符
    Makefile 注释符“#字符是注释符,makefile把#字符后面的内容作为注释内容处理(shell、perl脚本也是使用#字符作为注释符)......
  • 【AI】PTP时钟同步在智能驾驶系统里的重要性
    【AI】PTP时钟同步在智能驾驶系统里的重要性【AI】PTP时钟同步在智能驾驶系统里的重要性京准电子科技官微——ahjzsz一辆宣称具备L4/L5自动驾驶功能的车辆,如果多个激光......
  • shell:Makefile从shell脚本中导入变量
    目录​​需求描述​​​​Makefile读取变量​​​​Makefile文件中定义变量​​​​Makefile从shell脚本中导入变量​​​​优先级​​​​1、导入shell中的变量​​​​2......