Makefile GNU make具有许多目标目录

Makefile GNU make具有许多目标目录,makefile,release-management,gnu-make,build-management,Makefile,Release Management,Gnu Make,Build Management,我必须将许多HTML文件的生成集成到现有的Makefile中。 问题是HTML文件需要驻留在许多不同的目录中。 我的想法是编写一个隐式规则,将源文件(*.st)转换为相应的html文件 %.html: %.st $(HPC) -o $@ $< 如果HTML文件不在builddir中,make找不到隐式规则:***无规则生成目标。 如果我像这样更改隐式规则 $(rootdir)/build/doc/2009/06/01/%.html: %.st $(HPC) -o $@

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

%.html: %.st
    $(HPC) -o $@ $<
如果HTML文件不在builddir中,make找不到隐式规则:
***无规则生成目标
。 如果我像这样更改隐式规则

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

您的活动隐式规则使
$(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

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

另一个选项是根据需要使用创建规则。但这将相当复杂:

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

$(foreach htmlfile,$(html),$(eval $(call HTML_template,$(htmlfile))))
定义HTML\u模板
$(1):$(基本名称$(1))
cp$<$@
恩德夫
$(foreach htmlfile,$(html),$(eval$(调用html_模板,$(htmlfile)))

到目前为止,我找到的最佳解决方案是通过为每个目标目录生成隐式规则,如中所述。我不知道如何扩展到几千个目标目录,但我们会看到

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

代码如下:

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)
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
定义generateHtml
$(1)/%.html:%.st
-mkdir-p$(1)
$(HPC)-o$$@$$<
恩德夫
$(foreach targetdir,$(targetdirs),$(eval$(call generateHtml,$(targetdir)))
冒牌货:全部
全部:$(html)

另一种可能性是让突击队
对每个输出目录使用参数-C递归调用自己。

Recursive
make
在某种程度上是处理子目录的标准方法,但要注意“Recursive make被认为有害”一文中提到的含义

像Maria Shalnova一样,我喜欢Recursive make(尽管我不同意“Recursive make被认为有害”),总的来说,最好在这里从那里的来源制造一些东西,而不是相反。但如果您必须这样做,我建议您做一点小小的改进:让generateHtml只生成规则,而不是命令。

这样可以,但不幸的是,源布局是固定的,真正的Makefile使用VPATH。除了使用某种形式的调用foreach eval,我看不到任何其他解决方案。GNUMake不能很好地处理这种目录布局。(事实上,最初的make或多或少假设您的所有源代码都在一个目录中。)好的,我没有想到递归make。您的解决方案将非常方便。
define HTML_template
 $(1) : $(basename $(1))
      cp $< $@
endef

$(foreach htmlfile,$(html),$(eval $(call HTML_template,$(htmlfile))))
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)