I posted on the icculus quake3 list about the possibility of using
SCons; the build that id used was cons, though they also left behind a
Makefile
that was clearly out of date. The discussion didn’t last
long: someone suggested using automake and the lead developers
quickly doused that idea by stating that plain make would be the way
to go.
It got me thinking, why did I think SCons was better than that, when
there was strong demand to stay put, and suggestions to change to
something I can’t stand? Why did I want to use SCons in the first place?
I think it all boils down to one particular use case, that I find so
attractive that all other failings are massively outweighed:
modifications to the build just work.
Let’s assume we have a project with three different build systems:
plain make, GNU automake, and SCons. All three from a fresh checkout
do the right thing and you end up with the binary you’re expecting.
Also, the build systems do the right thing when you modify the source
code: make will detect the timestamp change and recompile; automake
just generated a Makefile with the correct dependencies, so that make
will detect the timestamp change and recompile. SCons will notice
either a timestamp change or a MD5 sum change on the source file, and
recompile.
There’s a caveat here: with automake and SCons you can guarantee that
your build will be correct, with plain make you need to be sure that
you’ve specified the dependencies correctly. This is a corner case
though, it takes a special kind of project to mess this up, but it is
possible and tracking it down and fixing it can lead to pain: at work,
other developers can and have set up the build system to do something
the wrong way, and then complain to me “I wanted to do this and it
doesn’t work!”
My use case, however, is not modifying the source code, it’s modifying
the build.
Say you’ve been hacking for a while, and your project is working, but
you realise that you’ve foolishly left out -Wall -Werror
from the
CFLAGS. Let’s see what happens if you add it to each of the above
projects and recompile:
Plain make will do nothing. The targets already exist and the
source code has not changed. Make knows nothing of recipe signatures,
so the fact that the command line to do the build has changed is of no
consequence. In order to get a correct build you will need to make clean
, and that relies on the fact that you’ve written a target to do
that correctly – more potential for getting it wrong.
Let’s not limit ourselves to CFLAGS here; if there’s an option that
only changes part of the build, then you are going to have to
rebuild the whole project in order to take advantage of the change.
That totally sucks on a project that takes between 30s and 5 minutes
to build, because it’s too long to wait and not long enough to go get
a coffee.
Automake will either do nothing, or do something wrong. Depending
on whether you ran configure
with --enable-maintainer-mode
and
you have AM_MAINTAINER_MODE
specified in configure.in
, the
generated Makefile
may have no idea about its own dependencies.
On the other hand, my experience with automakes 1.4, 1.5, 1.6, 1.7,
and 1.8 have always caused some frustration with random regeneration
errors – partially reconstructing the build system, usually caused by
make’s own reliance on timestamps – and even when it gets it right
you still have the problem of needing to do a full clean before a
rebuild.
SCons will rebuild your project correctly. SCons keeps a record of
what the command line for each target was, and if that changes then it
will consider the target to be out of date. If you change the CFLAGS
for a project between builds, the project will be rebuilt correctly.
If you change something that only affects part of the build, only
those parts that are affected will be rebuilt.
There are three kinds of people who will be affected by your build
system: users, distributors, and developers. The users, though
automake has a lot of mindshare (with it’s configure; make; make install
) mantra, don’t really care how it builds as
long as the README
explains how and that it works. They only need
to build it once. The distributors don’t care what builds it as long
as it builds and installs into the right places, i.e. FHS compliance
out of the box – --prefix
and DESTDIR
variables or something
equivalent so that the packages can be built. They may build it
several times, but it’s all encapsulated in the packaging scripts and
hidden behind a simple command tool: debian/rules
or rpmbuild -ba
or what have you.
Developers, who are building and hacking and building and tweaking and
profiling and building, do care that their build is correct, and
that the time spent interacting with the build system is as short as
possible. As a developer, I don’t want to spend time cleaning,
regenerating, and building just to make sure I get a correct build. I
just want to type one command.
scons
is that command.