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).

See also SconsProjects for lots more real-life SCons examples.

SConstruct:

import SCons.Script
import os
import fnmatch

##-------------------------------------------------
# Use:
#   scons projectx [mode=debug]
#        - defaults to mode=release
##-------------------------------------------------

#-- lists of projects for various groupings
gFrozenDirProjects = []
gSrcDirProjects = []
gMiscDownloadsDirProjects = []

gDownloadsProjects = []
gMiscDownloadsProjects = []
gNeuralnetsProjects = []
gOtherProjects = []   #unclassified
#taskdefs
#snippets

##-------------------------------------------------
#-- Function definitions here
def GetConscriptPath(d, project):
    return '../' + d + '/' + project + '/sconscript'

def DoSrc(project, mode, group = gOtherProjects):
    gSrcDirProjects.append(project)
    group.append(project)
    SConscript(GetConscriptPath('src', project), exports='project')

def DoMiscVC7(project, mode, group = gOtherProjects):
    gSrcDirProjects.append(project)
    group.append(project)
    SConscript(GetConscriptPath('miscdownloads', project), exports='project')

def DoMiscVC6(project, mode, group = gOtherProjects):
    gSrcDirProjects.append(project)
    group.append(project)
    SConscript(GetConscriptPath('miscdownloads', project), exports='project')

def DoSrcVC7(project, mode, group = gOtherProjects):
    gSrcDirProjects.append(project)
    group.append(project)
    SConscript(GetConscriptPath('src', project), exports='project')

def DoSrcVC6(project, mode, group = gOtherProjects):
    gSrcDirProjects.append(project)
    group.append(project)
    SConscript(GetConscriptPath('src', project), exports='project')

def DoFrozen(project, mode, group = gOtherProjects):
    gFrozenDirProjects.append(project)
    group.append(project)
    SConscript(GetConscriptPath('frozen', project), build_dir= dev.GetBuildDir(project, mode), exports='project')

def DoFrozenVC7(project, mode, group = gOtherProjects):
    gFrozenDirProjects.append(project)
    group.append(project)
    SConscript(GetConscriptPath('frozen', project), exports='project')

def DoFrozenVC6(project, mode, group = gOtherProjects):
    gFrozenDirProjects.append(project)
    group.append(project)
    SConscript(GetConscriptPath('frozen', project), exports='project')

