Hacker News new | ask | show | jobs
by dzaima 559 days ago
I've written a good amount of makefiles (and even one rather complex one.. before replacing it with a thing written in an actually sane language, bootstrapped by a stripped down version of the makefile), and I still mix up $@ $< $> or whatever else my brain comes up with. And this is coming from someone deep into array languages, which have entire sets of unicode glyphs.

For how often one typically writes/looks at build scripts, remembering the specifics about makefiles is quite likely to not be worth the effort.

Makefiles start becoming incredibly awful if you want to do anything outside of pure computations in the separate targets. Making the target directory requires either putting the mkdir call in each separate built thing (awfully redundant), introducing a whole another rule (and still adding it as a dependency on every rule that'll be outputting to said directory), doing some recursive make, or running it outside of rules (but putting it under a proper if statement is likely pain). That's a bunch of awful solutions to something that really really really should just be a single calls to mkdir in any sane system.

Another horrifically awful thing is if you want some reused data across rules (e.g. pkg-config results, current OS/arch). You can put them as globals, but that'll make them be calculated always, even if no build target needs them, unless you put them under an if, which is again non-trivial to get the condition correctly for. This becomes super bad if you do recursive make stuff.

More generally, makefiles start out simple, but doing anything that's not strictly simple is gonna be pain, at the very least requiring looking at docs of a thing you'll probably never use again, and debuggability is also very low (amusingly, '-p' and '--debug' break on recursive make, seemingly losing some variables; and '-n' requires copying out & running the recursive call to get to the actually important part; and afaict none of those help with figuring out why a thing didn't build).

And you're completely SOL if you wanted to do things like reorder compilations based on how long they previously took, or want a nice display of currently-compiling things.

1 comments

Fair. But as said, in my experience, they remain useful and simple for a pretty long time. I usually always start out with a simple Makefile. Only sometimes do I start with or eventually switch to something else because of the projects’ needs, but for most stuff (even stuff where the project itself is complex, i.e. embedded kernel stuff where different units are pasted together and whatnot), relatively simple Makefiles do their job pretty well.

I also have a lot of phony targets. It really enjoy just being able to type:

   make restore kernel reset upload
To bring a device into a sane state, build the kernel, reset the device, and upload the built firmware.
Aand that brings up another issue - that (and a good amount of things that will work as expected on the default -j1) breaks with -j4.

Apparently .WAIT and .NOTPARALLEL exist, which I couldn't find last time I needed something around this. Though for this unfortunately `make -j4 foo .WAIT bar` isn't allowed, but at that point separate make invocations is fine.

Another fair point. I think I'd use this:

    make restore & (make -j 20 kernel && make reset upload)
But in reality, the kernel target actually calls make anyway, so it's just in there. Depends on the exact situation.