2009-06-01 75 views
4

我必须在现有的Makefile中集成许多HTML文件的生成。 问题是HTML文件需要驻留在许多不同的目录中。 我的想法是写的源文件(* .ST)转换为相应的HTML文件GNU make有许多目标目录

%.html: %.st 
    $(HPC) -o [email protected] $< 

,并依赖于所有的HTML文件

all: $(html) 

如果HTML规则的隐含规则文件不在builddir中make未找到隐含规则:*** No rule to make target。 如果我改变,像这样

$(rootdir)/build/doc/2009/06/01/%.html: %.st 
    $(HPC) -o [email protected] $< 

它的发现隐含的规则,但我必须有一个隐含的规则在项目几乎每一个文件。 根据在GNU make手动Implicit Rule Search Algorithm,规则搜索的工作原理是这样的:

  1. t分裂成目录部分,称为d,其余的,所谓的ñ。例如,对于 示例,如果t是src/foo.o', then d is src /'且n是`foo.o'。
  2. 列出其中一个目标匹配t或n的所有模式规则。 如果目标模式包含一个 斜线,则它与t相匹配; 否则,针对n。

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

这里是我的Makefile一个精简版:

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

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

%.html: %.st 
    $(HPC) -o [email protected] $< 

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

.PHONY: all 
all: $(html) 

回答

4

像玛丽亚Shalnova我喜欢递归make(虽然我不同意“递归制作有害” ),一般情况下,最好从某个来源制造某种东西,而不是相反。但是,如果你必须,我建议稍微改进一下:有generateHtml只生成规则,而不是命令。

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 $< [email protected] 
endef 

$(foreach htmlfile,$(html),$(eval $(call HTML_template,$(htmlfile)))) 
+1

这可行,但不幸的是源布局是固定的,真正的Makefile使用VPATH。 – 2009-06-01 09:44:50

4

我迄今发现的最好的解决办法是通过foreach-eval-call生成每个目标目录中的隐含规则,如GNU make manual解释。我不知道这是如何扩展到几千个目标目录,但我们会看到...

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

下面是代码:

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 [email protected] $$< 
endef 

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

.PHONY: all 
all: $(html) 
+0

我看不到任何其他解决方案,而不是使用某种形式的call-foreach-eval。 GNU make不能很好地处理这种目录布局。 (实际上,原作或多或少地假设你将所有源代码放在一个目录中。) – JesperE 2009-06-01 12:33:01

3

的另一种可能是有突击队make与每一个输出目录参数-C递归调用本身。 递归make有点对付子目录,但文章中提到的含义提防的标准方法“递归制作有害”

+1

好的,递归make并没有出现在我的脑海中。您的解决方案将非常便于携带。 – 2009-06-01 13:03:02