##-------------------------------------------------
#-- Dev Helper Class
class Dev(Environment):
   #-- get build directory
   def GetBuildDir(self, project, mode):
      return os.path.join('\projects', mode, project)

   #-- Get Source files from the source node using patterns as
   def GetSourceFiles(self, patterns=None):
      files = []
      if patterns is None:
         patterns=['*'+self["CXXFILESUFFIX"],'*'+self["CFILESUFFIX"], '*'+self["QT_UISUFFIX"]]
      for file in os.listdir(self.Dir('.').srcnode().abspath):
          for pattern in patterns:
             if fnmatch.fnmatchcase(file, pattern):
                 files.append(file)
      return files

   def SetAliases(self, e, projname, tgt):
       e.Alias(projname, tgt)
       e.Alias(projname.lower(), tgt)

   #-- set up a VC7 project to be built
   def VC7(self, localenv, project, slnname=None, exename=None, exetype=None):
      if slnname is None:  slnname = project
      if exename is None:  exename = project
      if exetype is None:  exetype = 'exe'
      localenv.PrependENVPath('PATH', 'E:/Program Files/Microsoft Visual Studio .NET 2003/Common7/IDE')
      bdir = self.GetBuildDir(project, mode)
      slnpath = slnname + '.sln'
      projpath =  os.path.join(bdir, exename + '.' + exetype)
      localenv.Tool('msvs')
      if mode == 'debug':
         cmd = localenv.Command(projpath, slnpath, 'devenv.exe /rebuild Debug $SOURCE')
      else:
         cmd = localenv.Command(projpath, slnpath, 'devenv.exe /rebuild Release $SOURCE')
      localenv.Clean(cmd, self.GetBuildDir(project, mode))
      return cmd

   #-- set up a VC6 project to be built
   #-- assumes:
   #--      - .dsp is in the source dir
   #--      - build_dir is not used
   #--      - exetype is one of exe, dll, lib
   def VC6(self, localenv, project, dspname=None, exename=None, exetype=None):
      if dspname is None:  dspname = project
      if exename is None:  exename = project
      if exetype is None:  exetype = 'exe'
      localenv.PrependENVPath('PATH', 'E:/Program Files/Microsoft Visual Studio/Common/MSDev98/Bin')
      bdir = self.GetBuildDir(project, mode)
      dsppath = dspname + '.dsp'
      projpath =  os.path.join(bdir, exename + '.' + exetype)
      localenv.Tool('msvc')
      if mode == 'debug':
         cmd = localenv.Command(projpath, dsppath, 'msdev.exe $SOURCE /MAKE "all - Win32 Debug" /NORECURSE /BUILD')
      else:
         cmd = localenv.Command(projpath, dsppath, 'msdev.exe $SOURCE /MAKE "all - Win32 Release" /NORECURSE /BUILD')
      localenv.Clean(cmd, bdir)
      return cmd

   def VC6_dsw(dev, localenv, project, dspname=None, exename=None, exetype=None):
      if dspname is None:  dspname = project
      if exename is None:  exename = project
      if exetype is None:  exetype = 'exe'
      localenv.PrependENVPath('PATH', 'E:/Program Files/Microsoft Visual Studio/Common/MSDev98/Bin')
      bdir = dev.GetBuildDir(project, mode)
      dsppath = dspname + '.dsw'
      projpath =  os.path.join(bdir, exename + '.' + exetype)
      localenv.Tool('msvc')
      if mode == 'debug':
         cmd = localenv.Command(projpath, dsppath, 'msdev.exe $SOURCE /MAKE "all - Win32 Debug" /NORECURSE /BUILD')
      else:
         cmd = localenv.Command(projpath, dsppath, 'msdev.exe $SOURCE /MAKE "all - Win32 Release" /NORECURSE /BUILD')
      localenv.Clean(cmd, bdir)
      return cmd

##-------------------------------------------------
#--
# prevent accidental building of everything;
# - to build everything use 'scons.py .'
Default(None)

##-------------------------------------------------
#- check compilation mode: 'debug' or 'release' only
mode = ARGUMENTS.get('mode', 'release')
if not (mode in ['debug', 'release']):
   print "Error: expected 'debug' or 'release', found: " + mode
   Exit(1)

print '**** Compiling in ' + mode + ' mode...'

env = Environment()
dev = Dev()
Export('env', 'dev', 'mode')

#put all .sconsign files in one place
env.SConsignFile()

#-- frozen projects
#astyle
DoFrozenVC7('ClassesInC', mode, gDownloadsProjects)
#com
DoFrozenVC7('DbDiff', mode, gDownloadsProjects)
#devutils
DoFrozenVC7('ExternalScrollbarListBox', mode, gDownloadsProjects)
DoFrozenVC7('Fave2Xml', mode, gDownloadsProjects)
#gensnippets
DoFrozenVC7('GenWeb', mode)
#genwebcore
DoFrozenVC7('jBackup', mode, gDownloadsProjects)
DoFrozenVC6('jComHeap', mode, gDownloadsProjects)
#jcomheap_test
DoFrozenVC7('jConfigureVC', mode, gDownloadsProjects)
DoFrozenVC7('jContinuousBackup', mode, gDownloadsProjects)
#jdump
DoFrozenVC7('jEnvEditor', mode, gDownloadsProjects)
DoFrozenVC7('jMirror', mode, gDownloadsProjects)
DoFrozenVC7('jPlayer', mode, gDownloadsProjects)
#jplayer - VC6
#jqwiki
DoFrozenVC7('jWebTest', mode, gDownloadsProjects)
#jwiki
DoFrozenVC7('MD5', mode, gDownloadsProjects)
#msdev
#perlvcaddin
DoFrozenVC7('RegDiff', mode, gDownloadsProjects)
DoFrozenVC7('ResumeMaster', mode)
#resumemastercore
DoFrozenVC7('SimpleXml', mode, gDownloadsProjects)
#sourcemonitor
DoFrozenVC7('SpreadSheet', mode, gDownloadsProjects)
#todo: resolve subdir name is 'ut', DoFrozenVC7('utx', mode, gDownloadsProjects)
DoFrozenVC7('W32Chat', mode, gDownloadsProjects)
#winmisc
#xml2tree

