# Build automation tools before make?

I realized that make was "only" invented in 1976 and seems to be one of the first build automation tools (at least it's probably the oldest still in use). Make with its shell focus seems like a total Unix-ism. It's interesting innovation is not being a build system but its dependency graph solver that runs build steps lazily.

But we already had a history of large software projects in 1976. What did people use for e.g. OS/360 or the software for the F-14? Were there any real precursors for make or did make invent the concept of build automation?

• Indeed, the quest for the perfect "dependency graph solver" has been a monument. – Brian H Apr 17 at 15:18
• Just getting your first print-out from the execution attempt on your stack of cards was an important step. Did it even compile/assemble? If it generated output, was it obviously non-sensical? Have you got enough paper yet to burn and provide your home with warmth for the winter? 😏 – RichF Apr 17 at 21:53

Preface 1: There can't be a single answer for all the varieties that have been out there

Preface 2: It's important to keep in mind, that make didn't start out as the almighty build automation and installation tool it's seen as today, but as a utility to reduce compile time by only compiling files that have changed or that depend on changed files. Compiling was a resource intensive and slow task on machines back then. It wasn't 50 files per second, but rather 50 seconds per file. So saving every little step did count a lot.

Were there any real precursors for make

Yes, there were, but usually rather OS-, development environment- and project-specific tools.

or did make invent the concept of build automation?

Not really, it's rather that make is a solution for a problem that did not arise the same way on mainframes. Software structure (at least for reasonable sized projects) was way more modularized and built around (internal) APIs. Changing a module interface was rather frowned upon - and even more so using global variables and the like.

Access to interfaces and data provided was usually encapsulated by interfaces - much like today's idea of methods. Except, we didn't use all these various fancy names. There were interfaces and records (parameter blocks). These 'methods' were kept binary stable as long as possible to avoid the need to compile whole applications at once. Changing some basic structure on the fly and starting a make was seen as quite unprofessional - think before you code.

Software development was much more incremental, based on module concepts. Modules (and thus interfaces) were (could be) versioned. The task to handle this was often handled by, or at least done with great support from, the linker, handling dependencies including version matching (*1).

Bottom line, it was a different approach using a much more deliberate process.

Wartime Stories:

I took part in development of a rather large (>1200 modules) mainframe software. In the mid 1990s the development process was stable for more than 10 years (in fact, even longer, predating this project) - when a major customer became interested in the development process used. The usual crap about quality. And the usual combination of outsider management with no real idea about software - or more exactly with about the knowledge of a weekend course about software - and some young graduate with 'fresh ideas' - as well just as fresh as his limited knowledge from university could carry - produced a request to change to a make style development - as our proven process is of course outdated by modern tools. Even worse, the whole team was developing into a single repository only separated by task and only versioned by delivery cycle. Yeah, right.

Also as usual, the largest customer got more say about things he should not care about than was good. There is no make for the mainframe OS we used, so we had to create our own. Even more so, we didn't have trees of weird source-and-alike files, but well defined libraries holding sources, macros and scripts including many rules about how to combine and evaluate them.

Long story short, it took us about a year (and about half a million dollars) to develop a new build process. We finally settled to a hybrid. The development was done as before, except now every developer had to have his own repository (which of course added way more errors and more management to handle them). When a release was up to be delivered everything was now pumped into the new build system and configurated in one huge almost-an-hour-long build run.

Of course that new system never did report any new error. But hey, modern ... if I only had killed it with the argument that make is way older than the system we had, back when they proposed it :))

*1 - Linking was also usually not done against a bunch of .o files, but libraries holding versioned binaries - which itself could be the result of a linking process.

