Build

What is Build?

Build is a new build tool. It is intended to be a clean, scalable, heavy-duty, easy-to-use replacement for all of make, autoconf, automake, libtool, and ccache.

Build is based on experience with all these tools and more. It tries to correct their design flaws, and unify them into a more easily comprehensible framework.

Status

Build is still in a very early stage. The basic classes have been written (and work), but the to-do list is quite long, and some critical pieces have yet to be written. Hardly any tools exist yet.

At this point, most of the statements below represent our plan rather than actual fact.

Build Ideas

One of the big ideas in build is that configure and make should not be separate operations. Separating these two steps is an ongoing annoyance with current tools. It makes the build system harder to understand and maintain, and it also can cause performance problems, as configury is not parallelizable.

In Build, configury is fully integrated with the build. In fact, in Build, most computations are handled through a generic dependency resolution algorithm. From this perspective there is no difference between computing a "configure" result (e.g., does this platform have socket?), a string of some kind (e.g., the host triplet), or an object file.

Build tries hard to capture precise dependencies for all derived objects. The standard tools are smart about computing dependencies automatically. Build automatically includes the command line and the command's file in dependencies.

Build uses signatures rather than timestamps to decide when something must be updated. Timestamps have proven unreliable in several well-known ways.

Build keeps a lookaside database that remembers the relationships between objects. Additional, the combination of precise dependencies, command dependencies and signatures allows us to keep a derived object database. In essence, this is what ccache does, except Build's design allows us to use the cache for any derived object.

Build constructs a single model of the entire build -- there is no need for a "recursive make". However, you can still put build rules into separate build files throughout your package's directory hierarchy. Build will read them and "relativize" them for you.

Rather than implement our own scripting language for this new tool, we elected to reuse an existing one. No language is perfect for this task -- all have problems of various sorts. The current version of Build uses Python. One benefit of using a standard scripting language is that we get a less ugly syntax (depending on taste). Another benefit, relative to make, is that there are no quoting problems. It is easy to refer to and manipulate files no matter what strange characters appear in their names.

Build scripts are easily parallelizable. This is the default mode of operation, and most tasks (including configury) can be parallelized.

Files are not a necessary concept to Build. They are heavily used, and most tools deal with files, but there is no requirement on this. Build could easily be extended for use on derived objects other than files.

Build's built-in tools and tool factories are written in a standardized way, so that things like flags and customizations are handled similarly. For instance, the standard tools always allow you to specify flags on a per-object basis (e.g., you can set the C compiler flags for one program differently from the flags for another).

In Build, and unlike make, macros have scope. Also, Build understands cross-compilation. In conjunction with the use of scope this makes it very easy to run configure tests, and build programs for, the host, target, or build machines, all in one build file. (This is difficult in an autoconf-based project.)

Build uses objects internally, not names. And from the command line, Build has different namespaces for mapping names to objects. As a consequence, for instance, it is no longer difficult to build a program named install.