26

Is it possible to create an executable script that would be interpreted by make?

I tried this:

#!/usr/bin/env make --makefile=/dev/stdin

main:
        @echo Hello!

but it does not work - hangs until press Ctrl-c.

Aleksandr Levchuk
  • 3,751
  • 4
  • 35
  • 47
  • Prefixing commands with `@` is possibly a bad practice. Exceptions for `echo` might be okay. It removes the ability of the user to chose whether or not to use `-s` to (not) echo commands as they are executed. Just saying in case beginners copy from this. – Christian Hujer Sep 11 '17 at 19:41
  • i do not think this is a good idea. and if you ever think about using a makefile for system administrator tasks please read this first: https://unix.stackexchange.com/a/497601/1170 – Lesmana Oct 16 '19 at 09:04

2 Answers2

30
#!/usr/bin/make -f

main:
        @echo Hello World!

Is normally all you need in a standard make file. The filename is implicitly passed as the last argument. /dev/stdin here is (usually) the tty. You can do the whole env thing if there's a reason to, but often there's no need.

ajw@rapunzel:~/code/videocc/tools > vi Makefile                       
ajw@rapunzel:~/code/videocc/tools > chmod a+x Makefile         
ajw@rapunzel:~/code/videocc/tools > ./Makefile                 
Hello World!
Samuel Rossille
  • 18,940
  • 18
  • 62
  • 90
Flexo
  • 87,323
  • 22
  • 191
  • 272
  • `#!/usr/bin/env make -f` gives "/usr/bin/env: make -f: No such file or directory" – Aleksandr Levchuk Aug 19 '11 at 14:56
  • 3
    You cannot rely on using options when you run /usr/bin/env for the #! interpreter. If you don't want to hard code the path (and you are not using OSX), then use `#! make -f` for the first line. – dadinck Aug 13 '12 at 16:18
  • 1
    Why include the `-f`? `#!/usr/bin/env make` seems to work equally well for me. – Taylor D. Edmiston Nov 30 '18 at 17:49
  • @Taylor I think that's a GNU make-ism and won't work on Solaris for example. Either that or your test simply isn't doing what you think. From my test though I can't even make that do what you seem to have tried with GNU make. – Flexo Nov 30 '18 at 18:00
  • @Flexo You're right. `$ make --version` shows GNU Make 4.2.1 and I'm on macOS. Here's the example Makefile I'm using - https://stackoverflow.com/a/53562601/149428. Edit: I should clarify I came here from querying "makefile shebang" in search of a canonical make shebang vs OP's need for an executable makefile. – Taylor D. Edmiston Nov 30 '18 at 18:30
  • 1
    Starting with coreutils 8.30, you can also use "#!/usr/bin/env -S make -f" as a shebang too. – Curious Sam Aug 27 '20 at 09:52
5

The following adds a level of indirection but it's the best solution I've come up with for self-executing makefiles not called "makefile":

#!/bin/sh
exec make -f- "$@" << 'eof'

.PHONY: all
all:
    @echo 'hello world!'

I'm trying to collect #! env hacks for each language / program here.

Stephen Niedzielski
  • 2,497
  • 1
  • 28
  • 34
  • Very interesting, however when I run `make` instead of `./Makefile`, `make` says : `Makefile:2: *** missing separator. Stop.` – SebMa Sep 12 '17 at 09:49
  • @SebMa, your use case is a makefile that supports default parameters AND is an executable with the same parameters. The question asks only for the latter. I've followed up in more detail on the ticket you've opened here: https://github.com/niedzielski/shebang/issues/1. – Stephen Niedzielski Sep 12 '17 at 21:58
  • I get a warning: `warning: here-document at line 2 delimited by end-of-file (wanted \`eof')` – CMCDragonkai Aug 22 '18 at 01:42
  • @CMCDragonkai, did you copy the shebang at the top? On my machine, bash prints this warning, sh does not. If you only have Bash available, you could try changing the `'eof'` to `'#eof'` and appending a `#eof` to the bottom. – Stephen Niedzielski Aug 22 '18 at 04:08
  • 1
    You need `eof` at the bottom. – CMCDragonkai Aug 22 '18 at 04:34