1
votes

Trying to write a simple makefile to compile Markdown files to HTML with Pandoc. I don't want to have to add all the prerequisite .md files explicitly to the makefile, so I've tried to use a pattern rule along with a wildcard prerequisite:

all: www/*.html

www/%.html: src/%.md
    pandoc -f markdown -t html $< > $@

This is close, but only processes prerequisite .md files for which an .html target file already exists and is out of date. New .md files which don't already have an .html file get ignored (so if all the non-new files are built, I get make: Nothing to be done for 'all'.)

What's the concept I'm missing? I'm not sure how to tell make to run on both the changed AND new .md files in src/ and apply the pattern rule to each.

2
My hunch is *.html is being treated as anything that currently matches the pattern, not as a wildcard. I'm not a Makefile expert by any stretch, but you'll probably want to look into variable substitution (something that's always eluded me). Try this to start: gnu.org/software/make/manual/html_node/Substitution-Refs.htmlStephen Newell
I think you're on the right track. If I clear out all the generated *.html files and run, it actually creates a file called www/*.html out of one of the prerequisites...definitely not treating the wildcard the way I expected.user574835783

2 Answers

4
votes

You could obtain a list of the .html files to be generated from the already existing .md files you have in the src/ directory.


First, the list of the existing .md files can be obtained with the wildcard built-in function:

md-files := $(wildcard src/*.md)

Then, apply a substitution reference to the md-files variable, so that the src/ prefix is removed and the suffix .md is replaced by .html for each element of the list of the .md files:

$(md-files:src/%.md=%.html)

Finally, by applying the addprefix built-in function to the resulting list, the prefix www/ can be added to each element of that list:

html-files := $(addprefix www/,$(md-files:src/%.md=%.html))

Putting everything together, the resulting makefile would be:

md-files := $(wildcard src/*.md)
html-files := $(addprefix www/,$(md-files:src/%.md=%.html))

.PHONY: all
all: $(html-files)

www/%.html: src/%.md
    pandoc -f markdown -t html $< > $@
1
votes

Try this:

$ cat Makefile
input := foo.md bar.md baz.md
output := $(input:%.md=www/%.html)

.PHONY: all

all: ${output}

www/%.html: src/%.md
        pandoc -f markdown -t html $< > $@

$ make -n
pandoc -f markdown -t html src/foo.md > www/foo.html
pandoc -f markdown -t html src/bar.md > www/bar.html
pandoc -f markdown -t html src/baz.md > www/baz.html