senfutil helps setting up projects which utilize SENF. It will configure all necessary compiler and linker options and additionally sets up some useful defaults and utilities.
senfutil really serves three roles
senfutil you need to do two things:
SConstruct filesenfutil.py to site_scons
SConstruct file
import senfutil env = Environment() senfutil.SetupForSENF(env) senfutil.DefaultOptions(env) env.SetDefault( PROJECTNAME = 'Example project', PROJECTEMAIL = 'developer@domain.com', DOCLINKS = [ ('Homepage', 'http://www.domain.com') ] ) sources, tests = senfutil.Glob(env, exclude=['main.cc']) objects = env.Object(sources) example = env.Program('example', objects + ['main.cc']) test = env.BoostUnitTest('test', objects + tests) env.Default(example) senfutil.Doxygen(env) senfutil.CleanGlob('all', [ '*~', '#*#' ])
This simple sample already enables a lot of functionality:
$ scons
$ scons doc test
$ scons -c all
$ scons CXXFLAGS+=-Wextra
senfutil.py is not on the standard python or SCons path, some extra steps are needed to find it.
sys.path before importing senfutil:
import sys sys.path.extend(('/usr/local/lib/senf/site_scons', '/usr/lib/senf/site_scons')) import senfutil
site_scons/senfutil.py into your project. This script will search for site_scons/senfutil.py in a list of directories and then load the real senfutil.py on top of itself. The directories searched include: the current directory and all parents, subdirectories named senf/, Senf/ or SENF/ thereof, and /usr/local/lib/senf/ and /usr/lib/senf/
def findsenf(sysdirs = ('/usr/local/lib/senf','/usr/lib/senf'), subdirs = ('', 'senf', 'Senf', 'SENF')): import os, itertools def ancestors(d): p = d.split(os.path.sep) return (os.path.join(p[0]+os.path.sep,*p[1:i]) for i in range(len(p),0,-1)) for d in itertools.chain(ancestors(os.getcwd()),sysdirs): for s in subdirs: py = os.path.join(d,s,'site_scons/senfutil.py') if os.path.exists(py) and not os.path.samefile(py,__file__): return py raise ImportError, 'senfutil not found' # replace module with real senfutil import sys, os __file__ = findsenf() sys.path.append(os.path.dirname(__file__)) del sys, os, findsenf execfile(__file__, locals(), globals())
senfutil utility for SCons helps setting up a project to compile against SENF:
senfutil adds all necessary libraries to link againstsenfutil will set necessary compile options.senfutil supports normal, debug and final project build optionssenfutil adds support for Boost unit testssenfutil implements a very simple to use enhanced doxygen build with SENF symbol cross-referencesenfutil allows specifying variables on the scons command linesenfutil supports more readable compile-time SENF loglevel configurationimport sys sys.path.extend(('senf/site_scons','/usr/lib/senf/site_scons')) import glob, senfutil env = Environment() senfutil.SetupForSENF(env) # senfutil.DefaultOptions(env) # Set or change SCons environment variables with env.Append, env.Replace or env.SetDefault env.Append( CXXFLAGS = [ '-Wall', '-Woverloaded-virtual' ], CXXFLAGS_final = [ '-O2' ], CXXFLAGS_normal = [ '-O0', '-g' ], CXXFLAGS_debug = [ '$CXXFLAGS_normal' ], LINKFLAGS_normal = [ '-Wl,-S' ], LOGLEVELS_debug = [ 'senf::log::Debug||VERBOSE' ], PROJECTNAME = 'Example project', PROJECTEMAIL = 'developer@domain.com', DOCLINKS = [ ('Homepage', 'http://www.domain.com') ] ) # Create a list of sources and tests. Sources are all *.cc files, test are *.test.cc sources, tests = senfutil.Glob(env, exclude=['main.cc'] ) # Build objects from sources objects = env.Object(sources) # Build main binary env.Default( env.Program( target='example', source=objects + ['main.cc'] ) ) # Build a boost unit-test from additional test sources env.BoostUnitTest( 'test', source=objects + tests) # Build a documentation, autogenerates a Doxyfile senfutil.Doxygen(env)
This example builds a simple binary from a number of source files (all '.cc' files). It links against the SENF library and automatically sets all the correct compiler options using senfutil.SetupForSENF( env ).
This script automatically uses a SENF installation either symlinked or imported into the current project in directory 'senf' or, if this directory does not exist, a globally installed SENF.
senfutil supports the debug=1 or final=1 build options. These parameters select one of the build configurations 'debug', 'normal' or 'final'. The following variables are supported each with separate values for all three configurations:
CXXFLAGSCPPDEFINESLINKFLAGSLOGLEVELSsenfutil will detect the type of SENF library used (final or not) and set the correct compile options.
LOGLEVELS (and it's build configuration specific variants) may be set. This variable will be parsed and converted into the correct SENF_LOG_CONF definition. The LOGLEVELS Syntax is
senf::log::Debug) and level is the loglevel. There must be no whitespace in a single specification, multiple specifications are either specified using an array or separated with whitespace.
senfutil.DefaultOptions(env) is provided. This function is identical to:
senfutil.DefaultOptions(env) =>
env.Append(
CXXFLAGS = [ '-Wall', '-Woverloaded-virtual' ],
CXXFLAGS_final = [ '-O2' ],
CXXFLAGS_normal = [ '-O0', '-g' ],
CXXFLAGS_debug = [ '$CXXFLAGS_normal' ],
LINKFLAGS_normal = [ '-Wl,-S' ],
)
Thus above example can be simplified to
import sys sys.path.extend(('senf/site_scons','/usr/lib/senf/site_scons')) import glob, senfutil env = Environment() senfutil.SetupForSENF(env) senfutil.DefaultOptions(env) env.Append( LOGLEVELS_debug = [ 'senf::log::Debug||VERBOSE' ], PROJECTNAME = 'Example project', PROJECTEMAIL = 'developer@domain.com', DOCLINKS = [ ('Homepage', 'http://www.domain.com') ] ) sources, tests = senfutil.Glob(env, exclude=['main.cc'] ) objects = env.Object(sources) env.Default( env.Program( target='example', source=objects + ['main.cc'] ) ) env.BoostUnitTest( 'test', source=objects + tests) senfutil.Doxygen(env)
# Generate list of sources and tests (sources=*.cc, tests=*.test.cc) extra_sources = ['main.cc'] sources, tests = senfutil.Glob(env, exclude=extra_sources) # Build object files needed for both main target and unit tests objects = env.Object(sources) # Build main target, e.g. a Binary with additional sources which are not part of the unit test env.Program('example', objects+extra_sources) # Build unit tests including additional test sources env.BoostUnitTest('test', objects+tests)
It is important to exclude the main function from the unit-test build since the boost unit test library provides it's own.
senfutil.Doxygen utility
env.Append( PROJECTNAME = "Example project", PROJECTEMAIL = "coder@example.com", COPYRIGHT = "The Master Coders", DOCLINKS = [ ('Homeage', 'http://www.example.com') ], REVISION = 'r'+os.popen('svnversion').read().strip().lower() ) senfutil.Doxygen(env)
The senfutil.Doxygen utility autogenerates a Doxyfile.
The utility will search for a SENF documentation in the senfdoc and senf subdirectories as well as via the senfutil module directory and some other standard locations. If SENF documentation is found, the SENF tagfiles will automatically be added. Links will be resolved to the documentation found.
senfutil.Doxygen takes some additional optional keyword arguments:
doxyheader: Path of an alternative HTML headerdoxyfooter: Path of an alternative HTML footerdoxycss: Path on an alternative CSS filemydoxyfile: If set to True, don't generate or clean the Doxyfile\
senfdoc_path: List of additional directories to search for SENF documentationsenfutil automatically parses SCons command line arguments into the SCons build environment. This allows specifying any parameter on the command line:
$ scons CXX=myg++ CXXFLAGS+=-mtune=geodeYou may either set variables unconditionally using '=' or append values to the end of a list using '+='.