首页 文章

如何以编程方式定义GNU Make中的目标?

提问于
浏览
1

我不知道有任何方法可以在GNU Make中定义编程目标 . 这怎么可能?

有时一个人可以离开with alternate methods . 但是,在Makefile中定义编程目标的能力对于使用 make 编写和组织复杂的 生产环境 规则非常重要 . 复杂 生产环境 规则的示例可在FreeBSD的构建系统或Makefile库中找到,例如BSD Owl

shell脚本和Makefile之间的main differences是:

  • 在Makefile中,程序的状态由命令行和文件系统给出,因此可以在作业中断后恢复作业 . 当然,这需要正确编写Makefile,但即使这很难,但要比使用shell脚本实现类似的效果要容易得多 .

  • 在Makefile中,使用建议装饰过程或用钩子装饰它是非常容易的,而这在shell脚本中基本上是不可能的 .

例如,一个非常简单和有用的模式如下:

build: pre-build
build: do-build
build: post-build

这将 build 目标显示为三个目标的组合,一个包含实际指令 do-build ,另外两个是挂钩,在 do-build 之前和之后执行 . 这种模式被许多为BSD Make编写的构建系统使用,它偶然允许对目标进行编程定义,以便可以批量编写:

.for _target in configure build test install
.if !target(${_target})
${_target}: pre-${_target}
${_target}: do-${_target}
${_target}: post-${_target}
.endif
.endfor

.if/.endif 块引入的条件使用户能够使用自己的任何 ${_target} 定义 .

GNU Make的片段翻译是什么?

2 回答

  • 2

    这里的FWIW是make等效语法

    .for _target in configure build test install
    .if !target(${_target})
    ${_target}: pre-${_target}
    ${_target}: do-${_target}
    ${_target}: post-${_target}
    .endif
    .endfor
    

    基本上,你想让make看到这样的代码片段:

    build: pre-build
    build: do-build
    build: post-build
    

    configuretestinstall 类似 . 这暗示了一个带有 eval 的循环:

    define makerule =
      $1: pre-$1
      $1: do-$1
      $1: post-$1
    endef
    
    targets := configure build test install
    
    $(foreach _,${targets},$(eval $(call makerule,$_)))
    

    (要使用此功能,请将 eval 更改为 info ) . 小心那些关闭!

    FWIW,这是 foreach 的扩展:

    • make扩展要迭代的列表

    • ${targets} 变为 configure ,_ buildtestinstall

    • 我们有 $(foreach _,configure build test install,$(eval $(call makerule,$_)))

    • _ 设置为第一个值 configure .

    • make expands $(eval $(call makerule,configure))

    • 要评估 eval ,请展开 $(call makerule,configure)

    • 它通过将 1 设置为 configure 并展开生成3行文本的 ${makerule} 来实现此目的:
      configure: pre-configure
      configure: do-configure
      configure: post-configure

    • $(eval) 开始工作,将此文本作为make语法阅读

    • 注意 $(eval) 的扩展是空的!它的所有工作都是副作用 . 洗净,起泡,冲洗,重复 .

    Please note: I have to agree with all the other commenters: your pattern is bad make. If your makefile is not -j safe, then it is broken (missing dependencies).

  • 2

    如果您想要支持并行构建,首先此结构无效;如果你使用 -j 选项调用make,它将同时运行所有三个先决条件规则,因为虽然所有这些规则必须在 build 之前完成,但它们都没有相互依赖,所以's no ordering defined (that is, you don' t表示 pre-build 必须在 do-build 之前完成能跑) .

    其次,GNU make为programmatically defining rules提供了许多功能 . 目前,GNU make还没有能够搜索已定义的目标,因此没有直接类比 .if !target(...) .

    但是,您可以使用 .VARIABLES 变量搜索是否已定义变量 . 因此,如果您需要自己的目标,然后让规则生成器检查,那么一种解决方法是定义变量 .

相关问题