我不知道在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的那个片段的翻译是什么?
答案 0 :(得分:3)
如果您想要支持并行构建,首先此结构无效;如果你使用-j
选项调用make,它将同时运行所有三个先决条件规则,因为虽然所有这些规则必须在build
之前完成,但它们都没有相互依赖,所以#39} ; s没有定义排序(也就是说,在pre-build
可以运行之前,你不能说do-build
必须完成。)
其次,GNU make为programmatically defining rules提供了许多功能。目前,GNU make还没有能够搜索已定义的目标,因此没有直接类比.if !target(...)
。
但是,您可以使用.VARIABLES
变量搜索是否已定义变量。因此,如果您需要自己的目标,然后让规则生成器检查,那么一种解决方法是定义变量。
答案 1 :(得分:3)
这里的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
,同样适用于configure
,test
和install
。这表明在某处有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
:
${targets}
变为configure
,build
,test
和install
$(foreach _,configure build test install,$(eval $(call makerule,$_)))
_
设置为第一个值configure
。$(eval $(call makerule,configure))
eval
,制作展开$(call makerule,configure)
1
设置为configure
并展开生成3行文字的${makerule}
来实现此目的:configure: pre-configure
configure: do-configure
configure: post-configure
$(eval)
开始工作,将此文本作为 make 语法$(eval)
的展开是空的!它的所有工作都是副作用。
洗净,起泡,冲洗,重复。 请注意:我必须同意所有其他评论者:您的模式糟糕制作。如果您的makefile不是-j
安全的,那么已损坏(缺少依赖项)。