Please note:The SCons wiki is now restored from the attack in March 2013. All old passwords have been invalidated. Please reset your password if you have an account. If you note missing pages, please report them to webmaster@scons.org. Also, new account creation is currently disabled due to an ongoing spam flood (2013/08/27).

Introduction

This page describes one way to create a modular build that can support multiple platforms and support building multiple setups at a time. This is one way, not necessarily the best way.

Supporting multiple builds

To support multiple builds at a time, each build can be separated into a setup file. One or more files can be specified by the SETUP on the command line. If none are specified only the command line options are used:

   1 import os
   2 import glob
   3 
   4 setup = ARGUMENTS.get('SETUP', None)
   5 if setup is None:
   6   setup = [ None ] # If not setup specified, do one pass only with ARGUMENTS
   7 else:
   8   parts = setup.split(os.pathsep)
   9   setup = []
  10   for part in parts:
  11     setup.extend(glob.glob(part))
  12   if len(setup) == 0:
  13     print 'SETUP specified but no matching setup files found'
  14     Exit()

Separating the configuration

To simplify the configuration of the environments and reduce the amount of conditional tests, each supported platform,compiler,etc is separated into a configuration module. This configuration is specified by the CONFIG option and loaded dynamically. It contains certain useful functions for creating the options, environment, and configure tests, as well as preparing the environment with any needed variables and flags. Before creating this configuration, it still needs to be detected from the setup file or command line:

   1 def DetectConfig(file, args):
   2   import sys
   3 
   4   dummyvars = Variables(file, args)
   5   dummyvars.Add('CONFIG')
   6   dummyenv = Environment(options=dummyopts, TOOLS=[])
   7 
   8   name = dummyenv['CONFIG']
   9   if not name:
  10     return None
  11 
  12   # Dynamically load the configuration module
  13   name = 'build.config.' + name
  14   __import__(name, dict(), dict())
  15 
  16   return sys.modules[name]

Then, for each setup file create the options, build environment, tests, etc.

   1 for setupfile in setup:
   2 
   3   config = DetectConfig(setupfile, ARGUMENTS)
   4   if config is None:
   5     # Raise error, or log error and continue with next setup
   6     continue
   7 
   8   # Create variables, first config-specific then the global ones
   9   vars = config.Variables(setupfile, ARGUMENTS)
  10 
  11   vars.Add(...)
  12 
  13   # Create environment add do config-specific initialization from variables
  14   # such as loading tools, setting build options, build flags, etc.  Then do
  15   # and global setup needed
  16   env = config.Environment(vars)
  17 
  18   ...
  19   ...
  20 
  21   # Running configure tests by getting them from the config module, passing in any extra
  22   # tests needed globaly.  The config module will run some config-specific tests and then
  23   # return the Configure object for any more tests needed
  24   conf = config.Configure(env, extra_tests)
  25 
  26   conf.Check...
  27 
  28   env = conf.Finish()
  29 
  30   Export('env', 'config')

The config module's Environment and Configure functions may also add some helper methods to the base environment. It should use env.AddMethod and not AddMethod so that the method added will get rebound for any cloned environment. In addition other files may also add some helper methods.

Platform-specific code

The config module can set up into the environment which platform-specific code directory should be build, so the build system can then use that directory to build the platform specfic code library, and add a method for the later code to use that library:

src/SConscript:

   1 Import('*')
   2 
   3 # First build platform-dependent code library
   4 # The SConscript file will add a method to the base environment 'SetupPlatformLibrary'
   5 SConscript(env['PLATFORMDIR'] + '/SConscript')
   6 
   7 # Next prepare and build main code
   8 sources = Glob('*.c')
   9 
  10 lenv = env.Clone()
  11 lenv.SetupPlatformLibrary()
  12 
  13 program = lenv.Program(sources)
  14 
  15 # Remember the target for later packaging in the base environment
  16 env['BUILDTARGETS']['program'] = program

ModularExample (last edited 2009-09-16 11:43:03 by IanVaughan)