如何强制 makefile 重建目标?

2024-10-23 08:47:00
admin
原创
231
摘要:问题描述:我有一个 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
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用