redo for make users

Looking at the development of Daniel J. Bernstein's various softwares over the final few years of the 20th century, it is evident how redo had its origins in the idea of turning Makefiles inside out. Bernstein gradually developed a system where the shell script to be found in the body of a Makefile rule became incorporated into helper programs in .do files that ran (undocumented and unpublished) programs named dependon, dependcc, formake, and directtarget.

As the fundamentals explain, in redo there is no control file containing shell script snippets, but with its own set of separate variables, and flow control and conditional compilation mechanisms. Instead, the shell scripts are the first class .do programs, no longer embedded into something else, no longer requiring escaping to ensure that shell metacharacters do not conflict with make metacharacters, and fully in charge of all loops, conditionals, variable expansions, and whatnot.

The fact that they are recursive is a good thing and by design, whereas "recursive make" is famously problematic. "recursive make" fails because nested make invocations contain incomplete change information. redo has a separate, on‐disc, dependency database where recursive invocations at all levels can look up all information. "recursive make" fails because lower‐level makefiles lack honest dependency information on non‐local things. redo encourages fully honest dependencies upon everything including compiler/linker/assembler/archiver names and flags and even out‐of‐tree programs.

The tool names and flags are also part of a larger idea in redo that auto‐configuration is not a separate step. There's no need for a whole system of separately running a completely different set of tools, with their own oddball macro language, just to generate a custom massive shell script that then test compiles things, just to eventually generate some source file headers and the actual Makefile to use. (This is Autotools, in a nutshell.)

With redo, a shell script to test compile things to see whether the platform supports them, and make a header (or indeed non‐header) source code file appropriate for the results, is just more of the build system, an exercise in platform dependencies. Not only does the build system automatically configure itself from scratch when totally unconfigured, it can even automatically re‐configure itself for platform dependencies that are (as many are) as simple as testing whether a platform has an API with a header file.