Wednesday, August 18, 2010

Build Systems in a Rush - A Quick Recipe for SCons (C-Code Compiling)

In general, I like using SCons more than makefiles. Why? Well, the following 3 points are a big drawcard:
  1. It's files are based on Python. So no funking around with yet another ancient/archaic shell language
  2. SCons works nicely (as a 1-step process) on a Windows computer once installed, without needing special shells or whatnot. This practically knocks out CMake (it's a two-step process, which ends up creating makefiles or msvc projectfiles, both of which have their downsides) and standard mingw-makefiles (which I cannot ever seem to get running without using a special msys shell, and/or other arcane invokations) 
  3. Being able to show simplified progress info instead of blurting out compiler commands every time (i.e. "Compiling XYZ" vs "gcc -o afkhaf aghaffoof.c -lfghj -lagfhkja -akfha -Wah -Wajgh -aekfh -laksighf-lajfhjf -alkhaf- lakghaf- -lajigfb -lafgjh..."). Sure, this is doable with makefiles too, but it seems that everytime people do it there, it needs more environment variables to be set. Meanwhile with scons, we can easily turn it on/off with command-line options. No wonder so many people miss and ignore compiler warnings, leading to some very weird bugs in their code (also a factor leading to the issues in a previous post).
Despite this, at times I have resorted to using one of my home-brewed py-scripts to just compile some simple stuff when I've been too lazy to read through the SCons docs to get things done (or when there were some problems which I couldn't fix in time).

Fortunately, this time it didn't happen, so now I think I've finally got a reasonable scons template. The template included here is what I'm using to compile the code for one of my assignments, btw.


Overview
  • This template requires: 1) "SConstruct" (main file), and 2) "SConscript" (one for each 'module'). 
  • It creates an "out of source" build (i.e. none of the typical source-files mixed in with .o's and .exe's garbage)
  • It is intended for C-Code, although C++ can also be compiled like this using some modifications. (IMO, you shouldn't be using that vile language anyways, so getting that working is your problem)
    • This is intended for mingw usage, not msvc. I've already mentioned before my reasons for preferring one over the other, not to mention that this time I needed code that would be ok on the department's Linux computers.
  • To compile, point a console at the root directory of your source files (where SConstruct will live), and type: scons

The Goods...
So, here it is: "SConstruct" (no file extension. Just place this in the root of your source directory)

# SConstruct file for assignment 1
env = Environment(tools = ['mingw'])

# tidy output
if ARGUMENTS.get('VERBOSE'):
    env['CCCOMSTR'] = "Compiling => $TARGET"
    env['LINKCOMSTR'] = "Linking => $TARGET"

# compiler flags
env['CCFLAGS'] = '-Wall -g' + ' -funsigned-char -fno-strict-aliasing'

# 'perform time measurements' option? <---- XXX: use this as a base for adding as many other conditional-compilation parts you need
if ARGUMENTS.get('DOTIME') == "1":
    # add 'MEASURE' flag to compile args
    env['CCFLAGS'] += ' -DMEASURE'

# 'debug' options?
if ARGUMENTS.get('DEBUG') == "1":
    # add 'sorted' flag to compile args
    env['CCFLAGS'] += ' -DDEBUG'

# linker libs
# 'm' here just means 'math' (for gcc)
env['LIBS'] = 'm'

# build the files
Export('env')
SConscript('SConscript', variant_dir='../build', duplicate=0)



You'll also need "SConscript" (no extension again) files. These can reference other SConscript files if need be, but if you need a "buildsystem in a rush", then it's likely that you have a small set of code. So, here are some examples of what your SConscripts could look like here...

1) Only need to compile a single program:
Import('env')

env.Program('bst.c')

2) Need to compile several programs with no overlap
Import('env')

env.Program('bst.c')
env.Program('avl.c')
#... continue this pattern below...

3) Multiple source files to give a single program
Import('env')

env.Program('countWords2', ['countWords2.c', 'wordTable2.c', 'misc.c'])

Hopefully this was a useful overview of some SCons recipes to get your small batches of code compiling. Someday I shall write a more comprehensive overview, but for now, this is just a little handy guide.

No comments:

Post a Comment