• "except now every developer had to have his own repository" Looks like the mid 90s were too early for git, then... (SCNR). – dirkt Apr 18 at 5:39
• @dirkt There was source code c control in the 90's. It was just way less sophisticated than now. – JeremyP Apr 18 at 8:47
• @JeremyP: In case you missed it: One of the main things that makes git different from other, earlier source code control systems, say, CVS (which counts as 90's, I suppose), is that every developer does have his own repository, and he/she can synchronize it to and from other "upstream" repositories. In CVS, you always check out from a central repository, and I'd suppose that was the case with earlier variant like RCS and SCCS, too (haven't used either). So the idea "every developer needs to have his own repository" was valid, just a bit early. – dirkt Apr 18 at 10:03
• @dirkt I've used SCCS and briefly RCS. In both, each file was tracked separately. I'm not sure there was a concept off a remote repository or even a repository. CVS represented a huge step up (in my experience, at least) because you could treat a whole set of files as a single thing. git by the way is not the first distributed VCS nor the best. In fact, of all the distributed VCS's I have used, it is the worst (admittedly, I've used only two, the other one is Mercurial). – JeremyP Apr 18 at 14:15
• It took only an hour to build your software? Luxury! – another-dave Apr 23 at 17:45

Based on what I know of the history of build automation tools, make was the first tool of its kind. By this I mean that make was the first widely-distributed and widely-used tool expressly designed to solve the problem of speeding up software rebuilds by using a dependency graph.

As @Raffzahn very adequately describes, there was never a case where programmers on large projects didn't need to solve this problem. The "problem" was that programmers were solving it over-and-over in isolation for different projects and programming environments. make brought into existence a tool for just this one thing... which, as you say in the question, is a "Unix-ism" in the best sense.

• I think the definition of a "large project" was much different in 1961 than it is now. Computational capacity, memory, i/o, and production techniques were all limited by the technology and procedures of the time. In some cases just gaining the understanding to start asking the right questions was a limitation. – RichF Apr 17 at 21:48
• @RishF I am basing on what I know from computing in the 1980s, which is you would never want to, for example, re-compile that which only needed to be re-linked. It was too slow for any program I worked on that would have been worthy of the name "project". I still spend a lot of time nowadays perfecting the dependecy graph for large projects. It's not because compilation is slow; rather, it's the automated deployment and testing cycle that takes too long if you don't cull the graph. – Brian H Apr 17 at 22:03
• I wasn't disagreeing with anything. Maybe my comment would have been better placed with the question than your answer. – RichF Apr 17 at 22:31

In the ages prior to make, program rebuilds were as fast as you could get the keypunch operator to type up a new stack of cards from your hand-written coding pad.

• Plus, at many facilities, there was the wait time to get your project scheduled on the mainframe. – RichF Apr 17 at 21:39
• Don't knock it. You had time to smoke a cigar, get a shoe shine, and read the newspaper between rebuilds... – Brian H Apr 17 at 22:07

One precursor was Digital's Concise Command Language. This reduced the number of steps required to go through a revise and test cycle.

Later, Digital moved on to DCL, which permitted building a customized command procedure to automate building. But DCL came after the make command you asked about.

• I accept the edits made to my post. But I did intend the lower case d for Digital. That's how it appeared in the digital logo. And to me, it will always be DEC. – Walter Mitty Apr 24 at 9:51

"Build automation system" seems to be a grandiose name for how we used to build software in late 1970s in my corner of DEC.

There was a file containing the commands needed to build the software system. Someone wrote that command file. You ran that command file (batch, indirect command processor, whatever - it depended on the system). If the commands needed to build the software change, then we have interactive editors that can change the command file :-)

For day-to-day software development, you'd typically know what you needed to rebuild based on what you'd changed, so you might say that dependency management was all wetware-based.

Every now and then, when some functional milestone had been reached, a "baselevel" would be declared. A clean set of sources would be collected, built from scratch, run through a few cursory tests, maybe some distribution binary tapes made if needed, and the baselevel disk would be taken down and put somewhere safe, offsite if you were important enough.

tl;dr - "how to build this software" was a pretty static procedure, so the lack of automation -- as distinct from unattended operation -- did not seem to be a problem.

• "For day-to-day software development, you'd typically know what you needed to rebuild based on what you'd changed" -- except when you overlooked something. That added an entire class of very common errors to the process. Couple that with linkers that would only produce a viable executable if you got the file order exactly right (I'm glaring at you, VMS), and it was -- kind of hellish, really. – jeffB Apr 23 at 18:24
• Real programmers wrote task-builder ODL files. ;-) – another-dave Apr 23 at 18:28