如何强制 makefile 重建目标?

2024-10-23 08:47:00
admin
原创
78
摘要:问题描述:我有一个 makefile,它构建后会调用另一个 makefile。由于这个 makefile 调用了更多 makefile 来完成工作,因此它实际上并没有改变。因此它一直认为项目已构建且是最新的。dnetdev11 ~ # make make: `release' is up t...

问题描述:

我有一个 makefile,它构建后会调用另一个 makefile。由于这个 makefile 调用了更多 makefile 来完成工作,因此它实际上并没有改变。因此它一直认为项目已构建且是最新的。

dnetdev11 ~ # make
make: `release' is up to date.

我如何强制 makefile 重建目标?

clean = $(MAKE) -f ~/xxx/xxx_compile.workspace.mak clean


build = svn up ~/xxx                                                       \n        $(clean)                                                                \n        ~/cbp2mak/cbp2mak -C ~/xxx ~/xxx/xxx_compile.workspace        \n        $(MAKE) -f ~/xxx/xxx_compile.workspace.mak $(1)                    \n

release:
        $(build )

debug:
        $(build DEBUG=1)

clean:
        $(clean)

install:
        cp ~/xxx/source/xxx_utility/release/xxx_util /usr/local/bin
        cp ~/xxx/source/xxx_utility/release/xxxcore.so /usr/local/lib

注:为保护无辜者,姓名被删除

最终修复版本:

clean = $(MAKE) -f xxx_compile.workspace.mak clean;


build = svn up;                                         \n        $(clean)                                        \n        ./cbp2mak/cbp2mak -C . xxx_compile.workspace;   \n        $(MAKE) -f xxx_compile.workspace.mak    $(1);   \n

.PHONY: release debug clean install

release:
        $(call build,)

debug:
        $(call build,DEBUG=1)

clean:
        $(clean)

install:
        cp ./source/xxx_utillity/release/xxx_util /usr/bin
        cp ./dlls/Release/xxxcore.so /usr/lib

解决方案 1:

make 的开关-B,其完整形式为--always-make,指示make忽略时间戳并生成指定的目标。这可能会违背使用 make 的目的,但这可能是您所需要的。

解决方案 2:

你可以将你的一个或多个目标声明为虚假的。

伪目标实际上并不是文件的名称;它只是您发出明确请求时要执行的配方的名称。使用伪目标有两个原因:避免与同名文件发生冲突,以及提高性能。

...

虚假目标不应是真实目标文件的先决条件;如果是,则每次 make 更新该文件时都会运行其配方。只要虚假目标永远不是真实目标的先决条件,则仅当虚假目标是指定目标时才会执行虚假目标配方

解决方案 3:

Sun 手册中曾经记录过一个技巧,即make使用(不存在的)目标“.FORCE”。您可以通过创建文件 force.mk 来实现此目的,该文件包含:

.FORCE:
$(FORCE_DEPS): .FORCE

然后,假设您现有的 makefile 名为makefile,您可以运行:

make FORCE_DEPS=release -f force.mk -f makefile release

由于.FORCE不存在,任何依赖它的东西都会过时并被重建。

所有这些都适用于任何版本的make;在 Linux 上,您拥有 GNU Make,因此可以使用所讨论的 .PHONY 目标。

还值得考虑为什么make认为 release 是最新的。这可能是因为touch release在执行的命令中有一个命令;可能是因为有一个名为“release”的文件或目录存在并且没有依赖项,因此是最新的。然后是实际原因...

解决方案 4:

其他人建议使用 .PHONY,这绝对是正确的。对于输入和输出之间的日期比较无效的任何规则,都应使用 .PHONY。由于您没有任何格式的目标,因此output: input您应该对所有目标使用 .PHONY!

尽管如此,您可能应该在 makefile 的顶部为各种文件名定义一些变量,并定义具有输入和输出部分的实际 make 规则,以便您可以利用 make 的好处,即您实际上只会编译编译所需的东西!

编辑:添加了示例。未经测试,但这就是执行 .PHONY 的方法

.PHONY: clean    
clean:
    $(clean)

解决方案 5:

make clean删除所有已编译的目标文件。

解决方案 6:

如果我没记错的话,“make”使用时间戳(文件修改时间)来确定目标是否是最新的。强制重新构建的常用方法是使用“touch”命令更新该时间戳。您可以尝试在 makefile 中调用“touch”来更新其中一个目标(可能是其中一个子 makefile)的时间戳,这可能会强制 Make 执行该命令。

解决方案 7:

我尝试过这个,它对我有用

将这些行添加到 Makefile

clean:
    rm *.o output

new: clean
    $(MAKE)     #use variable $(MAKE) instead of make to get recursive make calls

保存并立即调用

make new 

它将再次重新编译所有内容

发生了什么?

1) 'new' 调用 clean。'clean' 执行 'rm',删除所有以 '.o' 为扩展名的目标文件。

2) 'new' 调用 'make'。'make' 发现没有 '.o' 文件,因此再次创建所有 '.o'。然后链接器将所有 .o 文件链接到一个可执行输出

祝你好运

解决方案 8:

这种简单的技术可以让 makefile 在不需要强制时正常运行。在makefile末尾创建一个名为force的新目标。force目标将触及默认目标所依赖的文件。在下面的示例中,我添加了touch myprogram.cpp 。我还添加了对make 的递归调用。这将导致每次键入make force时都会生成默认目标。

yourProgram: yourProgram.cpp
       g++ -o yourProgram yourProgram.cpp 

force:
       touch yourProgram.cpp
       make

解决方案 9:

正如 abernier 指出的那样,GNU make 手册中有一个推荐的解决方案,它使用“假”目标来强制重建目标:

clean: FORCE
        rm $(objects)
FORCE: ; 

无论任何其他依赖项如何,它都将干净运行。

我从手册中为解决方案添加了分号,否则需要一个空行。

解决方案 10:

根据 Miller 的《递归 Make 被认为有害》一文,您应该避免调用$(MAKE)!在您展示的情况下,它是无害的,因为这实际上不是一个 makefile,只是一个包装器脚本,它可能也是用 Shell 编写的。但是您说您会在更深的递归级别继续这样做,所以您可能遇到了那篇令人大开眼界的文章中显示的问题。

当然,使用 GNU make 时,避免这个问题会很麻烦。尽管他们意识到了这个问题,但这是他们记录在案的做事方式。

另一方面,makepp就是为了解决这个问题而创建的。您可以在每个目录级别编写 makefile,但它们都会被集中到项目的完整视图中。

但是传统的 makefile 是递归编写的。因此,有一种解决方法,它$(MAKE)什么也不做,只是将子请求引导回主 makepp 进程。只有当您在子 make 之间执行了冗余或更糟的矛盾操作时,您才必须请求--traditional-recursive-make(这当然会破坏 makepp 的这一优势)。我不知道您的其他 makefile,但如果它们编写得干净利落,那么使用 makepp 所需的重建应该会自动进行,而无需其他人在此处建议的任何黑客攻击。

解决方案 11:

已经提到过了,但我认为我可以补充使用touch

如果您touch要编译所有源文件,该touch命令会将文件的时间戳更改为touch执行命令的系统时间。

源文件时间戳用于make“知道”文件已更改,需要重新编译

例如:如果该项目是 C++ 项目,则执行touch *.cpp,然后再次运行make,make 应该重新编译整个项目。

解决方案 12:

如果你不需要保留任何已经成功编译的输出

nmake /A 

重建所有

解决方案 13:

这实际上取决于目标是什么。如果是虚假目标(即目标与文件无关),则应将其声明为 .PHONY。

但是,如果目标不是虚假目标,但您只是出于某种原因想要重建它(例如当您使用 TIME 预处理宏时),您应该使用此处的答案中描述的 FORCE 方案。

解决方案 14:

在我的 Linux 系统 (Centos 6.2) 上,当规则确实创建与目标匹配的文件时,声明目标 .PHONY 和创建对 FORCE 的虚假依赖之间存在显著差异。当每次都必须重新生成文件时,它既需要对文件进行虚假依赖 FORCE,又需要对虚假依赖进行 .PHONY。

错误的:

date > $@

正确的:

FORCE
    date > $@
FORCE:
    .PHONY: FORCE
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用