如何在GNU Make中以编程方式定义目标? [英] How to programmatically define targets in 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
,并且对于configure
,test
和install
同样.这表明在某处带有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}
变为configure
,build
,test
和install
- 我们有
$(foreach _,configure build test install,$(eval $(call makerule,$_)))
- make expands the list to be iterated over
${targets}
becomesconfigure
,build
,test
andinstall
- 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
toconfigure
, 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屋!
-