Por que não existe uma regra para tornar o alvo necessário para outro alvo no meu makefile?

Por que não existe uma regra para tornar o alvo necessário para outro alvo no meu makefile?

Quando executo o makefile na parte inferior, recebo o erro:

make: *** No rule to make target 'xhtml/%.html', needed by 'manifold/01_doehmer_syntax_pre.zip'.  Stop.

Não entendo esse erro, pois existe uma regra com target xhtml/%.html. Por que esta regra não conta?

Eu executo isso em uma pasta que contém o arquivo 01_doehmer_aspekte.docx.

BINDIR:=~/TEIC-XSLT/bin
PROFDIR:=/mnt/c/Users/niels-oliver.walkows/OneDrive/Dokumente/Luxemburg/Melusinapress/Transformationen/xslt/TEIC/profiles
MANUSCRIPTFILE:=$(shell ls *.docx)
MANUSCRIPTNAME:=$(shell basename ${MANUSCRIPTFILE} .docx)

.PHONY : all clean

all: manifold/${MANUSCRIPTNAME}.zip

tei/%.xml: %.docx
    mkdir -p tei
    ${BINDIR}/docxtotei --profiledir=${PROFDIR} --profile=melusina $< $@

xhtml/%.html: tei/%.xml
    mkdir -p xhtml
    ${BINDIR}/teitohtml --profiledir=${PROFDIR} --profile=melusina $< $@
    cp -r tei/media xhtml/

manifold/${MANUSCRIPTNAME}.zip: xhtml/%.html
    mkdir -p manifold
    touch manifold/manifest.yml
    cp -r tei/media manifold/
    cp -r xhtml/*.html manifold/
    cd manifold && zip -r ${MANUSCRIPTNAME}.zip manifest.yml media *.html
    rm -rf manifold/media manifold/${MANUSCRIPTNAME}.html

test:
    echo "${MANUSCRIPTFILE}"
    echo "${MANUSCRIPTNAME}"

clean:
    rm -rf tei xhtml manifold

Responder1

Ao definir o objetivo xhtml/%.htmlvocê não está criando uma receita para um único arquivo, mas uma receita paratodos os arquivos que correspondem a este padrão, ou seja, todos os arquivos xhtml/com um .htmlsufixo, por exemplo xhtml/foobar.html.

Por exemplo, quando colocamos os seguintes objetivos:

xhtml/%.html: xml/%.xml
    xsltproc magic.xsl $< > $@

xml/foobar.xml:
    echo '<?xml version="1.0"?><a><b><c some="attr">Lorep Ipsum</c><c some="other">Dorlor si amet</c></b></a></xml>' >$@

podemos agora executar make xhtml/foobar.htmle fazer determinar o que xhtml/foobar.htmldepende xml/foobar.xmle, portanto, primeiro procuraremos criar xml/foobar.xmlpara o qual temos uma receita em mãos.

O %pode ser lido como "permitir texto arbitrário" e makelembra esse texto arbitrário para uso posterior. Então quando corremos make xhtml/foobar.html, makereconhecemos foobarcomo “texto arbitrário”, lembramos foobare avaliamos o objetivo como se tivéssemos escrito xhtml/foobar.html: xml/foobar.xml.

Quando você coloca xhtml/%.htmlcomo dependência, você está se referindo à parte arbitrária do objetivo. Da mesma forma, make xhtml/hello.htmlirá falhar, porque makenão será capaz de encontrar uma regra para fazer xml/hello.xml.

No seu Makefile, ao makechegar na receita manifold/${MANUSCRIPTNAME}.zip: xhtml/%.htmlele não consegue encontrar uma parte arbitrária no objetivo, pois é um nome de arquivo estático. Como resultado, não há nada para substituir %e acho que isso é considerado apenas um erro.

Não sei o que você quer substituir %(e por isso não faz), mas acho que você pode melhorar seu código com isso:

manifold/$(MANUSCRIPTNAME).zip: manifold/%.zip: xhtml/%.html

Observe que agora existem dois :nesta linha. O novo componente intermediário informa makecomo ler um valor sensato %do seu nome de arquivo.

Alternativamente você pode colocar:

# as your first recipe
default: manifold/$(MANUSCRIPTNAME).zip

# and then
manifold/%.zip: xhtml/%.html
    [...your recipe...]

Ou ainda:

.DEFAULT_GOAL: manifold/$(MANUSCRIPTNAME).zip
manifold/%.zip: xhtml/%.html
    [...your recipe...]

Mas acho que o último é apenas GNU Make.

PS: Acho muito estranho que makepareça (conseguir) desreferenciar ${}. Normalmente eu esperaria que usássemos $()-constructs.

informação relacionada