What do you look for in a build system? Ease of use, maintainability, portability, extensibility, simplicity, scalability, reproducibility and performance are all valid things to worry about. All are important. But what I find I'm looking for more & more are the latter two: build reproducibility and build performance.
Both come down to saving time. If your builds aren't reproducible you're going to end up wasting hours tracking down strange differences that somehow crept into your software product. Omitting a file or getting an incorrect version of a file in your product could cost you months of support effort.
I also hate sitting around waiting for builds to finish. That's wasting my time as a developer or tester. So it's important to me that my build system take as many shortcuts as possible to reduce build time (without sacrificing correctness or reproducibility of course). Correctly managing dependencies is the primary way a build system does this. More exotic schemes can be employed in a team environment, where derived objects built under the exact same conditions can be shared across developer sandboxes, or by doing distributed builds. But dependency management takes the biggest bite out of build time & should be tackled first.
Cons is the latest build system I've fooled around with & on these two counts, it seems a head above the rest.
Cons is very anal with respect to reproducibility--you have to be. By default it builds everything inside a clean system environment. You must manually specify the paths to any tools you're invoking, and there is a well-defined mechanism for importing and exporting these "construction environments" from a parent build into a sub-build. Compare this to GNU make, which by default is sloppy about these things.
Cons is also very precise in its dependency management. Rather than use timestamps to determine out-of-dateness--which there are innumerable problems with--it does MD5 checksums of dependencies to see if they've changed, and would necessitate a rebuild of targets. This makes builds more reproducible too. But Cons doesn't just checksum the files: it even goes so far as to checksum the construction environment and the command line used to perform a build action. If any of these things change, the target must be rebuilt.
Now this might seem a little severe. What if you change the command line or the environment in ways which don't actually affect the build product? Won't Cons waste time rebuilding things it doesn't need to?
Look at it this way though: overall, the fact that you can rely on Cons to do correct, if severe, dependency management is actually going to save you tons of time. How many times have you not been sure that everything out-of-date got rebuilt correctly, and wound up cleaning the entire build tree & kicking off a full rebuild just to be certain? Once you get Cons set up, a top-level "make clean" is going to be very, very unlikely. And this is where the time savings are biggest.
Another cool thing that Cons does is global build sequencing. Rather than examine some dependencies, execute some build actions, examine some more dependencies, etc., Cons gathers all dependency information and appropriate build actions over the whole active build tree before doing anything. By deferring this it is able to put all build actions in the correct (topological with respect to the dependency graph) order. This is sometimes a problem under other build systems when you have a large, hierarchical build in which there is some dependency interaction between sub-builds.
Cons pays a lot of attention to hierarchical builds, and for this reason appears to be really, really scalable.
Cons has other cool features: it can do repository builds (naturally this pales in comparison to clearmake's wink-in), has source files scanners to auto-detect dependencies in common file types, and is very extensible (of course, it's written in Perl).
That's not to say that Cons is all goodness and light though. Probably the biggest problems with Cons are in the areas of simplicity and maintainability. Writing a Conscript file is much trickier than writing a Makefile if you don't know Perl--there's a steep learning curve there.
Also, I've always liked the idea of storing everything about the build in some structured format like XML--Ant's got the right idea in this respect--since really, if done right, a build is mostly data about what's going in and what's coming out, and their dependencies. The process can be abstracted out. But with Cons all this information is jumbled up in scripts. There's definitely an opportunity for someone to write a framework in Cons that lets you store the dependency information, at least, in some consumable format.
There are also some specific features in Cons that need work. The Conscript_chdir setting, which is supposed to make Cons chdir down into sub-build directories, is one of them (as of cons-2.3.0).
Finally, I'm not sure how active the Cons development community is. Things seem pretty quiet. And certainly there isn't much of a userbase, so one's hacking abilities are put to the test whenever a problem comes up.
Overall, though, Cons scores pretty high according to most of the metrics for judging a build system, and certainly nails what I consider the big ones. As a Cons user I'm brand new, so we'll see if I'm still this excited about it in a few months.
Posted by Alan at April 12, 2004 03:21 AM