#-*-python-*- # SCons file to create Environment() for building RAT applications. import os import subprocess from buildhelp import RATROOT, ROOTARCH, testenv, PSQLENVFILE def rat_path(*args): """ Returns the canonical path to join(RATROOT, *args) by eliminating any symbolic links encountered in the path. Without this, scons will rebuild everything when compiling over NFS. """ return os.path.realpath(os.path.join(RATROOT, *args)) env = SConscript(PSQLENVFILE) # 27-Jul-2006 WGS: Allow for alternative compilers. Is there a CXX # variable set in the calling environment? If so, use it. if os.environ.has_key("CXX"): env.Replace(CXX=os.environ["CXX"]) if ARGUMENTS.get('sconsverbose') < 1: env['CXXCOMSTR'] = "Compiling $TARGET" env['LINKCOMSTR'] = "Linking $TARGET" env['SHCXXCOMSTR'] = "Compiling $TARGET" env['SHLINKCOMSTR'] = "Linking $TARGET" env['ARCOMSTR'] = "Making archive $TARGET" #### RAT version # # Update the RAT version and revision according to git. # # Inspired by http://stackoverflow.com/questions/4942452 need_version = True try: env['RATVERSION'] = subprocess.Popen(['git', '--git-dir={0}'.format(os.path.join(RATROOT, ".git")), 'describe', '--always', '--tag'], stdout=subprocess.PIPE).communicate()[0].strip() env['RATREVISION'] = subprocess.Popen(['git', '--git-dir={0}'.format(os.path.join(RATROOT, ".git")), 'log', '-1', '--format="%H"'], stdout=subprocess.PIPE).communicate()[0].strip().strip('"') except OSError, e: print 'No git: fall back to RATVERSION file' if env['RATVERSION'] != '': # save strings to a file try: with open('RATVERSION', 'w') as f: f.write('{0}\n'.format(env['RATVERSION'])) f.write('{0}\n'.format(env['RATREVISION'])) print 'RATVERSION file written' except IOError as e: print "I/O Error writing RATVERSION ({0}): {1}".format(e.errno, e.strerror) # as long as we have a git version (even if couldn't write RATVERSION), # we use it for writing Version.cc need_version = False if need_version: try: # No git installed; read from the file with open('RATVERSION', 'r') as f: s = [ x.strip('\n') for x in f ] env['RATVERSION'] = s[0] env['RATREVISION'] = s[1] print 'RATVERSION file read' need_version = False except IOError as e: print "I/O Error reading RATVERSION ({0}): {1}".format(e.errno, e.strerror) if need_version: # this only happens if no git or cached RATVERSION file env['RATVERSION'] = '6.5.1' env['RATREVISION'] = 'water_rat_base' print "Taking hardcoded RAT version and indicating the branch the version was made from under revision" else: print 'RAT version ', env['RATVERSION'] print 'RAT revision ', env['RATREVISION'] version_cc_template = \ '''/// This file is automatically generated by scons, do not edit! #include #include namespace RAT { const std::string RATVERSION = "%s"; const std::string RATREVISION = "%s"; } // namespace RAT ''' def write_rat_version(target, source, env): 'Write the RAT version file.' contents = version_cc_template % (env['RATVERSION'], env['RATREVISION']) f= open(target[0].path, 'w') f.write(contents) f.close() return None ratversion = env.Command(rat_path('src/core/Version.cc'), [], Action(write_rat_version)) env.Default(ratversion) env.AlwaysBuild(ratversion) #### #### Builder: RATHeader(header file) # # Copies header file to $RATROOT/include/RAT. Modules keep their header # files in their respective src/ subdirectories. However, it is convenient # to have them all in one place to reduce the number of -I flags needed # for g++. # # For now, only use this builder on one header file at a time. No source # lists. def ratheader_emitter(target, source, env): 'Returns target filenames in $RATROOT/include dir for given source files.' target = [File(rat_path('include', 'RAT', env['INCLUDE_SUBDIR'], os.path.basename(str(s)))) for s in source] return target, source def copy_generator(source,target,env,for_signature): 'Tell SCons how to "create" a header file (by copying it).' return Copy(target[0].path, source[0].path) # Tell SCons how to "build" a header file (by copying it using ratheader_emitter above). ratheader = Builder(generator=copy_generator, emitter=ratheader_emitter,duplicate=0) #### #### Builder: RATApp([list of source files]) # # Compiles and links source files into full RAT application. Links # against static RAT library, and includes default rat.cc main function. # If you want to supply your own main function instead, set the 'mymain' # attribute in your environment: # # env['mymain'] = True # env.RATApp('myapp', ['mymain.cc', 'foo.cc', 'bar.cc']) def ratapp_emitter(target, source, env): 'Appends RAT library and appropriate main source file to source list.' if not env.has_key('mymain') or not env['mymain']: source += [ env['RATMAIN'] ] return (target, source + [env['RATLIB'],env['PSQLLIB']]) ratapp = Builder(action=env['BUILDERS']['Program'].action, emitter=ratapp_emitter) #### #### Create Environment for compiling RAT applications rootopts = SConscript('ROOT.scons') g4opts = SConscript('GEANT4.scons') arch = SConscript('ARCH.'+ROOTARCH) extopts = SConscript('EXTERNAL.scons') SYSTEM = os.environ['RATSYSTEM'] env.Append(ENV=os.environ, CPPPATH=['#/include','#include/libpq'], LIBPATH=['#/lib'] ) # Add architecture-dependent flags, GEANT4, and ROOT env.Append(**arch['default']) env.Append(**rootopts) env.Append(**g4opts) # Add external options flags configured from the EXTERNAL.scons file. # Supersedes the hardcoded library calls previously implemented which # failed in non-standard installations env.Append(**extopts) # Add flags from the shell environment user_controlled_vars = ['CPPFLAGS', 'CXXFLAGS', 'LDFLAGS'] envdict = {} for envvar in user_controlled_vars: if envvar in os.environ: envdict[envvar] = os.environ[envvar] env.Append(**envdict) # Add flags from the command line envdict = {} for envvar in user_controlled_vars: if envvar in ARGUMENTS: envdict[envvar] = ARGUMENTS.get(envvar) env.Append(**envdict) # Add optional build flags # These use command line arguments: # scons profile=1 # scons debug=1 # scons opt=1 # scons verbose=0,1,2 : activates the extra verbosity preprocessor macros in RAT: (0:off, 1:RATDEBUG, 2:RATVERBOSE) # scons defines=X,Y,Z : activates extra custom preprocessor macros profile = int(ARGUMENTS.get('profile', 0)) == 1 if profile: env.Append(CXXFLAGS=arch['PROFILEFLAGS']) env.Append(LINKFLAGS=arch['PROFILEFLAGS']) debugdefault = 1 else: debugdefault = 0 debug = int(ARGUMENTS.get('debug', debugdefault)) == 1 if debug: env.Append(CXXFLAGS=arch['DEBUGFLAGS']) env.Append(LINKFLAGS=arch['DEBUGFLAGS']) if debug and not (testenv('G4OPTIMISE') or testenv('G4OPTIMIZE')): optdefault = 0 else: optdefault = 1 opt = int(ARGUMENTS.get('opt', optdefault)) == 1 if opt: env.Append(CXXFLAGS=arch['OPTFLAGS']) # verbose option. Can accumulate options. verbose = str(ARGUMENTS.get('verbose', 0)) # iterate over the options. Use AppendUnique avoid duplicated # flags in case someone actually passes verbose=1,1 # Anything that is not 1 or 2 is ignored for opt in verbose: if opt == '1': env.AppendUnique(CPPDEFINES=['RATDEBUG']) elif opt == '2': env.AppendUnique(CPPDEFINES=['RATVERBOSE']) cppdefines = [] for key, value in ARGLIST: if key == 'define': cppdefines.append(value) print "Appending custom defines : ", cppdefines env.AppendUnique(CPPDEFINES=cppdefines) #### Set other useful RAT-specific variables # Put all intermediate build targets into build/[ROOTARCH] directory # This allows multiple platforms to be compiled in same RAT tree env['BUILDDIR'] = os.path.join('#/build', ROOTARCH) env.VariantDir(env['BUILDDIR'], '#/', duplicate=0) env['RATROOT'] = RATROOT # Static library name for linking to RAT applications env['RATLIB'] = rat_path('lib', 'librat_%s.a' % SYSTEM) # Shared library name loaded into ROOT for scripts env['RATSOLIB'] = rat_path('lib', 'libRATEvent_%s.so' % SYSTEM) env['RATBIN'] = rat_path('bin', 'rat_%s' % SYSTEM) # Name of source file containing default main function env['RATMAIN'] = env.Object(os.path.join(env['BUILDDIR'], 'rat.cc')) env['ROOTCINT_INCFLAGS'] = ['-I$RATROOT/include/RAT', '-I$RATROOT/include/RAT/DS', '-I$RATROOT/include/libpq'] env.Append(BUILDERS={'RATApp' : ratapp, 'RATHeader' : ratheader}) # Allows user-compiled apps to find rat.cc main function. env.Repository('$RATROOT') # Return environment object to caller who loaded us this way: # # env = SConscript('$RATROOT/config/RAT.scons') Return('env')