Hacker News new | ask | show | jobs
by epistasis 2225 days ago
For complicated pipelines that I want to reuse multiple times, I have turned Makefiles into executables by putting this at the top:

    #!/usr/bin/make -f
And then putting them in my $PATH. I run them with arguments like:

    $ process-data.mk INTSV=a.tsv DB=largefile.gz OUTDIR=finished
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...
3 comments

-f is guaranteed by POSIX, and #! is de facto portable.[1] My criteria for shame is, "will this silently break in the future?". I think you're good. It's not my style, but if it were something I came across at work, so long as it worked well it wouldn't even cross my mind to try to "fix" it.

FWIW, using make -f in the shebang is also done for debian/rules in Debian package builds. I don't know if it serves any real purpose. I suppose it permits one to write a bespoke script for building targets without using make.[2] I guess I wouldn't be surprised if someone, somewhere depended on that capability, given how old and widespread Debian packages are.

[1] /usr/bin/env make -f would be better, but then you run afoul of the problem that you can't portably pass more than a single explicit shebang command argument.

[2] Which I see now is a bonus to your process-data.mk script. It could be replaced with a non-make version without effecting callers.

I can see two areas in which it might break.

I might put #!/usr/bin/env make -f in case it's somewhere in else in PATH.

Also some systems (BSD, old commercial Unix) have non-gnu-compatible make and sometimes call their gnu make port "gmake" or "gnumake".

AFAIR on Linux shebangs only support single argument so it would fail in this case. One can overcome this treating the file as a shell script:

  #!/bin/sh
  # make ignores next line \
  set -e
  # make ignores next line \
  exec make -f "$0" "$@"
Make treats slash-escaped new lines as a continuation even for comments, shell does not.
Wow. Impressive.
That shebang is appealing but unfortunately more than one argument (past the initial command name) in a shebang is unportable: some OSes will coalesce the extra arguments into one, others make them separate arguments.

There's also a special bonus papercut you might hit when /usr/bin/env is in the shebang with extra arguments: an infinite loop!

Sorry for the plug: I wrote about it here. https://www.crystae.net/posts/2019/11/08/two-shebang-papercu...

GNU coreutils env supports a flag for it since 8.30 which translates to Debian 10 & Ubuntu 19.04. Not a perfect solution, but it appears to allow portability across the vast majority of modern OSes?
In your scenario, "make processed_data" makes more sense semantically than rules commonly seem in the wild like "make run" or "make deploy"