Build 如何定义具有未知中间节点名称的依赖关系图?

Build 如何定义具有未知中间节点名称的依赖关系图?,build,makefile,scons,Build,Makefile,Scons,我使用的工具链不知道所有中间文件的名称 例如,我知道我从一个foo.s开始,经过几个步骤得到foo.XXXX.sym和foo.XXXX.hex,埋得很深。然后在foo.XXXX.hex和foo.XXXX.sym上运行其他工具,我最终得到类似final.results的结果 但是,问题是我不知道XXXX是什么。它是从其他一些参数派生出来的,但可能会被显著地转换为远离这些参数 现在,在运行生成foo.XXXX.{sym,hex}的工具/步骤之后,我通常会扫描整个结果目录以查找foo...{sym,h

我使用的工具链不知道所有中间文件的名称

例如,我知道我从一个foo.s开始,经过几个步骤得到foo.XXXX.sym和foo.XXXX.hex,埋得很深。然后在foo.XXXX.hex和foo.XXXX.sym上运行其他工具,我最终得到类似final.results的结果

但是,问题是我不知道XXXX是什么。它是从其他一些参数派生出来的,但可能会被显著地转换为远离这些参数

现在,在运行生成foo.XXXX.{sym,hex}的工具/步骤之后,我通常会扫描整个结果目录以查找foo...{sym,hex}。也就是说,我有可以识别中间输出的代码,我只是不知道确切的名称

我通常使用make或scon——实际上,我更喜欢scon,但我的团队更喜欢make。我对其他构建工具持开放态度

我想做的是能够说(1)“make final.results”或“scons final.results”;(2)并让它扫描部分树;(3) 要知道,虽然它不知道完整路径,但它肯定知道必须运行第一步,(4)在第一步之后,查找并找到foo.XXX.*文件;(5) 并将其插入依赖关系树

也就是说,我想在构建已经开始之后完成构建依赖关系树

一位朋友对scons在这方面的局限性感到非常失望,于是他编写了自己的构建工具。不幸的是,它是专有的

我想我可以创建一个第一个构建图,比如在make中创建多个.PHONY目标,然后在完成第一步后,使用新名称生成一个新的makefile,并让第一个make调用新生成的第二个makefile。看起来很笨拙。还有更优雅的方式吗?

GNU make有一个“auto rexec”功能,您可以使用它。看

make读取完所有makefiles(自动和/或在命令行上找到的makefiles,以及所有包含的makefiles)后,它将尝试重建其所有makefiles(使用它知道的规则)。如果这些makefiles中的任何一个被自动重建,那么make将重新执行它自己,以便它可以重新读取makefiles/包含文件的最新版本,并重新开始(包括重新尝试构建所有makefiles)

在我看来,你应该能用这个做点什么。例如,您可以在主makefile中编写“-include foo.sym.mk”,然后通过调用foo.s上的工具生成一个规则“foo.sym.mk”,然后运行“Recogated the next step”代码并生成一个“foo.sym.mk”文件,该文件为创建的中间输出定义一个规则。比如(由于你的问题缺乏具体性,我无法给出你理解的真实例子):

SRCS=foo.s bar.s baz.s
-包括$(patsubst%.s、%.sym.mk、$(SRCS))
%.sym.mk:%.s

“$Make在运行任何规则之前构造图形,因此不会有完美的答案。这里有一些相当干净的解决方案

1) 在命令中使用虚假的中间字符和通配符。(不能使用Make通配符,因为Make会在运行规则之前展开通配符。)

final.results:中等
#使用$(shell ls foo.*.sym)和$(shell ls foo.*.hex)构建$@
.冒牌货:中等
中间:foo.s
#从构建foo.XXXX.sym和foo.XXXX.hex$<
2) 使用递归Make(不像人们说的那么糟糕,有时非常有用)

SYM=$(通配符foo.*.SYM)
十六进制=$(通配符foo.*.HEX)
#请注意,这是您应该“制作”的。
#我把它放在第一位,所以它将是默认值。
.冒牌货:第一步
第一步:foo.s
#从构建foo.XXXX.sym和foo.XXXX.hex$<
@$(MAKE)-s最终结果
最后结果:
#使用$(符号)和$(十六进制)生成$@
3) 与2类似,但有一个makefile规则,该规则将导致Make再次运行

SYM = $(wildcard foo.*.sym)
HEX = $(wildcard foo.*.hex)

final.results:                                                                
    # build $@ using $(SYM) and $(HEX)

Makefile: foo.s
    # build foo.XXXX.sym and foo.XXXX.hex from $<
    @touch $@
SYM=$(通配符foo.*.SYM)
十六进制=$(通配符foo.*.HEX)
最后结果:
#使用$(符号)和$(十六进制)生成$@
Makefile:foo.s
#从构建foo.XXXX.sym和foo.XXXX.hex$<
@触碰$@

您不能使用隐式目标来填写您不知道的部分名称吗?也就是说,目标使用“%”s@claytontstanley No,因为不能使用类似于
final.results:foo.%.sym
@claytonstanley:我使用隐式规则来做类似的事情。贝塔提供了其中一个原因。另一个原因是,隐式规则有时撒网太广,会把不该撒网的东西捡起来。现在,我相信有一种语法可以说“这个隐式规则只适用于这些特定的文件…”谢谢。我应该知道/记住这一点。
final.results: middle                                                         
    # build $@ using $(shell ls foo.*.sym) and $(shell ls foo.*.hex)

.PHONY: middle
middle: foo.s
    # build foo.XXXX.sym and foo.XXXX.hex from $<
SYM = $(wildcard foo.*.sym)
HEX = $(wildcard foo.*.hex)

# Note that this is is the one you should "Make".
# I've put it first so it'll be the default.
.PHONY: first-step
first-step: foo.s
    # build foo.XXXX.sym and foo.XXXX.hex from $<
    @$(MAKE) -s final.results                                               

final.results:                                                                
    # build $@ using $(SYM) and $(HEX)
SYM = $(wildcard foo.*.sym)
HEX = $(wildcard foo.*.hex)

final.results:                                                                
    # build $@ using $(SYM) and $(HEX)

Makefile: foo.s
    # build foo.XXXX.sym and foo.XXXX.hex from $<
    @touch $@