4 ms·
This article has some questionable advice imo. SHELL := bash Bash is a much slower shell than Dash, which is why Debian and friends don't use it as /bin/s
by nrclark 4y ago
This article has some questionable advice imo.
SHELL := bash
Bash is a much slower shell than Dash, which is why Debian and friends don't use it as /bin/sh. .ONESHELL mitigates the speed problem, but you could also just use the default shell and leave ONESHELL turned off.
Use bash strict mode
....
.SHELLFLAGS := -eu -o pipefail -c
I wish people would stop cargo-culting the so-called "strict mode".
The -e flag is only useful because the author likes .ONESHELL mode. If you leave ONESHELL turned off, then you don't need it.
The -u flag is useful sometimes, depending on coding style. I use it on complex scripts. Individual Makefile recipes maybe don't want that much complexity though. Also the -u flag makes the shell's variable-handling behavior inconsistent with Make's.
The pipefail option is Bash-specific, and only works because the author likes to set SHELL to Bash in their Makefiles. It's also not a good default in my opinion. There are times when it's useful, and other times when it's the opposite of what you want. Just depends on the pipeline that you're writing.
- jart 4y agoThe fastest shell is to not use shell special characters. For example, if you say `foo bar >/dev/null` then Make needs to launch your program as `sh -c 'foo bar >/dev/null`. But if you say just `foo bar` then Make can pass that directly to execve(), bypassing the shell entirely. Sometimes I actually do this: SHELL := /bin/false Just to make sure my Makefile doesn't use shell syntax. If you want a `.STRICT` mode, then try Landlock Make.
- jwilk 4y agoDoesn't work for me: $ make -v | head -n1 GNU Make 4.3 $ printf 'SHELL := /bin/false\nall:\n\tls\n' > Makefile $ make ls make: *** [Makefile:3: all] Error 1
- jart 4y agoI completely forgot that the GNU Make source code has a check to see if the shell is bourne-compatible (it just strcmp's with sh, bash, and a hard coded list), and then only applies that optimization if it is. I deleted that code in my Landlock Make fork so I could use shells like /bin/false and still get the optimization. So sorry about that! Give it a try with Landlock Make https://github.com/jart/landlock-make https://github.com/jart/landlock-make and https://justine.lol/make/ https://justine.lol/make/
- nrclark 4y agoWoah, interesting! I didn't know that Make could launch programs directly. Is that specific to GNU Make?
- jwilk 4y agoAt least NetBSD make (also used by FreeBSD, and packaged as bmake in some distros) has the same optimization: https://github.com/NetBSD/src/blob/netbsd-9/usr.bin/make/compat.c#L298 https://github.com/NetBSD/src/blob/netbsd-9/usr.bin/make/com...
- jwilk 4y ago> The -e flag is only useful because the author likes .ONESHELL mode Not really. The most common class of bugs I see in makefiles is something like this: for x in foo bar baz; do frobnicate $x; done This ignores errors from frobnicate, unless you set -e.
- chriswarbo 4y ago> Bash is a much slower shell than Dash, which is why Debian and friends don't use it as /bin/sh Their advice is mostly about using a known interpreter, rather than 'vague POSIX hand-waving'; e.g. they end that section with: > The key message here, of course, is to choose a specific shell. If you’d rather use ZSH, or Python or Node for that matter, set it to that. Pick a specific language so you can stop targeting a lowest common denominator Your suggestion of Dash is compatible with that (as is any other particular shell interpreter). An analogy would be running Selenium tests with particular browsers, rather than using /usr/bin/www-browser and trying to accomodate lynx, dillo, netsurf, ...