SCons Intro: A Sane Software Construction Tool

By Thursday, September 11, 2014 0 , , Permalink 5

If you ever built C/C++ programs, you probably know about Make. But Make has long been broken. Everybody knows that.

SCons is an open source software construction tool – a next generation build tool.

You can think of SCons as an improved, cross-platform substitute for Make. One that also bakes in features from autoconf/automake and ccache.

SCons is my chosen C/C++ software build framework.

This is the first post in a series of SCons posts. In the series I will describe SCons, and analyze its strengths and weaknesses. I also explain how I use it (in DayJob) to build non-trivial software, and explore potential enhancements to optimize my workflow.

I open the series with an introduction to SCons.

What Is SCons?

As mentioned in the intro, SCons is an open source software construction tool, also known as build framework. A software developer uses a build framework to facilitate the process of turning a collection of source files into an executable program.

Technically speaking, it is not required to use any build framework in order to produce working program. It is possible to manually run the compiler and linker commands needed to build a program given its sources.

For instance, here is the eternal C++ Hello World program:

// hello.cpp

#include <iostream>

int main() {
    std::cout << "Hello, World.\n";
    return 0;
}

There is no need for any build framework to build this program. You can build it simply by running g++ hello.cpp -o hello, and get an executable hello program.

Of course, I’m assuming you have the g++ compiler installed, on a UNIX-like system (e.g. Linux, Mac OS X, Windows with Cygwin, etc.).

It’s not difficult to see how this approach doesn’t scale well to non-trivial programs. Programs consisting of multiple inter-dependent source files. Programs that use libraries, 3rd-party and internal. Programs that take hours to build from scratch, such that it is unpleasant to develop without incremental build support.

The original GNU Make tried to solve this by providing a domain specific language (DSL) to describe targets, actions and rules. Rules specify relationships (“the hello program depends on hello.o object file”, “hello.o object file depends on hello.cpp source file”, etc.). Actions are shell commands. This means that as a developer, you are expected to learn both the Make language, and some shell language.

The make approach proved to be useful for small C programs, but quite hectic when it came to big programs. In addition, Make is effectively not cross-platform.

So, SCons is an alternative, next generation, build framework. It was designed to be cross platform from the ground up. It is meant to be easier to use and maintain, more reliable and faster.

SCons is written in Python. The configuration files (Makefile alternatives) are pure Python scripts. SCons exposes a declarative API, used to describe relationships. The developer can write very simple configuration files, using only SCons commands, while having the option to unleash the full power of Python.

Why Is SCons Better Than Make?

Here are a couple of reasons:

  • SO MUCH SIMPLER to use and maintain! No more job security for the person maintaining the Makefiles.
  • Python!
    • You can use a real programming language to solve build problems.
    • Assuming you have Python installed, it’s super easy to install SCons (as easy as apt-get install scons, or even easy_install scons).
  • Reliable, automatic dependency analysis built-in for several languages, with the ability to extend to more languages via user-defined scanners.
  • Built-in support for building programs in many languages, also extensible via user-defined builders.
  • Automatic detection of system build tools across platforms (be it GCC, or Visual Studio).
  • Baked in features from complementing tools like autoconf, automake, cache, as we’ll see.

Show Me the Money

To demonstrate how much simpler SCons is, let’s do the SCons version of building the hello world program.

Same source file as above. We add a SConstruct configuration file:

# SConstruct for "Hello World" CPP program

Program('hello.cpp')

Executing the build is as easy as running scons in a terminal:

itamar@legolas hello-scons $ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o hello.o -c hello.cpp
g++ -o hello hello.o
scons: done building targets.

Of course, as long nothing changes in the source, there’s no need to rebuild anything:

itamar@legolas hello-scons $ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
scons: `.' is up to date.
scons: done building targets.

I won’t blame you if you’re not too impressed by the simplicity of an already simple scenario. But contrast this against the Makefile for the same scenario:

# Makefile for "Hello World" CPP program

CC = g++

EXE = hello
OBJ = ${EXE}.o

${EXE}: ${OBJ}

.PHONY: clean
clean:
    rm -f ${EXE} ${OBJ}
# (note: the indent before rm must be a tab...)

Am I the only one who finds it unintuitive that the only thing this is actually an input to the build process (namely, hello.cpp) is not mentioned in any way?

And all the voodoo that goes into defining a clean target? In SCons you get clean for free:

itamar@legolas hello-scons $ scons -c
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Cleaning targets ...
Removed hello.o
Removed hello
scons: done cleaning targets.

If you need to customize clean behavior – you can. Most of the times, the default behavior in SCons is sufficient.

Anyhow, to be more impressed, you’ll have to see a more elaborate scenario. One that I leave for more advanced posts in the series, so this intro is not too intimidating.

In this example we needed only the SConstruct configuration file. This is where SCons starts processing. In projects with subdirectories, it is customary to have a SConscript file each one. The main SConstruct file would then include the SConscript files from the subdirectories.

Is SCons the Only Solution?

SCons is definitely not the only solution that offers to replace Make (with or without autoconf etc.); There are plenty of alternative build frameworks. Just to name a well known few: Ant, CMake, Maven, MakeIt, (Boost) Jam, Rake, built-in build system in IDEs.

I will not go into a detailed comparison (you can see one from Wikipedia, and another one from the SCons wiki). This is mainly because I have never done the comparative research, and also because it will lengthen this post, and launch a flame war or two.

I will just say a couple of things regarding alternatives:

  • If I was developing Java, I would probably not choose SCons. Maybe Maven, or Gradle, due to more natural integration with popular IDEs.
  • I may not have done detailed research on all options. I chose SCons based on previous experience with Make, a little Ant, a little Boost.Build, and too much IDE-specific systems (Eclipse, Visual Studio).
  • One of my insights: XML is OK for machine-to-machine interactions. Human beings, on the other hand, should never need to read or write XML…
  • Built-in IDE solutions are almost never a good alternative (exception: you write only .Net stuff in Visual Studio).
Human beings should never need to read or write XML.

What About Non-C/C++ Projects?

SCons has built-in support for couple of languages, including: C, C++, D, Java, Fortran, Yacc, Lex, Qt and SWIG, TeX and LaTeX documents.

It can also be extended with user-defined builders to support more languages. You can probably find what you need in the SCons contributed builders wiki page, unless it’s esoteric.

Resources

  1. Official SCons site
  2. Official SCons documentation
  3. SCons user guide
  4. SCons wiki
  5. A nice presentation by Dr Russel Winder

Summary

This was a short introduction to the SCons build framework. I tried to keep it short and simple. Maybe even too simple, so the advantages of using it are not yet clear. But worry not! For future posts in my SCons series will bring enlightenment! The next post will provide a simple C++ example project with SCons build. This simple example will be useful as a reference for future SCons extensions I will describe in the series.

SCons is my chosen C/C++ software build framework.

No Comments Yet.

Leave a Reply