Почему в моем makefile нет правила, делающего цель необходимой другой цели?

Почему в моем makefile нет правила, делающего цель необходимой другой цели?

При запуске makefile внизу я получаю ошибку:

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

Я не понимаю эту ошибку, потому что есть правило с целью xhtml/%.html. Почему это правило не учитывается?

Я запускаю это в папке, содержащей файл 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

решение1

Когда вы определяете цель, xhtml/%.htmlвы создаете рецепт не для одного файла, а длявсе файлы, соответствующие этому шаблону, т. е. все файлы xhtml/с .htmlсуффиксом, например xhtml/foobar.html.

Например, когда мы ставим следующие цели:

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>' >$@

теперь мы можем запустить make xhtml/foobar.htmlи сделать определите, что xhtml/foobar.htmlзависит от xml/foobar.xmlи поэтому сначала попробуем создать xml/foobar.xmlто, для чего у нас есть рецепт под рукой.

Можно %прочитать как «разрешить произвольный текст» и makeзапомнить этот произвольный текст для дальнейшего использования. Поэтому, когда мы запускаем make xhtml/foobar.html, makeраспознает foobarкак «произвольный текст», запоминает foobarи оценивает цель, как если бы мы написали xhtml/foobar.html: xml/foobar.xml.

Когда вы ставите xhtml/%.htmlкак зависимость, вы ссылаетесь на произвольную часть цели. Аналогично, make xhtml/hello.htmlне получится, потому что makeне будет возможности найти правило, чтобы сделать xml/hello.xml.

В вашем Makefile, когда makeон достигает рецепта, manifold/${MANUSCRIPTNAME}.zip: xhtml/%.htmlон не может найти произвольную часть в цели, потому что это статическое имя файла. В результате ему нечем заменить, %и я думаю, что это просто считается ошибкой.

Я не знаю, что вы хотите заменить %(и поэтому не делает), но я думаю, что вы можете улучшить свой код с помощью этого:

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

Обратите внимание, что теперь в этой строке их два :. Новый средний компонент сообщает, makeкак считывать разумное значение %из вашего имени файла.

В качестве альтернативы вы можете указать:

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

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

Или даже:

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

Но я думаю, что последний доступен только GNU Make.

PS: Я думаю, что это очень странно, что, makeкажется, (можно) разыменовывать ${}. Обычно я ожидаю, что мы используем $()-конструкции.

Связанный контент