4

我必须将许多 HTML 文件的生成集成到现有的Makefile. 问题是 HTML 文件需要驻留在许多不同的目录中。我的想法是编写一个隐式规则,将源文件(*.st)转换为相应的html文件

%.html: %.st
    $(HPC) -o $@ $<

和一个依赖于所有 html 文件的规则

all: $(html)

如果 HTML 文件不在 builddir 中,则make找不到隐式规则:*** No rule to make target. 如果我像这样更改隐式规则

$(rootdir)/build/doc/2009/06/01/%.html: %.st  
    $(HPC) -o $@ $<

找到了,但是我必须对项目中的几乎每个文件都有一个隐式规则。根据GNU 手册中的隐式规则搜索算法make,规则搜索的工作方式如下:

  1. 将整个目标名称t拆分为目录部分,称为d,其余部分称为n。例如,如果tsrc/foo.o,则dsrc/,并且nfoo.o
  2. 列出所有目标匹配tn的模式规则。如果目标模式包含斜线,则与t匹配;否则,反对n

为什么没有找到隐含规则,假设make使用 GNU,什么是最优雅的解决方案?

这是我的精简版Makefile

rootdir  = /home/user/project/doc
HPC      = /usr/local/bin/hpc

html = $(rootdir)/build/doc/2009/06/01/some.html

%.html: %.st
    $(HPC) -o $@ $<

#This works, but requires a rule for every output dir
#$(rootdir)/build/doc/2009/06/01/%.html: %.st  
#   $(HPC) -o $@ $<

.PHONY: all
all: $(html)
4

4 回答 4

5

到目前为止,我发现的最佳解决方案是通过foreach-eval-call为每个目标目录生成一个隐式规则,如GNUmake手册中所述。我不知道这如何扩展到几千个目标目录,但我们会看到......

如果您有更好的解决方案,请发布!

这是代码:

rootdir  = /home/user/project/doc
HPC      = /usr/local/bin/hpc

html = $(rootdir)/build/doc/2009/06/01/some.html \
       $(rootdir)/build/doc/2009/06/02/some.html

targetdirs = $(rootdir)/build/doc/2009/06/01 \
             $(rootdir)/build/doc/2009/06/02

define generateHtml
 $(1)/%.html: %.st
    -mkdir -p $(1)
    $(HPC) -o $$@ $$<
endef   

$(foreach targetdir, $(targetdirs), $(eval $(call generateHtml, $(targetdir))))

.PHONY: all
all: $(html)
于 2009-06-01T12:25:17.630 回答
4

您的主动隐式规则$(rootdir)/build/doc/2009/06/01/some.html取决于$(rootdir)/build/doc/2009/06/01/some.st. 如果$(rootdir)/build/doc/2009/06/01/some.st不存在,则不会使用/找到该规则。

注释掉的规则使得$(rootdir)/build/doc/2009/06/01/some.html依赖于some.st.

一种解决方案是使您的源布局与您的目标/结果布局相匹配。

另一种选择是根据需要使用eval. 但这将非常复杂:

define HTML_template
 $(1) : $(basename $(1))
      cp $< $@
endef

$(foreach htmlfile,$(html),$(eval $(call HTML_template,$(htmlfile))))
于 2009-06-01T09:36:27.130 回答
4

像 Maria Shalnova 一样,我喜欢递归制作(尽管我不同意“递归制作被认为是有害的”),一般来说,从那里的源头制作一些东西会更好,而不是相反。但如果必须,我建议稍微改进一下:让 generateHtml 只生成 RULE,而不是 COMMANDS。

于 2009-06-19T00:39:00.177 回答
3

另一种可能性是让突击队make在每个输出目录中使用参数 -C 递归调用自身。递归make在某种程度上是处理子目录的标准方法,但要注意文章“递归使被认为是有害的”中提到的含义

于 2009-06-01T12:45:32.443 回答