15

I'm learning how to use make and makefiles, so I wrote this little file:

%.markdown: %.html
    pandoc -o $< $@

But when I run make, all I get is make: *** No targets. Stop. What's going on?

3
  • Are those spaces or a tab in front of the pandoc command. Make is notoriously picky about those being a tab and not spaces.
    – slm
    Jul 5, 2014 at 17:20
  • @slm: it's a tab. I read somewhere that Windows' EOL are not compatible, so I converted to whole file to Unix compatible EOL.
    – ahmed
    Jul 5, 2014 at 20:11
  • I guess u can use .SUFFIXES: .markdown .html
    – zerocool
    Nov 3, 2020 at 7:16

2 Answers 2

21

Problem:

You problem is that make doesn't know about your targets.

You can run your above Makefile with make stackoverflow.markdown for example and it will work.

make only, however, will fail, since you only specified how to create your targets, but not which.

As leiaz point's out the above pattern rule is called an implicit rule.

Makefile:

SRC = $(wildcard *.html)
TAR = $(SRC:.html=.markdown)

.PHONY: all clean

all: $(TAR)

%.markdown: %.html
    pandoc -o $< $@

clean:
    rm -f $(TAR)

Explanation:

SRC get's all source files (those ending in .html) via Makefile's wildcard.

TAR substitutes each source file listed in SRC with a target ending with .markdown instead of .html.

.PHONY lists non-physical targets that are always out-of-date and are therefore always executed - these are often all and clean.

The target all has as dependency (files listed on the right side of the :) all *.markdown files. This means all these targets are executed.

%.markdown: %.html
    pandoc -o $< $@

This snippet says: Each target ending with .markdown is depended on a file with the same name, except that the dependency is ending with .html. The wildcard % is to be seen as a * like in shell. The % on the right side, however, is compared to the match on the left side. Source.

Note that the whitespace sequence infront of pandoc is a TAB, since make defines that as a standard.

Finally, the phony clean target depicts how to clean your system from the files you've created with this Makefile. In this case, it's deleting all targets (those files that were named *.markdown.

6
  • 2
    Great answer and these are other links I found when trying to further understanding it : wildcard function, substitution references, and phony targets.
    – ahmed
    Jul 5, 2014 at 23:32
  • One more question please : can makefile create files from scratch or it only updates existing files? Because when I delete the generated files, it stops to work. Silly question I know, but this is Newfoundland to me ^^"
    – ahmed
    Jul 5, 2014 at 23:35
  • 1
    you mean if there are no .markdown files, then they will be created? yeah it should do that as far as I know
    – polym
    Jul 5, 2014 at 23:37
  • 1
    Alright then. I'll do some more digging. Thanks for your answers, thanks to you I'm on the right way now : )
    – ahmed
    Jul 5, 2014 at 23:40
  • 1
    Just wanted to thank you for the great answer. The way you have explained is very easy to understand the reason behind the command wasn't working and a very detailed instructions on how to proceed. Thanks again.
    – zanona
    Aug 26, 2016 at 15:45
5

Pattern rules are implicit rules.

You have no targets defined in your Makefile. You can specify the target on the command line : make something.markdown will use the recipe to create something.markdown from something.html.

Or you can add to your Makefile a rule specifying default targets.

all: file1.markdown file2.markdown

Or with a wildcard :

all: *.markdown

When you run just make, the first target of the first rule is the default goal. It doesn't need to be called all.

So above, the target all have all the files you want to make as prerequisites, so when you make all, it will make all the listed files.

0

You must log in to answer this question.

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