Differences between revisions 4 and 5
Revision 4 as of 2005-05-17 13:41:53
Size: 3876
Editor: 213
Comment: Added #!python
Revision 5 as of 2008-03-12 02:47:11
Size: 3876
Editor: localhost
Comment: converted to 1.6 markup
No differences found!

SconstructMultiple has much redundancy in the Sconscripts and some redundancy in the Sconstruct. Some examples:

  • The list of variables to import/export is replicated in all sconscripts and in the sconstruct
  • the build sequence is done in all the sconscripts
  • the set up of the compile flags is done in all the sconscripts
  • etc.

The new refactored sconstruct/sconscript below simplifies adding a new sub-project tremendously:

  1. cut and paste the sconscript to the new project directory.
  2. add a line env.jDev.Subproject(project) at the bottom of the sconstruct with the sub-project's name

As the project matures, the sconstruct will get more complicated. The Dev class can be extended to handle the new complexity, keeping the sconscripts simple. If the Dev class becomes too large, it can be moved out of the Sconstruct into a separate .py file and/or it can be broken up into smaller classes. The sconscript files on the other hand should remain very simple. In the simple project setup below, the contents don't change at all from sub-project to sub-project.

Here's the new Sconstruct:

   1 from SCons.Script.SConscript import SConsEnvironment
   2 import glob
   3 
   4 #this is our catch-all Dev class
   5 #it keeps track of all the variables and common functions we need
   6 class Dev:
   7   mymode = ''
   8   debugcflags = ''
   9   releasecflags = ''
  10 
  11   #---
  12   # sets up the sconscript file for a given sub-project
  13   def Subproject(self, project):
  14       SConscript(env.jDev.SPath(project), exports=['project'])
  15 
  16   #sets up the build for a given project
  17   def Buildit(self, localenv, project):
  18      buildroot = '../' + env.jDev.mymode
  19      builddir = buildroot + '/' + project
  20      targetpath = builddir + '/' + project
  21 
  22      #append the user's additional compile flags
  23      #assume debugcflags and releasecflags are defined
  24      if self.mymode == 'debug':
  25          localenv.Append(CCFLAGS=self.debugcflags)
  26      else:
  27          localenv.Append(CCFLAGS=self.releasecflags)
  28 
  29      #specify the build directory
  30      localenv.BuildDir(builddir, ".", duplicate=0)
  31 
  32      srclst = map(lambda x: builddir + '/' + x, glob.glob('*.cpp'))
  33      pgm = localenv.Program(targetpath, source=srclst)
  34      env.Alias('all', pgm)  #note: not localenv
  35 
  36   #---- PRIVATE ----
  37 
  38   #---
  39   # return the sconscript path to use
  40   def SPath(self, project):
  41      return project + '/sconscript'
  42 
  43 env = Environment()
  44 
  45 #put all .sconsign files in one place
  46 env.SConsignFile()
  47 
  48 #we can put variables right into the environment, however
  49 #we must watch out for name clashes.
  50 SConsEnvironment.jDev = Dev()
  51 
  52 #get the mode flag from the command line
  53 #default to 'release' if the user didn't specify
  54 env.jDev.mymode = ARGUMENTS.get('mode', 'release')   #holds current mode
  55 
  56 #check if the user has been naughty: only 'debug' or 'release' allowed
  57 if not (env.jDev.mymode in ['debug', 'release']):
  58    print "Error: expected 'debug' or 'release', found: " + env.jDev.mymode
  59    Exit(1)
  60 
  61 #tell the user what we're doing
  62 print '**** Compiling in ' + env.jDev.mymode + ' mode...'
  63 
  64 env.jDev.debugcflags = ['-W1', '-GX', '-EHsc', '-D_DEBUG', '/MDd']   #extra compile flags for debug
  65 env.jDev.releasecflags = ['-O2', '-EHsc', '-DNDEBUG', '/MD']         #extra compile flags for release
  66 
  67 #make sure the sconscripts can get to the variables
  68 #don't need to export anything but 'env'
  69 Export('env')
  70 
  71 #specify all of the sub-projects in the section
  72 env.jDev.Subproject('myprogram')
  73 env.jDev.Subproject('hisprogram')
  74 env.jDev.Subproject('herprogram')

The new Sconstruct is more complicated, but it simplifies all the Sconscripts (they are all the same):

   1 #get environment and project
   2 Import('env', 'project')
   3 localenv = env.Copy()
   4 
   5 #call back to jDev to build the project for us
   6 env.jDev.Buildit(localenv, project)

SconstructMultipleRefactored (last edited 2008-03-12 02:47:11 by localhost)