0

I have the following Makefile, but it does not work. When I call

make html

I get a

make: *** No rule to make target `docs/index.html', needed by `html'.  Stop.

error, even though I think I have defined it.

SRCDIR = source
OUTDIR = docs

RMD = $(wildcard $(SRCDIR)/*.Rmd)

TMP  = $(RMD:.Rmd=.html)
HTML = ${subst $(SRCDIR),$(OUTDIR),$(TMP)}


test:
    echo $(RMD)
    echo $(TMP)
    echo $(HTML)


all: clean update html

html:   $(HTML)

%.html: %.Rmd
    echo $(HTML)
    @Rscript -e "rmarkdown::render('$<', output_format = 'prettydoc::html_pretty', output_dir = './$(OUTDIR)/')"

update:
    @Rscript -e "devtools::load_all(here::here()); microcosmScheme:::updateFromGoogleSheet(token = './source/googlesheets_token.rds')"


## from https://stackoverflow.com/a/26339924/632423
list:
    @$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | xargs

.PHONY: update clean cleanhtml all list

The variables seem to be correct:

15:21 $ make test
echo source/index.Rmd
source/index.Rmd
echo source/index.html
source/index.html
echo docs/index.html
docs/index.html

If I change it as follow it works, but the target points to the SRCDIR, but I want it to point to the OUTDIR:

RMD = $(wildcard $(SRCDIR)/*.Rmd)

HTML  = $(RMD:.Rmd=.html)
# HTML = ${subst $(SRCDIR),$(OUTDIR),$(TMP)}

I am sure it is one small thing...

Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182
Rainer
  • 8,347
  • 1
  • 23
  • 28

1 Answers1

2

This rule:

%.html : %.Rmd
        ....

tells make how to build a file foo.html from a file foo.Rmd, or a file source/foo.html from a file source/foo.Rmd, or a file docs/foo.html from a file docs/foo.Rmd.

It doesn't tell make how to build a file docs/foo.html from a file source/foo.Rmd, because the stem that matches the pattern % is not the same.

If you want to write a pattern for docs/foo.html to be built from source/foo.Rmd, you have to write it like this:

$(OUTDIR)/%.html : $(SRCDIR)/%.Rmd
      ....

so that the part that matches the pattern % is identical.

ETA Some other notes: you should be using := with the wildcard function as it's much better performing. Also you shouldn't use subst here because it replaces all occurrences of the string which could break things if any of your .Rmd files contain the string source for example (e.g., source/my_source_file.Rmd. This is much better written with patsubst, as in:

RMD := $(wildcard $(SRCDIR)/*.Rmd)
HTML := $(patsubst $(SRCDIR)/%.Rmd,$(OBJDIR)/%.html,$(RMD))

Finally, you don't show what the clean target does but it's unusual to have the clean target depended on by all. Usually it's a separate target that is invoked only when you want it, like make clean.

MadScientist
  • 92,819
  • 9
  • 109
  • 136
  • Makes sense. But I now changed the Makefile as suggested, but I still get the same error. I posted it as a gist at https://gist.github.com/rkrug/f060bab62b3b0c1b20a7360e86cd0652 – Rainer Nov 22 '18 at 09:09
  • It's because I incorrectly used the variable `SOURCE` in my example pattern rule when the variable you used was `SRCDIR`, and you blindly copied my mistake :). Unknown variables expand to the empty string so your pattern rule was `docs/%.html : /%.Rmd` which of course won't work. – MadScientist Nov 22 '18 at 14:47
  • Thanks. Workshop perfectly now. – Rainer Nov 23 '18 at 15:56