【发布时间】:2024-01-10 05:03:01
【问题描述】:
我有一系列(数十个)项目,其中包含 git 存储库中的大量内容。每个存储库都有一个通用工具包的 git 子模块。该工具包包含处理内容存储库和构建可发布结果所需的库和脚本。所有存储库都被推送到运行 CI 并发布结果的主机。这个想法是将重复的代码保持在绝对最低限度,并且大部分内容都在存储库中,并且依赖于工具包以将每个项目以相同的方式组合在一起。
每个项目都有一个* Makefile,通常只有几行,例如:
STAGE = stage
include toolkit/Makefile
stage 变量有一些关于这个特定的阶段的信息,决定了构建哪些格式。几乎所有其他内容都由工具包中的 600 行 Makefile 处理。构建某些输出格式可能需要一长串依赖关系:源的过程可能会触发目标规则,但要到达目标可能需要 8-10 个中间依赖关系,其中在最终目标生成之前会生成各种文件制作。
我遇到过几种情况,我想完全替换(而不仅仅是扩展)一个项目中的特定目标规则。目标在一系列依赖关系的中间被触发,但我想为这一步做一些完全不同的事情。
我尝试只替换顶层 Makefile 中的目标:
STAGE = stage
%-target.fmt:
commands
include toolkit/Makefile
这是专门记录在不要支持的,但很吸引人的是它有时会起作用。我尝试更改声明自定义目标和包含的顺序,但这似乎并没有显着影响。如果重要的话,是的,在目标中使用模式很重要。
有时,拥有一个类似于另一个 makefile 的 makefile 是很有用的。您通常可以使用“包含”指令将一个包含在另一个中,并添加更多目标或变量定义。但是,对于同一个目标,两个 makefile 给出不同的配方是无效的。
有趣的是,如果我将自定义函数放在顶层 Makefile 下面包含我可以覆盖工具包中的函数,这样$(call do_thing) 将使用我的覆盖:
STAGE = stage
include toolkit/Makefile
define do_thing
commands
endef
但是,目标似乎并非如此。我知道two colon syntax,但我不想只是扩展具有更多依赖项的现有目标,我想用生成相同文件的不同方式完全替换目标。
我曾考虑过使用递归调用来生成as suggested in the documentation,但随后包含在工具包 Makefile 中广泛设置的辅助函数的环境将不适用于* Makefile 中的任何目标。这将是一个表演的终结者。
有什么方法可以让 make 为我破例吗?可以强制它成为压倒一切的目标吗?我只使用最新版本的 GNU-Make,并且不太关心可移植性。如果做不到这一点,还有另一种实现相同目的的概念方法吗?
¹ 我的大脑今天没有喝足够的咖啡。在尝试打开 Stack Overflow 来询问这个问题时,我在浏览器中输入了makeoverflow.com,并且很困惑为什么没有启动自动完成功能。
【问题讨论】:
-
我说对了吗,您的工具包还包含
%-target.fmt规则以及您想要覆盖的一些默认命令? -
@valir 是的。先决条件和配方都不同,但规则名称相同,我想用顶层的那个完全覆盖工具包中的那个。