5 ms·
When I started with make, I copied working files to a safe place, copied from the safe place to a scratch place, tweaked the scratch, got it working, etc., etc.
by PeterWhittaker 12y ago
When I started with make, I copied working files to a safe place, copied from the safe place to a scratch place, tweaked the scratch, got it working, etc., etc. Managing the make file was itself part of managing the project.
Then I read and thoroughly grokked the O'Reilly book on make (which some douche stole from my desk; twenty plus years on, I am still bitter about that one... ...don't miss the Tannenbaum OS book or the Stevens networking books, but the make book, it burns, it burns....)
After that all I wrote all of my make files from scratch. Doing so made sure I understood my project, its dependencies, etc., and made sure I wasn't going to accidentally corrupt a build with some edge case from another one.
make is super straightforward once you get how it works. Sort of like git rebase, I suppose (still working on that one... :->).
- DannoHung 12y agogit rebase I pretty much understand. Make will forever be a mystery to me. Mostly just how after the third or fourth version of it they didn't take a step back and think, "Hey, wait, maybe we should just make a language that spits out a shell file and ditch having it sort of kind of look like a shell file itself."
- GauntletWizard 12y agoBecause a shell file would be an inefficient and imprecise way of describing the state and logic that Make uses.
- DannoHung 12y agoReally? I mean, it pretty much just runs commands in sequence and/or parallel, right? Sorry, like I said, I don't think I really understand make. I mean, I can understand that it's doing some checks to determine what commands to emit, but doesn't it all end up falling out as pretty much a straight "Yes? Do this. No? Do that. Do this and then this and then this. Do all these at the same time." That's my mental model at the moment anyway.
- GauntletWizard 12y agoUltimately, make represents a dependency graph; Something that a shell language is not well prepared to represent. Yes, it's doing X, Y, and Z at the same time, but when X is done it can launch A and B, when Z finishes then C can also be started, but you don't want to run them all at the same time because of a max subprocesses limit. You don't know if X or Z will finish first, so you can't just launch C as soon as Z is done, nor do you want to waste time waiting for A and B to finish to launch C if Z is done. How do you express that in pure shell?
- barrkel 12y agox: y z x depends on y (meaning, if x is missing, or is a file that is older than y where y is also a file, it needs to be recreated). z is how to recreate x. Makefiles are programs that construct a dependency graph. The rest of makefile syntax is mostly about ways of generating variants of the above without being overly verbose, or reducing gruntwork when e.g. adding new header includes to existing source files. But this is the heart of it. Root the dependency graph somewhere, and as long as the dependencies are complete and correct, the minimal set of commands, and potential parallelism, can be calculated.
- hamstergene 12y agoThe point of make is to avoid doing what does not need to be done. Don't recompile binary whose sources didn't change, don't copy file which is already there, and so on. Because those operations add up to hours as the project grows. If we didn't mind waiting for hours each time we build, then of course, a shell script that does `rm -rf target` then assembles everything from scratch would be significantly more straightforward and readable.