#-- miscdownloads
DoMiscVC6('BuildStamp', mode, gMiscDownloadsProjects)
DoMiscVC6('CIncl', mode, gMiscDownloadsProjects)
DoMiscVC7('KillProc', mode, gMiscDownloadsProjects)
DoMiscVC7('LogoffNicely', mode, gMiscDownloadsDirProjects)
DoMiscVC7('WordSearch', mode, gMiscDownloadsDirProjects)
DoMiscVC6('TestFsm', mode, gMiscDownloadsProjects)
DoMiscVC6('TestMsgLoop', mode, gMiscDownloadsProjects)
#OtherUtilities

#-- src projects
DoSrcVC6('CppWiki', mode)
DoSrcVC6('jUtAsserter', mode, gDownloadsProjects)
DoSrcVC6('jWebServer', mode, gDownloadsProjects)

#-- neuralnets
#-- todo:
#jneuralnetcore -- doesn't exist yet
#todo: resolve directory structure DoSrcVC7('jNeuralNets', mode, gNeuralnetsProjects)
DoSrc('pso', mode, gNeuralnetsProjects)


#--todo:
#jWebServer
#jsnippets
#jtaskdefs

# <!--missing java compiles: utjava, fsmgen, jwiki -->
# <!--missing cpp compiles: perlvcaddin, sourcemonitor -->

#-- set up some other aliases for compilation convenience
env.Alias('frozen', gFrozenDirProjects)
env.Alias('src', gSrcDirProjects)
env.Alias('misc', gMiscDownloadsDirProjects)

env.Alias('downloads', gDownloadsProjects)
env.Alias('miscdownloads', gMiscDownloadsProjects)
env.Alias('neuralnets', gNeuralnetsProjects)
env.Alias('other', gOtherProjects)

env.Alias('all', ['downloads','miscdownloads', 'neuralnets', 'other'])
env.Alias('universe', ['all','frozen', 'src', 'misc'])

# <target name='compile_all' depends='init,
#         compile_downloads,
#         compile_miscdownloads,
#         compile_snippets,
#         compile_taskdefs,
#         compile_neuralnets'
# />


#-- end of compilation aliases


#-- targets
def GetFiles(dir, includes, excludes=None):
      files = []
      for file in os.listdir(Dir(dir).srcnode().abspath):
          for pattern in includes:
             if fnmatch.fnmatchcase(file, pattern):
                 files.append(file)
      if not excludes is None:
        for file in files:
           for pattern in excludes:
              if fnmatch.fnmatchcase(file, pattern):
                  files.remove(file)
      return files

def InstallFiles(env, dest_dir, src_dir, includes, excludes):
   src = GetFiles(src_dir, includes, excludes)
   #print "x=" + `src`
   dest = env.Dir(dest_dir)
   for f in src:
      env.Install(dest, src_dir + '/' + f)
   return dest

def InstallTree(env, dest_dir, src_dir, includes, excludes):
    destnode = env.Dir(dest_dir)
    dirs = []
    dirs.append(src_dir)
    while len(dirs) > 0:
      currdir = dirs.pop(0)
      currdestdir = dest_dir + currdir[len(src_dir):]
      #print "c=" + currdestdir
      flist = os.listdir(currdir)
      for currfile in flist:
         currpath = currdir + '/' + currfile
         match = 0
         for pattern in includes:
            if fnmatch.fnmatchcase(currfile, pattern):
              match = 1
         if (match == 1):
            for pattern in excludes:
               if fnmatch.fnmatchcase(currfile, pattern):
                  match = 0
            if (match == 1):
               if (os.path.isdir(currpath)):
                  #print "d=" + currpath
                  dirs.append(currpath)
               else:
                  #print "f=" + currpath
                  env.Install(currdestdir, currpath)
      #print "x= len=" + str(len(dirs))
    return destnode

#-- source dirs
arrizza_websrc_root = '/projects/websrc/arrizza'
arrizza_resume_root = '/MyStuff/myresume'
frozen_root = '/projects/frozen'

