3 ms·
Wow. This is atrocious. > You really just need the .RECIPEPREFIX = > Now I can't copy & paste a block anymore (into the shell, to run it), and all my editor i
by eqvinox 4y ago
Wow. This is atrocious.
> You really just need the .RECIPEPREFIX = >
Now I can't copy & paste a block anymore (into the shell, to run it), and all my editor indentation settings are broken.
> SHELL := bash
And the Makefile is now non-portable.
> .SHELLFLAGS := -eu -o pipefail -c
If this matters, it's likely you're wedging too complicated things into one recipe. But less bad than the other suggestions.
> .ONESHELL
Funnily enough using this is the primary reason the previous item becomes important. The subtly changed behavior also turns multi-line recipes into a giant footgun if you end up with a non-GNU make.
(skipping a few that are not as bad)
> out/image-id: $(shell find src -type f)
Might be OK in a single rule. Otherwise, it's calling find more... and more...
> Sentinel files
Actual good practice to end it on.
- jen20 4y ago> And the Makefile is now non-portable. The article calls out GNU Make, so almost everything else in there is also non-portable.
- eropple 4y agoEven beyond that I don't really understand the criticism. Like, I don't remember the last machine I had to do serious work on that didn't come with GNU Make either out of the box or added as part of some very basic bootstrapping scripts. (I don't know what a Mac comes with because my bootstrap for every new machine has coreutils in it and every project has a Brewfile with it too.) I definitely don't remember the last machine I saw that didn't have bash on it.
- dllthomas 4y agoAnd in this case we're concerned about computers that do have GNU make but don't have bash...
- eqvinox 4y agoIf you write Makefiles for your own personal use — sure. If you're working in a team with other people, or are publishing things for a broader public to use… no. Especially since things like .ONESHELL don't just flat-out cause errors, but rather introduce subtle and insidious distinctions in behavior.
- eropple 4y agoEhh. If I'm writing a Makefile, team context or no, it's almost certainly because I don't expect other people to be more familiar with Make than I am. If anything, I would expect ONESHELL to map to how most programmers think Make already works, even though it doesn't. I know I have to go look up the various Make-isms whenever I need to do anything complex. And a Make supergenius, should I ever meet one, surely will look at the top of the file or derive from "incorrect" code that something is nonstandard. I'd love better tools that take the good parts of Make (around file transformations, mostly) and expose them more effectively in shells (because doing so in a more fully featured programming language often results in different and worse hacks--hi, Rake) but using Make to do things more people will find predictable seems fine to me.
- eqvinox 4y agoI guess I should've been more clear. My point is other people /using/ your Makefile, not editing it. You know what you're running. You don't know what everyone else is running. I've singled out ONESHELL because it will be silently ignored by non-GNU make, and it will behave ever so slightly different enough to cause extremely hard to find bugs. Example: .ONESHELL: sometarget: someinput ␉BASEDIR=other_expression ␉SHELLVAR=complicated_expression ␉rm -rf $$BASEDIR/$$SHELLVAR (obviously extreme to illustrate the point, but you get the idea.)
- eqvinox 4y agobtw. On the BSDs, GNU make is "gmake" while plain "make" is POSIX-compliant BSD make. Better hope you never make the easy mistake of forgetting that "g"… (If you use any of these features — please rename your Makefile to GNUmakefile. Please. I beg you.)
- aldonius 4y agoAt least on my machine, it's a GNU Make... version 3.81. I can only assume that's the last of the GPLv2 licensed ones. Classic Apple.
- eqvinox 4y ago> The article calls out GNU Make, so almost everything else in there is also non-portable. My brain honestly didn't process that, and it's still refusing to. I think it's the braces around (GNU) — seems like I have some neurons wired to push (bracketed) pieces of text down into a "detail" stack and eliminate them from high-level processing… P.S./ed.: GNU make looks for GNUmakefile before Makefile, and arguably if the Makefile is GNU specific, that feature should be used — and that includes the title of the article ("Your GNUmakefiles Are Wrong")
- dllthomas 4y ago> Now I can't copy & paste a block anymore (into the shell, to run it) You likely can, actually. Most terminal emulators have a key you can hold (ctrl in gnome-terminal, alt in urxvt) to select a block of text that doesn't start at the beginning of the line. Doesn't work if your lines wrap, of course.
- spicybright 4y agoBut then you can't copy a target and it's steps in one go. And the pasted code will only have a single space for indentation, if I'm understanding right. Plus without word wrap you can't copy more than a screen width at a time on most terms.
- dllthomas 4y ago> But then you can't copy a target and it's steps in one go. The parent said they wanted to paste it into the shell to run it. In that case, you aren't going to want to copy the target, only the steps. It will have a single space indentation if you start there, or no indentation if you start one character over; either could be what you want, depending on your shell settings and whether you want the commands in your history. If you want to copy and paste the target and all of its steps in one go, you need to ask yourself where you want to paste it, but probably including the > and copying normally is the right thing, to be reformatted on the other side as desired. In fact, I expect that to break a little less often than pasting things with leading tabs. > Plus without word wrap you can't copy more than a screen width at a time on most terms. Yeah, I was imprecise; "doesn't work if your lines wrap" should probably have been "doesn't work if your lines are long enough that they would need to wrap".