That's interesting.<p>Author probably wants to use `private` for those target-local variables, though.<p>For example,<p><pre><code> R: .SHELLFLAGS := -e
R: SHELL := Rscript
R:
greeting = "bonjour"
message(paste0(greeting, ", R!"))
</code></pre>
Everything that target `R` depends on will also have SHELL and .SHELLFLAGS over-ridden. If `R` depends on some data generated by another program, it probably wants to be built and executed with the default SHELL (or another shell, perhaps).<p><pre><code> R: private .SHELLFLAGS := -e
R: private SHELL := Rscript
R:
greeting = "bonjour"
message(paste0(greeting, ", R!"))
</code></pre>
Now, `R`'s dependencies will be generated with the makefile's defaults.<p>Usually I prefer to build up richer stages like this using the system shell anyway, though. Build a target which in turn is executed by the shell normally to traverse the next edge in the graph. But I can see how this mechanism has its uses.<p>See also <a href="https://www.gnu.org/software/make/manual/html_node/Target_002dspecific.html" rel="nofollow">https://www.gnu.org/software/make/manual/html_node/Target_00...</a>
Make was designed for building dependencies. I think it is always problematic to use it as a command runner (for example there is no standard way to list out the available commands).<p>[just](<a href="https://github.com/casey/just" rel="nofollow">https://github.com/casey/just</a>) is a tool that feels similar to make but is designed explicitly for the purpose of running commands.<p>I think of this as a simple CLI for your project workflow. You still really want to avoid putting code into a Justfile and put it into scripts. But the Justfile helps provide a slightly nicer UX and automatically invoke dependencies.
For complicated pipelines that I want to reuse multiple times, I have turned Makefiles into executables by putting this at the top:<p><pre><code> #!/usr/bin/make -f
</code></pre>
And then putting them in my $PATH. I run them with arguments like:<p><pre><code> $ process-data.mk INTSV=a.tsv DB=largefile.gz OUTDIR=finished
</code></pre>
This makes me feel like I've sold my soul to the devil, and that I'm just living on borrowed time until it all fails and falls apart. It hasn't yet, however...
Note that this article (like many, many others) assumes GNU Make. POSIX
Make has neither .ONESHELL nor local macros. Neither do most built-in
Make implementations in other OSes, like OpenBSD's bmake.
I wish someone would write a modern alternative to GNU Make. I've looked and there don't seem to be any. The closest is Ninja but it doesn't seem to be intended to be hand written.
I added this to my list about Make at <a href="https://github.com/adelarsq/awesome-make" rel="nofollow">https://github.com/adelarsq/awesome-make</a><p>Pull requests are welcome.