#-- staging local dirs
arrizza_local_root       = '/projects/staging/arrizza.com'
arrizza_local_html       = arrizza_local_root + '/html'
arrizza_local_cgibin     = arrizza_local_root + '/cgi-bin'
arrizza_local_private    = arrizza_local_html + '/private'
arrizza_local_links      = arrizza_local_html + '/links'
arrizza_local_snippets   = arrizza_local_html + '/snippets'
arrizza_local_taskdefs   = arrizza_local_html + '/taskdefs'
arrizza_local_resume     = arrizza_local_html + '/resume'
arrizza_local_downloads  = arrizza_local_html + '/downloads'
arrizza_local_miscdownloads = arrizza_local_html + '/miscdownloads'
arrizza_local_neuralnets = arrizza_local_html + '/neuralnets'
arrizza_local_articles   = arrizza_local_html + '/articles'
arrizza_local_testpages  = arrizza_local_html + '/testpages'
arrizza_local_jwikipriv  = arrizza_local_cgibin + '/jwikipriv'
arrizza_local_jwikipub   = arrizza_local_cgibin + '/jwikipub'
arrizza_local_jwikitest  = arrizza_local_cgibin + '/jwikitest'
arrizza_local_ubu        = arrizza_local_cgibin + '/ubu'

#------------ MAIN ---------------------
env.Alias('prepare_main', [
     InstallFiles(env,
        dest_dir = arrizza_local_root,
        src_dir  = arrizza_websrc_root + '/main',
        includes = ['*'],
        excludes = ['.svn']),
     InstallFiles(env,
        dest_dir = arrizza_local_html,
        src_dir  = arrizza_websrc_root + '/htmlmain',
        includes = ['*'],
        excludes = ['.svn'])
      ])
env.Alias('main', ['prepare_main', 'send_main'])

#------------ TESTPAGES ---------------------
env.Alias('prepare_testpages', [
     InstallFiles(env,
        dest_dir = arrizza_local_testpages,
        src_dir  = arrizza_websrc_root + '/testpages',
        includes = ['*'],
        excludes = ['.svn'])
      ])
env.Alias('testpages', ['prepare_testpages', 'send_testpages'])

#------------ CGI MAIN ---------------------
env.Alias('prepare_cgimain', [
     InstallFiles(env,
        dest_dir = arrizza_local_cgibin,
        src_dir  = arrizza_websrc_root + '/cgi-bin',
        includes = ['*'],
        excludes = ['.svn'])
      ])
env.Alias('cgimain', ['prepare_cgimain', 'send_cgimain'])

#------------ PRIVATE ---------------------
env.Alias('prepare_private', [
     InstallFiles(env,
        dest_dir = arrizza_local_private,
        src_dir  = arrizza_websrc_root + '/private',
        includes = ['*'],
        excludes = ['.svn'])
      ])
env.Alias('private', ['prepare_private', 'send_private'])

#------------ ARTICLES ---------------------
env.Alias('prepare_articles', [
     InstallFiles(env,
        dest_dir = arrizza_local_articles,
        src_dir  = arrizza_websrc_root + '/articles',
        includes = ['*'],
        excludes = ['.svn'])
      ])
env.Alias('articles', ['prepare_articles', 'send_articles'])

#------------ RESUME ---------------------
env.Alias('prepare_resume', [
     env.InstallAs(arrizza_local_resume + '/johnarrizzawebresume.txt', arrizza_resume_root + '/JohnArrizzawebResume.txt'),
     env.InstallAs(arrizza_local_resume + '/johnarrizzaresume.txt',    arrizza_resume_root + '/JohnArrizzawebResume.txt'),
     env.InstallAs(arrizza_local_resume + '/johnarrizzawebresume.doc', arrizza_resume_root + '/JohnArrizzawebResume.doc'),
     env.InstallAs(arrizza_local_resume + '/johnarrizzaresume.doc',    arrizza_resume_root + '/JohnArrizzawebResume.doc'),
     env.Install(arrizza_local_resume, arrizza_resume_root + '/resume.html'),
     env.Install(arrizza_local_resume, arrizza_resume_root + '/uofccoatofarms.jpg'),
     InstallFiles(env,
        dest_dir = arrizza_local_resume,
        src_dir  = arrizza_websrc_root + '/resume',
        includes = ['*'],
        excludes = ['.svn'])
      ])
