¿Por qué no hay ninguna regla para hacer que otro objetivo necesite un objetivo en mi archivo MAKE?

¿Por qué no hay ninguna regla para hacer que otro objetivo necesite un objetivo en mi archivo MAKE?

Cuando ejecuto el archivo MAKE en la parte inferior, recibo el error:

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

No entiendo este error porque hay una regla con target xhtml/%.html. ¿Por qué esta regla no cuenta?

Ejecuto esto en una carpeta que contiene el archivo 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

Respuesta1

Cuando defines el objetivo xhtml/%.htmlno estás creando una receta para un solo archivo, sino una receta paratodos los archivos que coinciden con este patrón, es decir, todos los archivos xhtml/con un .htmlsufijo, por ejemplo xhtml/foobar.html.

Por ejemplo cuando nos fijamos los siguientes 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>' >$@

Ahora podemos ejecutar make xhtml/foobar.htmly determinar de qué xhtml/foobar.htmldepende xml/foobar.xmly, por lo tanto, primero buscaremos crear xml/foobar.xmlpara lo cual tenemos una receta a mano.

Puede %leerse como "permitir texto arbitrario" y makerecuerda este texto arbitrario para su uso posterior. Así, cuando lo ejecutamos make xhtml/foobar.html, makelo reconoce foobarcomo "texto arbitrario", recuerda foobary evalúa el objetivo como si lo hubiéramos escrito xhtml/foobar.html: xml/foobar.xml.

Cuando pones xhtml/%.htmlcomo dependencia te estás refiriendo a la parte arbitraria del objetivo. Del mismo modo, make xhtml/hello.htmlfracasará, porque makeno podrá encontrar una regla que hacer xml/hello.xml.

En su Makefile, cuando makellega a la receta manifold/${MANUSCRIPTNAME}.zip: xhtml/%.htmlno puede encontrar una parte arbitraria en el objetivo, porque es un nombre de archivo estático. Como resultado, no tiene nada con qué reemplazarlo %y creo que eso simplemente se considera un error.

No sé qué quieres reemplazar %(y por eso no lo hace), pero creo que puedes mejorar tu código con esto:

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

Observe que ahora hay dos :en esta línea. El nuevo componente central indica makecómo leer un valor razonable %de su nombre de archivo.

Alternativamente puedes poner:

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

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

O incluso:

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

Pero creo que el último es solo GNU Make.

PD: Creo que es muy extraño que makeparezca (poder) desreferenciar ${}. Por lo general, esperaría que usáramos $()-constructs.

información relacionada