The guys over at Power of 2 Games (their blog, by the way, is probably one of the best blogs on coding process and practice that I know of) have a post that basically lambasts the SCons build system, and for good reason: it's dependency checking is slow, and for large game projects that can have very large numbers of dependencies (especially in assets) that's a problem. But, it got me thinking about build languages and build systems in general, and what I would want from a perfect build system.
As a result of the Power of 2 Games post, I took a look at not only Scons, but as many of the build systems mentioned in the comments, including Waf, Jam and it's
variants, CMake, MSBuid, Ant, and Maven. There's a ton to choose from, and most tools are happy to explain to you why they're the best (SCons expliation vs. Waf's explination). Of course all of these different build systems try to solve one problem: a complicated build process is hard.
Interestingly, I don't like any of these build systems. I use MSBuild day to day because I use Visual Studio day to day, though I use Ant for the actual build script that is executed by my continuous integration system, and for running unit tests and deployment scripts (one thing I've learned over the years is never have a target in Visual Studio that deploys an executable, it's only asking for trouble). However, the only reason I use Ant at all is because I know it, it's almost universal in its acceptance across IDEs (except Visual Studio) and because I've yet to find something that I really like more, that has a simple enough syntax and is easily extendable. I certainly have my problems with Ant, including its use of a data definition language as a scripting language, it's speed, and the fact that it can be very difficult to get it to do what you actually want, but I live with it, much like I think most people live with whatever build system they use.
So, what do I want from a build system? Why don't I like these others? I want a build system that does the following:
First, I want something that can either a) be generated from Visual Studio project files or b) is just natively understood by Visual Studio, and I lean towards 2 as not only being more possible, but the better solution. Why do I want this? Well, believe it or not, I really like Visual Studio. Despite its flaws (and it has many, especially in the C++ department), it's a pretty good IDE, and I like using it, which means I want to be able to manage my projects from *inside* it. Most build systems recognize that Visual Studio is used and thus go the other way (generate projects from build files) but can't go the other way. The problem is that MSBuild (and VCBuild) aren't very good build systems and they're extremely complicated, which means creating something that understands both MSBuild AND VCBuild is probably something that would make someone want to tear their eyes out. Having Visual Studio open and understand another format is probably just as nasty, but perhaps slightly more possible with a Visual Studio add on. The difficulty would probably be duplicating as many of the features from Visual Studio in the project file type, which could be potentially a big issue.
Second, I want a build system that understands high level project dependencies, as well as low level file dependencies. When builds rely on shared libraries and such, it's sometimes good enough to know that the shared library changed, meaning that regardless the project will need a rebuild. In some cases, a build system can look for the binaries of a changed library, instead of requesting to build source that you might not have. Maven is fairly good at this, though I don't agree with how it's done (though, in defense of Maven, it's almost certainly the way it should be done for Java).
Third, I need my build system to be cross language and cross platform. At best, it should understand how to convert build parameters between different platforms automatically, which would mean you could build using Visual Studio's system or GNU C using the same build file, same parameters. This may, however, be a complete pipe dream.
Lastly, I want a build system that can, without any changes to the build file, distribute builds among multiple machines. This is not much of an issue because it is currently true of KJam, SCons and (potentially) Waf. The idea is that the same build file could be used on a build server for complete builds of a project, and thus it may need to be farmed to other machines in order to produce a build in a timely manner.
Now, if that's too much to ask, I have other demands as well, especially on the side of continuous integration or build server. I've yet to find a continuous integration product that I really like, as very few allow one key feature that I want: Organization of a large project into multiply dependant sub-projects. If I check in a change that changes dependant libraries, I want my build system to recognize this and build each part that it needs to build. In addition, I want it to deploy that new build only when all outdated parts of the project are finished. In most cases, I think that continuous integration systems expect your build system to handle this, but…
In addition, I find that finding a system that understands build steps is also hard. For example, I have unit tests and integration tests on one of my projects. I want the unit tests run on every build, including developer builds. The integration tests, however, only need to be run by people currently working on those systems and by the build machine itself. So, why can't I tell my continuous integration system: "Build, then run these tests, then deploy. Any of those steps failed is a failed build." Instead, I have to put this in the build script… even though it's technically not part of the build.
And really lastly, I want my CI server to understand isolated builds. Team City does this (I think) and it looks like it could be pretty awesome. Let's face it, if we set up our build system right, it'll be able to build way faster than a developer machine ever could, and for a long, complicated build, a developer should be able to request that the CI take over and make a build just for him, using his code. Integrate this with Mercurial, and it could actually work really well. Couple that with artists being able to ask for asset builds, and you'd have a happy, happy team.
So, maybe this is too much to ask for a complete build system, and maybe we'll never see it, but I will say that I'd love to work on it someday.
So, you might want to give CMake a look. It pretty much does what you want. It generates native VS projects (VS 6,7,8,9). It keeps track of both low level and high level depend information. It is very cross platform (linux, OSX, Windows, IRIX, HPUX, and others.)
The problem is that CMake generates Visual Studio projects, but doesn’t go the other way, which was my main point. I want my build system integrated into my development environment, and that’s not something CMake does (so far as I know).
No, CMake does not go the other way. I think there have been attempts to write one time conversion utilities. I suppose you could create a VS plugin, that did some sort of edit on the cmake files for a project as new files and targets are added, but CMake does not currently do that. So, it comes down to trade offs I guess. With CMake you can do most of the stuff you do with your environment, build stuff, edit files, and debug stuff. You can not add new files to the project via the IDE, or change compile flags. Other than that the other parts of the IDE work as they would in a native VS project.