我有一系列(数十个)项目,包含git存储库中的大量内容 . 每个存储库都有一个通用工具包的git子模块 . 该工具包包含处理内容存储库和构建可发布结果所需的库和脚本 . 所有存储库都被推送到运行CI的主机并发布结果 . 我们的想法是将重复的代码保持在绝对最小值,并且大部分内容都存储在存储库中,并依赖于工具包,并以相同的方式将它们放在一起用于每个项目 .
每个项目都有一个顶级的Makefile,通常只有几行,例如:
STAGE = stage
include toolkit/Makefile
stage变量有一些关于这个特定阶段的信息,它确定构建哪些格式 . 几乎所有其他东西都由工具包中的600行Makefile处理 . 构建一些输出格式可能需要很长的依赖关系:源的进程可能触发目标规则,但是为了到达目标,可能存在8-10个中间依赖关系,其中在最终目标可以生成之前生成各种文件制作 .
我遇到过几种情况,我只想在一个项目中使用 completely replace (而不仅仅是扩展)特定的目标规则 . 目标在一系列依赖关系的中间被触发,但我想为这一步做一些完全不同的事情 .
我试过替换顶级Makefile中的目标:
STAGE = stage
%-target.fmt:
commands
include toolkit/Makefile
这是特别记录的 not 得到支持,但令人着迷的是它在某些时候有效 . 我似乎对此产生了重大影响 . 如果重要,是的,在目标中使用模式很重要 .
有时使用一个makefile大致就像另一个makefile一样有用 . 您通常可以使用'include'指令将一个包含在另一个中,并添加更多目标或变量定义 . 但是,对于两个makefile,为同一目标提供不同的配方是无效的 .
有趣的是,如果我将自定义函数放在include下面的顶级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,并且很困惑为什么自动完成没有开始 .
2 回答
Updated answer: 如果您的配方具有依赖关系,则默认情况下不能覆盖这些依赖关系 . 那么$(eval)可能会像这样保存你:
在工具箱中有一个宏定义与您的通用规则:
然后进入调用代码,在包含工具包之前定义TARGET_FMT_COMMANDS和TARGET_DEPS,这应该可以解决问题 .
(请原谅定义/变量的名称,它们只是一个例子)
Initial answer: 好吧,我在工具箱中写这个:
您可以在
include toolkit/Makefile
之后重新定义TARGET_FMT_COMMANDS诀窍是如果不是你得到奇怪的错误,系统地让TAB字符在定义内部执行命令 .
您也可以像往常一样为定义提供参数 .
我遇到了同样的问题,我最终解决了覆盖目标不覆盖先决条件的问题,即覆盖先决条件的规则以及强制其中一些是空命令 .
在toolkit / Makefile中:
在Makefile中:
请注意,depend1和depend2现在具有空目标,因此覆盖了测试目标的命令,并且有效地覆盖了依赖项 .