首页 文章

使溢出¹,或“如何覆盖目标?”

提问于
浏览
3

我有一系列(数十个)项目,包含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 回答

  • 0

    Updated answer: 如果您的配方具有依赖关系,则默认情况下不能覆盖这些依赖关系 . 那么$(eval)可能会像这样保存你:

    在工具箱中有一个宏定义与您的通用规则:

    ifndef TARGET_FMT_COMMANDS
    define TARGET_FMT_COMMANDS
        command1 # note this these commands should be prefixed with TAB character
        command2
    endef
    endif
    
    define RULE_TEMPLATE
    %-target.fmt: $(1)
        $$(call TARGET_FMT_COMMANDS)
    
    endef
    
    # define the default dependencies, notice the ?= assignment
    TARGET_DEPS?=list dependencies here
    
    # instantiate the template for the default case
    $(eval $(call RULE_TEMPLATE,$(TARGET_DEPS)))
    

    然后进入调用代码,在包含工具包之前定义TARGET_FMT_COMMANDS和TARGET_DEPS,这应该可以解决问题 .

    (请原谅定义/变量的名称,它们只是一个例子)

    Initial answer: 好吧,我在工具箱中写这个:

    define TARGET_FMT_COMMANDS
        command1 # note this these commands should be prefixed with TAB character
        command2
    endef
    
    %-target.fmt:
        $(call TARGET_FMT_COMMANDS)
    

    您可以在 include toolkit/Makefile 之后重新定义TARGET_FMT_COMMANDS

    诀窍是如果不是你得到奇怪的错误,系统地让TAB字符在定义内部执行命令 .

    您也可以像往常一样为定义提供参数 .

  • 1

    我遇到了同样的问题,我最终解决了覆盖目标不覆盖先决条件的问题,即覆盖先决条件的规则以及强制其中一些是空命令 .

    在toolkit / Makefile中:

    test: depend depend1 depend2
       @echo test toolkit
    ...
    

    在Makefile中:

    include toolkit/Makefile
    
    depend1 depend2: ;
    
    test: depend
       @echo test
    

    请注意,depend1和depend2现在具有空目标,因此覆盖了测试目标的命令,并且有效地覆盖了依赖项 .

相关问题