Logo Search packages:      
Sourcecode: abakus version File versions  Download package

SConf.py

import cPickle
import os
import string
import sys
import traceback
import types
import SCons.Action
import SCons.Builder
import SCons.Errors
import SCons.Node.FS
import SCons.Taskmaster
import SCons.Util
import SCons.Warnings
import SCons.Conftest
SConfFS=SCons.Node.FS.default_fs
dryrun=0
_ac_build_counter=0
_ac_config_counter=0
_activeSConfObjects={}
00020 class SConfWarning(SCons.Warnings.Warning):
    pass
SCons.Warnings.enableWarningClass( SConfWarning )
def _createSource( target, source, env ):
    fd=open(str(target[0]), "w")
    fd.write(env['SCONF_TEXT'])
    fd.close()
def _stringSource( target, source, env ):
    import string
    return (str(target[0]) + ' <- \n  |' +
            string.replace( env['SCONF_TEXT'], "\n", "\n  |" ) )
BooleanTypes=[types.IntType]
if hasattr(types, 'BooleanType'): BooleanTypes.append(types.BooleanType)
00033 class SConf:
    def __init__(self, env, custom_tests={}, conf_dir='#/.sconf_temp',
                 log_file='#/config.log'): 
        import SCons.Script.SConscript
        if not SCons.Script.SConscript.sconscript_reading:
            raise SCons.Errors.UserError, "Calling Configure from Builders is not supported."
        global SConfFS
        if not SConfFS:
            SConfFS=SCons.Node.FS.FS(SCons.Node.FS.default_fs.pathTop)
        if len(_activeSConfObjects.keys()) > 0:
            raise (SCons.Errors.UserError,
                   "Only one SConf object may be active at one time")
        self.env=env
        if log_file != None:
            self.logfile=SConfFS.File(log_file)
        else:
            self.logfile=None
        self.logstream=None
        self.lastTarget=None
        default_tests={
                 'CheckFunc'          : CheckFunc,
                 'CheckType'          : CheckType,
                 'CheckHeader'        : CheckHeader,
                 'CheckCHeader'       : CheckCHeader,
                 'CheckCXXHeader'     : CheckCXXHeader,
                 'CheckLib'           : CheckLib,
                 'CheckLibWithHeader' : CheckLibWithHeader
               }
        self.AddTests(default_tests)
        self.AddTests(custom_tests)
        self.confdir=SConfFS.Dir(conf_dir)
        self.calc=None
        self.cache={}
        self._startup()
    def Finish(self):
        global _lastSConfObj
        _lastSConfObj=None
        self._shutdown()
        return self.env
    def _setCache(self, nodes, already_done=[]):
        for n in nodes:
            if (n.has_builder() and
                not n in already_done):
                n.add_pre_action(SCons.Action.Action(self._preCache,
                                                     self._stringCache))
                n.add_post_action(SCons.Action.Action(self._postCache,
                                                      self._stringCache))
                already_done.append( n )
            self._setCache(n.children())
            n.clear()
    def BuildNodes(self, nodes):
        global SCons
        import SCons.Script
        class SConfBuildTask(SCons.Script.BuildTask):
            def do_failed(self, status=2):
                pass
        class SConfDryRunTask(SConfBuildTask):
            def execute(self):
                target=self.targets[0]
                if (target.get_state() != SCons.Node.up_to_date and
                    target.has_builder() and
                    not hasattr(target.builder, 'status')):
                    raise SCons.Errors.ConfigureDryRunError(target)
                
            def failed(self):
                exc_type, exc_value=self.exc_info()[:2]
                if exc_type==SCons.Errors.ConfigureDryRunError:
                    raise exc_type, exc_value
                SCons.Script.BuildTask.failed(self)
        if self.logstream != None:
            oldStdout=sys.stdout
            sys.stdout=self.logstream
            oldStderr=sys.stderr
            sys.stderr=self.logstream
        old_fs_dir=SConfFS.getcwd()
        old_os_dir=os.getcwd()
        SConfFS.chdir(SConfFS.Top, change_os_dir=1)
        self._setCache( nodes ) 
        ret=1
        try:
            self.calc=SCons.Sig.Calculator(max_drift=0)
            if dryrun:
                buildTask=SConfDryRunTask
            else:
                buildTask=SConfBuildTask
            tm=SCons.Taskmaster.Taskmaster( nodes, buildTask )
            jobs=SCons.Job.Jobs(1, tm )
            try:
                jobs.run()
            except SCons.Errors.BuildError, e:
                sys.stderr.write("scons: *** [%s] %s\n" % (e.node, e.errstr))
                if e.errstr=='Exception':
                    traceback.print_exception(e.args[0], e.args[1], e.args[2])
            for n in nodes:
                state=n.get_state()
                if (state != SCons.Node.executed and
                    state != SCons.Node.up_to_date):
                    ret=0
        finally:
            os.chdir(old_os_dir)
            SConfFS.chdir(old_fs_dir, change_os_dir=0)
            if self.logstream != None:
                sys.stdout=oldStdout
                sys.stderr=oldStderr
        return ret
    def TryBuild(self, builder, text=None, extension=""):
        global _ac_build_counter
        nodesToBeBuilt=[]
        f="conftest_" + str(_ac_build_counter)
        pref=self.env.subst( builder.builder.prefix )
        suff=self.env.subst( builder.builder.suffix )
        target=self.confdir.File(pref + f + suff)
        self.env['SCONF_TEXT']=text
        self.env['PIPE_BUILD']=1
        self.env['PSTDOUT']=self.logstream
        self.env['PSTDERR']=self.logstream
        if text != None:
            source=self.confdir.File(f + extension)
            sourceNode=self.env.SConfSourceBuilder(target=source,
                                                     source=None)
            nodesToBeBuilt.extend(sourceNode)
        else:
            source=None
        nodes=builder(target=target, source=source)
        if not SCons.Util.is_List(nodes):
            nodes=[nodes]
        nodesToBeBuilt.extend(nodes)
        ret=self.BuildNodes(nodesToBeBuilt)
        del self.env['PIPE_BUILD']
        del self.env['PSTDOUT']
        del self.env['PSTDERR']
        del self.env['SCONF_TEXT']
        _ac_build_counter=_ac_build_counter + 1
        if ret:
            self.lastTarget=nodes[0]
        else:
            self.lastTarget=None
        return ret
    def TryAction(self, action, text=None, extension=""):
        builder=SCons.Builder.Builder(action=action)
        self.env.Append( BUILDERS={'SConfActionBuilder' : builder} )
        ok=self.TryBuild(self.env.SConfActionBuilder, text, extension)
        del self.env['BUILDERS']['SConfActionBuilder']
        if ok:
            outputStr=self.lastTarget.get_contents()
            return (1, outputStr)
        return (0, "")
    def TryCompile( self, text, extension):
        return self.TryBuild(self.env.Object, text, extension)
    def TryLink( self, text, extension ):
        return self.TryBuild(self.env.Program, text, extension )
    def TryRun(self, text, extension ):
        ok=self.TryLink(text, extension)
        if( ok ):
            prog=self.lastTarget
            pname=str(prog)
            output=SConfFS.File(pname+'.out')
            node=self.env.Command(output, prog, [ [ pname, ">", "${TARGET}"] ])
            ok=self.BuildNodes(node)
            if ok:
                outputStr=output.get_contents()
                return( 1, outputStr)
        return (0, "")