env.Alias('resume', ['prepare_resume', 'send_resume'])

#------------ LINKS ---------------------
env.Alias('prepare_links', [
     env.Install(arrizza_local_links, frozen_root + '/fave2xml/links.html'),
      ])
env.Alias('links', ['prepare_links', 'send_links'])

#------------ UBU ---------------------
env.Alias('prepare_ubu', [
     InstallTree(env,
        dest_dir = arrizza_local_ubu,
        src_dir  = arrizza_websrc_root + '/ubu',
        includes = ['*'],
        excludes = ['.svn', '*.pag', '*.log'])
      ])
env.Alias('ubu', ['prepare_ubu', 'send_ubu'])

#------------ jwiki ---------------------
#  locdir: local staging directory
#  srcdir: directory under where extra stuff is held
#  cgifile: filename of the cgifile...
#def gather_jwiki(locdir, srcdir, cgifile):

# <delete dir='${locdir}' />
# <mkdir dir='${locdir}' />
# <!-- copy the base code -->
# <copy todir='${locdir}' preservelastmodified='yes' overwrite='true'>
# <fileset dir='${frozendir}/jqwiki' includes='**/' excludes='db/**'/>
# </copy>
# <!-- overwrite with extra stuff -->
# <copy todir='${locdir}' preservelastmodified='yes' overwrite='true'>
# <fileset dir='${srcdir}' includes='**/' excludes='db/**'/>
# </copy>
# <delete file='${locdir}/qwiki.cgi' />
# <delete file='${locdir}/jqwiki.html' />
# <delete file='${locdir}/jqwiki.cgi' />
# <delete file='${locdir}/jqwiki.cpr' />
# <delete file='${locdir}/jqwiki.PRJ' />
# <delete file='${locdir}/bin/bakit.bat' />
# <delete file='${locdir}/bin/test.bat' />
# <move file='${locdir}/${cgifile}' tofile='${local.cgibin}/${cgifile}' />


#------------ jwiki ---------------------
# <target name='gather_jwikipub' depends='init'>
# <antcall target="gather_jwiki">
# <param name='locdir' value='${local.jwikipub}'/>
# <param name='srcdir' value='${arrizza.websrc}/jwikipub'/>
# <param name='cgifile' value='pub'/>
# </antcall>
# </target>

# env.Alias('prepare_jwikipub', [
#      InstallFiles(env,
#         dest_dir = arrizza_local_articles,
#         src_dir  = arrizza_websrc_root + '/articles',
#         includes = ['*'],
#         excludes = ['.svn'])
#       ])
env.Alias('jwikipub', ['prepare_jwikipub', 'send_jwikipub'])


#-- Overall Aliases
env.Alias('prepare_xpsdorg', ['gather_xpsdorgwiki', 'gather_xpsdorghtml', 'convert_xpsdorg'])
env.Alias('prepare_cgi', ['prepare_cgimain', 'prepare_jwikipub', 'prepare_jwikipriv', 'prepare_ubu'])
env.Alias('prepare_html', ['prepare_main', 'prepare_testpages', 'prepare_private', 'prepare_links', 'prepare_snippets', 'prepare_resume', 'prepare_downloads', 'prepare_miscdownloads', 'prepare_taskdefs', 'prepare_neuralnets', 'prepare_articles'])
env.Alias('prepare_all', ['prepare_html', 'prepare_cgi', 'prepare_xpsdorg'])
env.Alias('publish', ['prepare_all', 'send_all'])

env.Alias('send_html', ['send_main', 'send_testpages', 'send_private', 'send_links', 'send_snippets', 'send_resume', 'send_downloads', 'send_miscdownloads', 'send_taskdefs', 'send_neuralnets', 'send_articles'])
env.Alias('send_cgi', ['send_cgimain', 'send_jwikipub', 'send_jwikipriv', 'send_ubu'])
env.Alias('send_all', ['send_html', 'send_cgi', 'send_xpsdorg'])

sconscripts haven't changed from the last time. Here's a typical one:

Import('env', 'dev', 'project')
localenv = env.Copy()
tgt = dev.VC7(localenv, project)
localenv.Depends(tgt, dev.GetSourceFiles(['*.cpp', '*.h']))
dev.SetAliases(env, project, tgt)

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