0

I am working on a writing project and would like to use make for running pandoc on files. So far I've tried to pass arguments to make like I do with a bash script.

For example:

$ make chapter 2

In the make file chapter is the target and 2 would be the argument.

I don't know if makefiles have the facility to take cli arguments. I haven't been able to find what I'm looking for in the documentation.

So far I have tried to run make with this recipe.

chapter:
    @pandoc -s -o "$1.epub" "$1.md"

I get this error back

pandoc: .md: openBinaryFile: does not exist (No such file or directory)
make: *** [Makefile:2: chapter] Error 1

This is for turning sections of a book I'm working on into epubs. I'm open to other ways to do this with make seeing as tokens don't to work.

Jens
  • 69,818
  • 15
  • 125
  • 179
9716278
  • 2,044
  • 2
  • 14
  • 30
  • Possible duplicate of [Passing arguments to "make run"](https://stackoverflow.com/questions/2214575/passing-arguments-to-make-run) – tripleee Sep 20 '19 at 19:13

2 Answers2

0

The natural way to say this in Make is to enumerate all the chapters as targets, typically as dependencies for make all.

So basically

src := $(wildcard *.md)
epubs := $(patsubst %.md,%.epub,$(src))

.PHONY: all
all: $(epubs)

%.epub: %.md
    pandoc -s -o $@ $<

You can say make ch4.epub if you have a chapter whose source is ch4.md. You can't really pass in an argument which isn't a file name or a target name, and these cannot contain spaces.

I suppose you could add a phony like

.PHONY: 2
2: ch2.epub

to be able to say make 2 and have it mean make ch2.epub. If file names are systematically named like this, you could generalize to

short := $(patsubst ch%.md,%,$(src))
.PHONY: $(short)
$(short): %: ch%.epub

Don't use @ in front, it just makes things harder. You can use make -s if you don't want to see the output and not wreck your Makefile.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • I like your solution. When I tried `$ make forward.epub`, I got back `Makefile:7: *** mixed implicit and static pattern rules. Stop.` Could this be a problem with the directory lay out? – 9716278 Sep 20 '19 at 21:50
  • Sorry, I had a colon too much in the dependency declaration; fixed now. – tripleee Sep 21 '19 at 08:26
0

In the make file chapter is the target and 2 would be the argument

$ make chapter num=2

The assignment to variables on the make command-line overrides any definition inside the makefile (yep, such variables effectively become read-only). This suggests a makefile something like:

num = $(error You must set $$num to the chapter number you want (make chapter num=4))

.PHONY: chapter
chapter:
    pandoc -s -o "${num}.epub" "${num}.md"

What's going on here? Well, if you forget to set num, when make expands the recipe for chapter the $(error) will cause make to stop.

$ make
Makefile:5: *** You must set $num to the chapter number you want (make chapter num=4).  Stop.

And your original example?

$ make chapter num=2
pandoc -s -o "2.epub" "2.md"

Tips

  • I rarely recommend using the @ prefix — Users can use make's -s if they don't want to see the shell commands
  • Don't lie to make — In particular, your rule does not produce a file called chapter, so please tell make that by marking the target .PHONY
bobbogo
  • 14,989
  • 3
  • 48
  • 57
  • Thanks, this was just what I was looking for. I'm new to Makefiles. I was wondering if you knew of a way to include `-s` in the Makefile, seeing as using `@` prefix is not good? – 9716278 Sep 25 '19 at 16:48
  • `@` is fine, but how do you remove them all if you actually want to see the commands? (for debugging say). I suppose you could do a `q := @` at the top, and then start every recipe line with `$q` (`$qecho hello` for instance) — single character macros don't need to be surrounded in `{` and `}`. [Forcing `-s` is rather like forcing `-j5`. Really it should up to the user IMHO.] – bobbogo Sep 26 '19 at 17:14