00196     class TestWrapper:
        def __init__(self, test, sconf):
            self.test=test
            self.sconf=sconf
        def __call__(self, *args, **kw):
            if not self.sconf.active:
                raise (SCons.Errors.UserError,
                       "Test called after sconf.Finish()")
            context=CheckContext(self.sconf)
            ret=apply(self.test, (context,) +  args, kw)
            context.Result("error: no result")
            return ret
    def AddTest(self, test_name, test_instance):
        setattr(self, test_name, SConf.TestWrapper(test_instance, self))
    def AddTests(self, tests):
        for name in tests.keys():
            self.AddTest(name, tests[name])
    def _preCache(self, target, source, env):
        needs_rebuild=target[0].exists()
        buildSig=target[0].calc_signature(self.calc)
        for node in source:
            if node.get_state() != SCons.Node.up_to_date:
                needs_rebuild=1
        tname=str(target[0])
        if not self.cache.has_key( tname ):
            needs_rebuild=1
        else:
            lastBuildSig=self.cache[tname]['builder']
            if lastBuildSig != buildSig:
                needs_rebuild=1
        if not needs_rebuild:
            print ('(cached): Building "%s" failed in a previous run.' %
                   target[0])
            return 1
        else:
            self.cache[tname]={
               'builder' :  buildSig
            }
    def _postCache(self, target, source, env):
        del self.cache[str(target[0])]
    def _stringCache(self, target, source, env):
        return None
    def _loadCache(self):
        try:
            cacheDesc=cPickle.load(open(str(self.confdir.File(".cache"))))
            if cacheDesc['scons_version'] != SCons.__version__:
                raise Exception, "version mismatch"
            self.cache=cacheDesc['data']
        except KeyboardInterrupt:
            raise
        except:
            self.cache={}
    def _dumpCache(self):
        if dryrun:
            return
        try:
            cacheDesc={'scons_version' : SCons.__version__,
                         'data'          : self.cache }
            cPickle.dump(cacheDesc, open(str(self.confdir.File(".cache")),"w"))
        except Exception, e:
            SCons.Warnings.warn( SConfWarning, "Couldn't dump SConf cache" )
    def _createDir( self, node ):
        dirName=str(node)
        if dryrun:
            if not os.path.isdir( dirName ):
                raise SCons.Errors.ConfigureDryRunError(dirName)
        else:
            if not os.path.isdir( dirName ):
                os.makedirs( dirName )
                node._exists=1
    def _startup(self):
        global _ac_config_counter
        global _activeSConfObjects
        global SConfFS
        self.lastEnvFs=self.env.fs
        self.env.fs=SConfFS
        self._createDir(self.confdir)
        self.confdir.up().add_ignore( [self.confdir] )
        if self.logfile != None and not dryrun:
            if _ac_config_counter==0:
                log_mode="w"
            else:
                log_mode="a"
            self.logstream=open(str(self.logfile), log_mode)
            self.logfile.dir.add_ignore( [self.logfile] )
            tb=traceback.extract_stack()[-3]
            self.logstream.write( '\nfile %s,line %d:\n\tConfigure( confdir=%s )\n\n' % (tb[0], tb[1], str(self.confdir)) )
        else: 
            self.logstream=None
        action=SCons.Action.Action(_createSource, _stringSource, varlist=['SCONF_TEXT'])
        sconfSrcBld=SCons.Builder.Builder(action=action)
        self.env.Append( BUILDERS={'SConfSourceBuilder':sconfSrcBld} )
        self.active=1
        _activeSConfObjects[self]=None
        _ac_config_counter=_ac_config_counter + 1
        self._loadCache()
    def _shutdown(self):
        global _activeSConfObjets
        if not self.active:
            raise SCons.Errors.UserError, "Finish may be called only once!"
        if self.logstream != None:
            self.logstream.close()
            self.logstream=None
        blds=self.env['BUILDERS']
        del blds['SConfSourceBuilder']
        self.env.Replace( BUILDERS=blds )
        self.active=0
        del _activeSConfObjects[self]
        self._dumpCache()
        self.env.fs=self.lastEnvFs
00306 class CheckContext:
    def __init__(self, sconf):
        self.sconf=sconf
        self.cached=0
        self.did_show_result=0
        self.vardict={}
        self.havedict={}
        self.headerfilename=None
    def Message(self, text):
        if self.sconf.logstream != None:
            self.sconf.logstream.write(text + '\n')
        sys.stdout.write(text)
        self.did_show_result=0
    def Result(self, res):
        if type(res) in BooleanTypes:
            if res:
                text="ok"
            else:
                text="failed"
        elif type(res)==types.StringType:
            text=res
        else:
            raise TypeError, "Expected string, int or bool, got " + str(type(res))
        if self.did_show_result==0:
            if self.cached:
                text=text + " (cached)"
            if self.sconf.logstream != None:
                self.sconf.logstream.write("Result: " + text + "\n\n")
            sys.stdout.write(text + "\n")
            self.did_show_result=1
    def TryBuild(self, *args, **kw):
        return apply(self.sconf.TryBuild, args, kw)
    def TryAction(self, *args, **kw):
        return apply(self.sconf.TryAction, args, kw)
    def TryCompile(self, *args, **kw):
        return apply(self.sconf.TryCompile, args, kw)
    def TryLink(self, *args, **kw):
        return apply(self.sconf.TryLink, args, kw)
    def TryRun(self, *args, **kw):
        return apply(self.sconf.TryRun, args, kw)
    def __getattr__( self, attr ):
        if( attr=='env' ):
            return self.sconf.env
        elif( attr=='lastTarget' ):
            return self.sconf.lastTarget
        else:
            raise AttributeError, "CheckContext instance has no attribute '%s'" % attr
    def BuildProg(self, text, ext):
        res=self.TryBuild(self.env.Program, text, ext)
        if type(res) in BooleanTypes:
            if res:
                ret=""
            else:
                ret="failed to build test program"
        elif type(res)==types.StringType:
            ret=res
        else:
            raise TypeError, "Expected string or int"
        return ret
    def CompileProg(self, text, ext):
        res=self.TryBuild(self.env.Object, text, ext)
        if type(res) in BooleanTypes:
            if res:
                ret=""
            else:
                ret="failed to compile test program"
        elif type(res)==types.StringType:
            ret=res
        else:
            raise TypeError, "Expected string or int"
        return ret
    def AppendLIBS(self, lib_name_list):
        oldLIBS=self.env.get( 'LIBS', [] )
        self.env.Append(LIBS=lib_name_list)
        return oldLIBS
    def SetLIBS(self, val):
        oldLIBS=self.env.get( 'LIBS', [] )
        self.env.Replace(LIBS=val)
        return oldLIBS
    def Display(self, msg):
        sys.stdout.write(msg)
        self.Log(msg)
    def Log(self, msg):
        if self.sconf.logstream != None:
            self.sconf.logstream.write(msg)
def CheckFunc(context, function_name, language=None):
    res=SCons.Conftest.CheckFunc(context, function_name, language=language)
    context.did_show_result=1
    if not res:
        return 1
    return 0
def CheckType(context, type_name, includes="", language=None):
    res=SCons.Conftest.CheckType(context, type_name,
                                        header=includes, language=language)
    context.did_show_result=1
    if not res:
        return 1
    return 0
def CheckHeader(context, header, include_quotes='<>', language=None):
    if not SCons.Util.is_List(header):
        header=[header]
    l=[]
    for s in header[:-1]:
        l.append("#include %s%s%s\n" % (include_quotes[0], s, include_quotes[1]))
    res=SCons.Conftest.CheckHeader(context, header[-1], string.join(l, ''),
                                     language=language,
                                     include_quotes=include_quotes)
    context.did_show_result=1
    if not res:
        return 1
    return 0
def CheckCHeader(context, header, include_quotes='""'):
    return CheckHeader(context, header, include_quotes, language="C")
def CheckCXXHeader(context, header, include_quotes='""'):
    return CheckHeader(context, header, include_quotes, language="C++")
def CheckLib(context, library=None, symbol="main", autoadd=1, header=None, language=None):
    if library==[]:
        library=[None]
    if not SCons.Util.is_List(library):
        library=[library]
    res=SCons.Conftest.CheckLib(context, library, symbol, header=header,
                                        language=language, autoadd=autoadd)
    context.did_show_result=1
    if not res:
        return 1
    return 0
def CheckLibWithHeader(context, libs, header, language, call="main();", autoadd=1):
    if not SCons.Util.is_List(header):
        header=[header]
    l=[]
    for s in header:
        l.append('#include "%s"\n' % (s))
    if libs==[]:
        libs=[None]
    if not SCons.Util.is_List(libs):
        libs=[libs]
    res=SCons.Conftest.CheckLib(context, libs, "main", string.join(l, ''),
            call=call, language=language, autoadd=autoadd)
    context.did_show_result=1
    if not res:
        return 1
    return 0

Generated by  Doxygen 1.6.0   Back to index