Makefile recipe with a here-document redirection

Using the line .ONESHELL: somewhere in your Makefile will send all recipe lines to a single shell invocation, you should find your original Makefile works as expected.


When make sees a multi-line block in a recipe (i.e., a block of lines all ending in \, apart from the last), it passes that block un-modifed to the shell. This generally works in bash, apart from here docs.

One way around this is to strip any trailing \s, then pass the resulting string to bash's eval. You do this in make by playing with ${.SHELLFLAGS} and ${SHELL}. You can use both of these in target-specific form if you only want it to kick in for a few targets.

.PHONY: heredoc

heredoc: .SHELLFLAGS = -c eval
heredoc: SHELL = bash -c 'eval "$${@//\\\\/}"'

heredoc:
    @echo First
    @cat <<-there \
        here line1 \
        here anotherline \
    there
    @echo Last

giving

$ make
First
here line1
here anotherline
Last

Careful with that quoting, Eugene. Note the cheat here: I am removing all backslashes, not just the ones at the ends of the line. YMMV.