Pergunta

Eu tenho a integrar a geração de muitos arquivos HTML em uma Makefile existente. O problema é que os arquivos HTML precisam residir em muitos diretórios diferentes. Minha idéia é escrever uma regra implícita que converte o arquivo fonte (* .st) para o arquivo html correspondente

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

e uma regra que depende de todos os arquivos html

all: $(html)

Se o arquivo HTML não está no make builddir não encontra a regra implícita: *** No rule to make target. Se eu alterar a regra implícita como assim

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

é encontrado, mas então eu tenho que ter uma regra implícita para quase todos os arquivos no projeto. De acordo com a implícita Regra Pesquisa Algoritmo na GNU make Manual, pesquisa regra funciona assim:

  1. Split t em uma parte do diretório, chamado d, eo resto, chamado n. Para exemplo, se T é src/foo.o', then d issrc / 'e n é `foo.o'.
  2. Faça uma lista de tudo o padrão governa um de cujos alvos corresponde t ou n. Se o padrão de destino contém uma slash, que é comparado com t; caso contrário, contra o n.

Porque é que a regra implícita não encontrado, e qual seria a solução mais elegante, assumindo GNU make é usado?

Aqui está uma versão simplificada da minha 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)
Foi útil?

Solução

Como Maria Shalnova I como fazer recursiva (embora eu não concordar com "Make recursiva considerada prejudicial") e, em geral, é melhor fazer alguma coisa aqui de uma fonte LÁ, não o inverso. Mas se você deve, eu sugiro uma ligeira melhoria:. Tem generateHtml gerar apenas a regra, não os comandos

Outras dicas

A melhor solução que eu encontrei até agora é para gerar uma regra implícita per diretório de destino através de foreach-eval-call , como explicado na GNU make manual do . Eu não tenho nenhuma idéia de como isso escalas a alguns milhares de diretórios de destino, mas vamos ver ...

Se você tiver uma solução melhor, por favor, postá-lo!

Aqui está o código:

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)

A sua regra implícita ativo faz $(rootdir)/build/doc/2009/06/01/some.html dependem $(rootdir)/build/doc/2009/06/01/some.st. Se $(rootdir)/build/doc/2009/06/01/some.st não existe, então a regra não será usado / encontrado.

A regra comentada faz $(rootdir)/build/doc/2009/06/01/some.html dependem some.st.

Uma solução é fazer com que você está fonte layout corresponde à sua disposição destino / resultado.

Outra opção é criar as regras, conforme necessário com eval . Mas isso vai ser bastante complicado:

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

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

Uma outra possibilidade é ter a própria chamada make comando recursivamente com o -C discussão com cada diretório de saída. make recursiva é um pouco a maneira padrão de lidar com subdiretórios, mas cuidado com as implicações mencionadas no artigo "recursiva Marca considerada prejudicial"

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top