Thursday, 1 November 2007

Build Systems

The F5 key is not a build process

In my opinion, building software is the most important part of the development process besides developing the actual code. I think this is even more important than bug tracking. To me, a build process must:

  • Be fully automated aka "Push-button builds"
  • Only depend on source (no pre-built tools or libraries thank you very much)
  • Run sanity tests
  • Be able to run torture tests
  • Build a package you can ship to QA or clients
One way to accomplish most of the above goals is to use a build system. My favourite tool in this space is currently SCons. While it isn't nearly as sexy as Boost Jam, and scripts can be quite verbose, it is flexible enough to implement my favourite part of Boost Jam: usage requirements.

Usage requirements are essentially a neat way of saying: If you are going to use this module, then you should use these flags to compile. For example, if I was using static library A to create executable B, A might require me to add -DUSING_LIBA_STATIC=1 to the command line (and will most definitely require some linker flags.) In traditional build systems, this logic would be forced on the client usage in some annoying way:

# pseudo-makefile syntax
app: libA.a main.cpp
$(CC) $(LIBA_CCFLAGS) $(LIBA_LINKFLAGS) main.cpp -o app

Not bad but it can quickly get redundant and complex when the number of libraries grows. With Boost Jam:

exe app : main.cpp /path/to//libA ;

Thats it. Pretty neat eh? This is one feature that I sorely wish existed in SCons. However, it is possible to approximate the above:

def build(env):
env.Require('/path/to/libA')
return env.Program('app','main.cpp')

I just prototyped something like this last night that handled propagated usage requirements. I doubt I will need the full power of Boost Jam usage requirements, but even just being able to have the logic in one place would make life a lot easier for me.

I have yet to decide whether it is a kludge or an elegant hack :-)

No comments: