如何在GNU Make中以编程方式定义目标? [英] How to programmatically define targets in GNU Make?

查看:98
本文介绍了如何在GNU Make中以编程方式定义目标?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am not aware of any way to define programatically targets in GNU Make. How is this possible?

有时您可以替换方法.但是,在Makefile中以编程方式定义目标的功能对于使用make编写和组织复杂的生产规则非常重要.在FreeBSD的构建系统或Makefile库中,例如 BSD猫头鹰

Sometimes one can go away with alternate methods. The ability to define programatically targets in Makefiles is however a very important to write and organise complex production rules with make. Examples of complex production rules are found in the build system of FreeBSD or in Makefile libraries such as BSD Owl

shell脚本和Makefile之间的主要区别是:

The main differences between shell scripts and Makefiles are:

  • 在Makefile中,程序的状态由命令行和文件系统指定,因此可以在中断作业后恢复作业.当然,这需要正确地编写Makefile,但是即使这样做相当困难,也比通过shell脚本实现类似的效果要容易得多.

  • In a Makefile, the state of the program is given by the command line and the filesystem, so it is possible to resume a job after it has been interrupted. Of course, this requires to properly write the Makefiles, but even if this is rather hard, it is considerably easier than to achieve a similar effect with a shell script.

在Makefile中,用advis装饰程序或用钩子装饰程序是非常容易的,而在shell脚本中这实际上是不可能的.

In a Makefile, it is ridiculously easy to decorate a procedure with advises or decorate it with hooks, while this is essentially impossible in shell scripts.

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

For instance, a very simple and useful pattern is the following:

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

这将build目标呈现为三个目标的组合,一个目标包含实际指令do-build,另外两个目标是钩子,在do-build之前和之后执行.许多为BSD Make编写的构建系统都使用了这种模式,顺便说一下,它允许以编程方式定义目标,因此可以批量编写:

This presents the build target as a composite of three targets, one containing the actual instructions do-build and two other that are hooks, executed before and after do-build. This pattern is used by many build systems written for BSD Make, which incidentally allows programmatic definition of targets, so that one can write in a batch:

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

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

The condition introduced by the .if/.endif block enables the user to use its own definition of any ${_target}.

该代码片段对GNU Make的翻译是什么?

What would be the translation of that snippet for GNU Make?

推荐答案

FWIW这是与之等效的语法

FWIW here is the make equivalent syntax for

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

基本上,您希望 make 看到如下代码片段:

Basically, you want make to see something like this snippet:

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

,并且对于configuretestinstall同样.这表明在某处带有eval的循环:

and similarly for configure, test and install. This suggests a loop with an eval somewhere:

define makerule =
  $1: pre-$1
  $1: do-$1
  $1: post-$1
endef

targets := configure build test install

$(foreach _,${targets},$(eval $(call makerule,$_)))

(要进行此操作,请将eval更改为info).小心那些关闭!

(to play with this, change eval to info). Careful with those closures!

FWIW,这是foreach的扩展:

FWIW, here's the expansion of the foreach:

  • make 扩展要迭代的列表
    • ${targets}变为configurebuildtestinstall
    • 我们有$(foreach _,configure build test install,$(eval $(call makerule,$_)))
    • make expands the list to be iterated over
      • ${targets} becomes configure, build, test and install
      • We have $(foreach _,configure build test install,$(eval $(call makerule,$_)))
      • 通过将1设置为configure并展开${makerule}会产生3行文本来实现此目的:
        configure: pre-configure
        configure: do-configure
        configure: post-configure
      • It does this by setting 1 to configure, and expanding ${makerule} which produces 3 lines of text:
        configure: pre-configure
        configure: do-configure
        configure: post-configure

      请注意:我必须同意所有其他评论者的意见:您的模式很糟糕.如果您的makefile文件不是-j安全文件,则说明该文件已损坏(缺少相关性).

      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).

      这篇关于如何在GNU Make中以编程方式定义目标?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