You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 11 Next »

Introduction 

Navid has been busy setting up a demonstration environment using SCons and the ScienceTools v8r2.

Location of Installation

SCons is installed here at SLAC:  /afs/slac/g/glast/applications/SCons/0.97/bin/scons
There's a copy of SciTools in Navid's area:  /nfs/farm/g/glast/u06/golpa/ST-v8r2-scons/ScienceTools
If you desire to run SCons, please copy the ScienceTools from Navid's area into a place you have write-access.

Interesting Details

There is a top-level SConstruct file which contains configuration/build information to be used "globally".  This includes options for the compilation such as debug and optimization flags and tells SCons the list of packages associated with this project and how to find the SConscript files for each package.  See the Gory Details of the SConstruct file for more information.

Each package contains its own SConscript file which act as SCons' version of CMT's requirements file.  You can see an example for the facilities package further down on this page.  The SConstruct file communicates the location of the SConscript file for each package.

The virjpk subdirectories are not in place or assumed in this organization.  There is a note out to Riccardo to check if that arrangement is acceptable to MRStudio.  Doing without the package-tag subdirectories allows us to utilize CVS directly for our checkouts, rather than devising a way to recreate CMT checkouts.  Using this organization, users would obtain code and build via the following commands:
cvs co -r v8r2 ScienceTools
cd ScienceTools
scons

Externals

Gory Details of the SConstruct file

The SConstruct file begins by setting up the global environment for the build.  This is done by updating SCons' environment variable "baseEnv".  Here are the contents of the SConstruct file:

import os,platform
#########################
#   Global Environment  #
#########################
baseEnv = Environment();
if ARGUMENTS.get('debug',0):
        baseEnv.Append(CCFLAGS = "-g")
if ARGUMENTS.get('optimized',0):
        baseEnv.Append(CCFLAGS = "-O2")
if ARGUMENTS.get('CC',0):
        baseEnv.Replace(CC = ARGUMENTS.get('CC'))
if ARGUMENTS.get('CXX',0):
        baseEnv.Replace(CXX = ARGUMENTS.get('CXX'))
if ARGUMENTS.get('CCFLAGS',0):
        baseEnv.Append(CCFLAGS = ARGUMENTS.get('CCFLAGS'))
if ARGUMENTS.get('CXXFLAGS',0):
        baseEnv.Append(CXXFLAGS = ARGUMENTS.get('CXXFLAGS'))
helpString = """
Usage:
        scons [target] [compile options]
Targets:
        Default:                Build release binaries and libraries
        test:                   Build test binaries and required libraries
        binaries:               Build release binaries and required libraries
        libraries:              Build all libraries

Compile Options:
        Optimized:              Set to 1 to compile with optimization. Default 0.
        CC:                     Set to the compiler to use for C source code.
        CXX:                    Set to the compiler to use for C++ source code.
        CCFLAGS:                Set to additional flags passed to the C compiler.
        CXXFLAGS:               Set to additional flags passed to the C++ compiler.
"""
Export('baseEnv')

The next section pertains to externals:

#########################
#  External Libraries   #
#########################
helpString += SConscript('externals.scons')

Help(helpString)

The following sets up the directories which will contain the libraries, binaries, and include files: 

#########################
#  Project Environment  #
#########################
libDir = os.path.join(os.path.abspath('.'),'lib')
binDir = os.path.join(os.path.abspath('.'),'bin')
incDir = os.path.join(os.path.abspath('.'),'include')
testDir = binDir
baseEnv.Append(LIBPATH = [libDir])
baseEnv.Append(CPPPATH = [incDir])
baseEnv.Append(CPPPATH = ['.'])
baseEnv.Append(CPPPATH = ['src'])

Export('libDir','binDir','incDir','testDir')

Create a list of packages for this SCons project and define the registerObject function which will be used by each package in their respective SConscript file to define the list of libraries, applications, public headers, etc that are desired for the global compilation.

packages = [
  'tip',
  'facilities',
  'astro',
  'Likelihood',
  'st_app',
  'hoops',
  'st_graph',
  'st_stream',
  'dataSubselector',
  'st_facilities',
  'evtbin',
  'f2c',
  'optimizers',
  'xmlBase',
  'irfs',
  'map_tools',
  'burstFit',
  'catalogAccess',
  'celestialSources',
  'flux',
  'fitsGen',
  'likeGui',
  'observationSim',
  'periodSearch',
  'pulsarDb',
  'pulsePhase',
  'rspgen',
  'sane',
  'sourceIdentify',
  'timeSystem',
  'embed_python'
]

def registerObjects(package, objects):
        libs = []
        bins = []
        incs = []
        test = []
        if objects != None and package != None:
                if 'libraries' in objects:
                        libs = baseEnv.Install(libDir, objects['libraries'])
                if 'binaries' in objects:
                        bins = baseEnv.Install(binDir, objects['binaries'])
                if 'includes' in objects:
                        incs = baseEnv.Install(os.path.join(incDir,package), objects['includes'])
                if 'testApps' in objects:
                        test = baseEnv.Install(testDir, objects['testApps'])
                baseEnv.Alias(package, libs + bins + incs)
                baseEnv.Default(libs + bins + incs)
                baseEnv.Alias('libraries', libs)
                baseEnv.Alias('binaries', bins)
                baseEnv.Alias('test', test)

Export('registerObjects')

Lastly we tell SCons where to find the SConscript file for each package:

for pkg in packages:
        SConscript(os.path.join(pkg,"SConscript"))

An Example SConscript File

Here is the SConscript file for the facilities package.  Each package will have its own SConscript file, similar to the requirements file from CMT: 

import glob,os

Import('baseEnv')
Import('registerObjects')
env = baseEnv.Copy()

facilitiesLib = env.StaticLibrary('facilities', glob.glob(os.path.join('src','*.cxx')))

This line creates a variable called facilitiesList.  It says to create a static library called facilities and these are the source files
registerObjects('facilities',

Unknown macro: { 'libraries'}

 

)

We set up the compiler options, macros, etc in a SCons "environment".  In this case, the environment is imported from "baseEnv" which is set up in the SConstruct and the external.scons files at the top-level of ScienceTools.  It is imperative that the SConscript files COPY the baseEnv, and update the copy, rather than updating baseEnv directly.  The reason is that any changes to baseEnv will propagate to all packages, even retroactively.

The registerObjects function is called to setup the items we wish to submit from facilities to be part of the global build.  This is all just preparation, no building it done yet, we are just storing the information needed by scons to perform the build.  The first argument is what the package is called, in this case, "facilities".  The second argument is a hash of arrays.  The hash name is the type of object you are registering (libraries, include files, binaries, test apps, etc.), and the value of the hash is a list of those objects.

After all the SConscript files have been called, and registerObjects updated for each package, scons is ready to compute the dependencies and start the build in the correct order.

Interesting Python filesystem manipulation routines

os.path.join joins 'src' and '*.cxx' together in the correct way ie \ for windows and / for linux
glob.glob then takes the src/*.cxx and gets a list of files that match that pattern

  • No labels