2

When I run the makefile at the bottom, I receive the error:

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

I do not understand this error, because there is a rule with target xhtml/%.html. Why does this rule not count?

I run this in a folder that contains the file 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
6
  • In manifold/${MANUSCRIPTNAME}.zip: xhtml/%.html, there's no % in the target manifold/${MANUSCRIPTNAME}.zip, so what is the % in the prerequisite supposed to match?
    – muru
    Jun 6, 2019 at 10:49
  • does that mean, I can only use make wildcards when it may appear on both sides (target and dependency)? But what would I do then, when a clearly named target depends on an undefined number of dependencies? Jun 6, 2019 at 10:50
  • 1
    Yes. From gnu.org/software/make/manual/make.html#Static-Pattern : "Each target is matched against the target-pattern to extract a part of the target name, called the stem. This stem is substituted into each of the prereq-patterns to make the prerequisite names (one from each prereq-pattern). [...] When the target-pattern matches a target, the ‘%’ can match any part of the target name; this part is called the stem."
    – muru
    Jun 6, 2019 at 10:53
  • You can use wildcards: gnu.org/software/make/manual/make.html#Wildcards
    – muru
    Jun 6, 2019 at 10:54
  • % in not a glob, it is a pattern matching character. You used it in place of a glob (manifold/${MANUSCRIPTNAME}.zip: xhtml/%.html). It was interpreted as a literal character. Jun 6, 2019 at 12:09

1 Answer 1

3

When you define the goal xhtml/%.html you are not creating a recipe for a single file, but a recipe for all files that match this pattern, i.e. all files in xhtml/ with a .html suffix, for instance xhtml/foobar.html.

For instance when we put the following goals:

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

we may now run make xhtml/foobar.html and make will determine that xhtml/foobar.html depends on xml/foobar.xml and will therefore first look to create xml/foobar.xml for which we have a recipe at hand.

The % can be read as "allow arbitrary text" and make remembers this arbitrary text for further use. So when we run make xhtml/foobar.html, make recognises foobar as "arbitrary text", remembers foobar and evaluates the goal as if we had written xhtml/foobar.html: xml/foobar.xml.

When you put xhtml/%.html as a dependency, you are refering to the arbitrary part of the goal. Similarly, make xhtml/hello.html will fail, because make will not be able to find a rule to make xml/hello.xml.

In your Makefile, when make reaches the recipe manifold/${MANUSCRIPTNAME}.zip: xhtml/%.html it cannot find an arbitrary part in the goal, because it is a static file name. As a result it has nothing to replace the % with and I think that is just considered an error.

I do not know what you want to replace the % (and so doesn't make), but I think you can improve your code with this:

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

Notice that there are now two : in this line. The new middle component tells make how to read a sensible value for % from your filename.

Alternatively you can put:

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

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

Or even:

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

But I think the last is GNU Make only.

P.S.: I think its very strange that make seems to (be able to) dereference ${}. Usually I would expect we use $()-constructs.

3
  • Both $(foo) and ${foo} are valid ways to reference variables in a Makefile, nothing strange about that: gnu.org/software/make/manual/html_node/Reference.html#Reference . Oh and this is not a GNU Make specific feature, all make's (AFAICT) behave the same way. For variable names which consist of a single character, the syntax $x is also valid.
    – filbranden
    Jun 6, 2019 at 11:53
  • I find the solution involving a default rule (default: manifold/$(MANUSCRIPTNAME).zip as the first rule in your Makefile) much better than the one setting up a static pattern for that specific name only (the one you listed first), so I'd suggest listing that one first in your answer and the other one ($(MANUSCRIPTNAME).zip: %.zip: %.html, with paths) as an alternative approach to also be considered. By convention, the default rule is usually called all, so that a command such as make all will execute the same (building all default targets), so I'd use that name instead.
    – filbranden
    Jun 6, 2019 at 11:58
  • .DEFAULT_GOAL is an esoteric back door which should probably be avoided, the manual's example of it reinforces that impression: gnu.org/software/make/manual/html_node/Special-Variables.html . Just instruct on using a default target by placing it first in the Makefile, that's the correct way to do that. (BTW, I think that variable is not GNU make specific, but that point is somewhat moot if you end up removimg that part from the answer.)
    – filbranden
    Jun 6, 2019 at 12:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .