I was using Gnu Make
as a task runner. Specifically, I was trying to invoke my hand-rolled, go migrator to create a new migration file. This meant passing in a name for the db migration, and I was having a heck of a time passing this command-line arg past make, and through to my fledgling go program. I kept getting *** No rule to make target ...
errors: Make would encounter the first commandline token after the target, assume it was a target, try to build it, realise that it didn't know how to, then faceplant.
Yeah, I know I could've done name="add a column to foo table"
but I did not want to be bothered with typing name=
, each time, okay? Honestly I'm miffed I even have to type make <target> ...
. But we don't have telepathic interfaces to our machines, do we? So minimal commandlines are the next best thing .
.PHONY
targets? Duh!Yeah well they didn't work for my use case, so DOUBLE DUH?!! The arguments in this case aren't fixed / known ahead of time. Migration names can be almost anything (well, within reason). But point is, it's not a fixed token.
In the end after trawling through make
info online, and performing a small test locally, this is the combination of things that worked:
MAKECMDGOALS
var: it's basically the entire kitchen sink of arguments on the command line that make was invoked with.Given a test script foo.js
:
// a silly something that needs args passed down to it: just a stub mimicking my go program
const passedIn = process.argv.slice(3) // strip out nodejs invocation and make target name
console.log(`raw args of interest:[${passedIn}]`)
Turns out this is how you can slip past make:
# a match anything (else) rule, that does nothing, for those "*** No rule to make target ..." complaints.
# note: it will affect EVERY rule, so now you will be relying on each rule to fail in some other way when
# its dependencies aren't there / valid.
%:
@:
# ---- Failures that are still caught. Thank God! -----
# will fail because command not found
cats:
gecho "this is a cat\n"
# will fail because cats fails
bar: cats
echo "hello world"
# ---- But we can still suppress the "no rule to make target" complaint! -----
# This will pass because ALL the cmd line args, though parsed as targets by make, will fall into the "match anything else" trap.
foo:
node ./foo.js $(MAKECMDGOALS)
So now I can type:
> make foo bob has all the burgers
...and the target app can pick up ["bob", "has", "all", "the", "burgers"]
, which is exactly what I want.
In other words, I can now do things like make create new index for the blah table
and my migrator has a chance in hell of creating a migration file with a nice kebab-cased name and a unique identifier. Sweet!