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

Builder.py

import UserDict
import UserList
import SCons.Action
from SCons.Debug import logInstanceCreation
from SCons.Errors import InternalError, UserError
import SCons.Executor
import SCons.Node.FS
import SCons.Util
import SCons.Warnings
00010 class _Null:
    pass
_null=_Null
00013 class DictCmdGenerator(SCons.Util.Selector):
    def src_suffixes(self):
        return self.keys()
    def add_action(self, suffix, action):
        self[suffix]=action
    def __call__(self, target, source, env, for_signature):
        ext=None
        for src in map(str, source):
            my_ext=SCons.Util.splitext(src)[1]
            if ext and my_ext != ext:
                raise UserError("While building `%s' from `%s': Cannot build multiple sources with different extensions: %s, %s" % (repr(map(str, target)), src, ext, my_ext))
            ext=my_ext
        if not ext:
            raise UserError("While building `%s': Cannot deduce file extension from source files: %s" % (repr(map(str, target)), repr(map(str, source))))
        try:
            ret=SCons.Util.Selector.__call__(self, env, source)
        except KeyError, e:
            raise UserError("Ambiguous suffixes after environment substitution: %s==%s==%s" % (e[0], e[1], e[2]))
        if ret is None:
            raise UserError("While building `%s': Don't know how to build a file with suffix `%s'." % (repr(map(str, target)), ext))
        return ret
00034 class CallableSelector(SCons.Util.Selector):
    def __call__(self, env, source):
        value=SCons.Util.Selector.__call__(self, env, source)
        if callable(value):
            value=value(env, source)
        return value
00040 class DictEmitter(SCons.Util.Selector):
    def __call__(self, target, source, env):
        emitter=SCons.Util.Selector.__call__(self, env, source)
        if emitter:
            target, source=emitter(target, source, env)
        return (target, source)
00046 class ListEmitter(UserList.UserList):
    def __call__(self, target, source, env):
        for e in self.data:
            target, source=e(target, source, env)
        return (target, source)
misleading_keywords={
    'targets'   : 'target',
    'sources'   : 'source',
}
00055 class OverrideWarner(UserDict.UserDict):
    def __init__(self, dict):
        UserDict.UserDict.__init__(self, dict)
        self.already_warned=None
    def warn(self):
        if self.already_warned:
            return
        for k in self.keys():
            try:
                alt=misleading_keywords[k]
            except KeyError:
                pass
            else:
                SCons.Warnings.warn(SCons.Warnings.MisleadingKeywordsWarning,
                                    "Did you mean to use `%s' instead of `%s'?" % (alt, k))
        self.already_warned=1
def Builder(**kw):
    composite=None
    if kw.has_key('generator'):
        if kw.has_key('action'):
            raise UserError, "You must not specify both an action and a generator."
        kw['action']=SCons.Action.CommandGenerator(kw['generator'])
        del kw['generator']
    elif kw.has_key('action') and SCons.Util.is_Dict(kw['action']):
        composite=DictCmdGenerator(kw['action'])
        kw['action']=SCons.Action.CommandGenerator(composite)
        kw['src_suffix']=composite.src_suffixes()
    if kw.has_key('emitter'):
        emitter=kw['emitter']
        if SCons.Util.is_String(emitter):
            var=SCons.Util.get_environment_var(emitter)
            if not var:
                raise UserError, "Supplied emitter '%s' does not appear to refer to an Environment variable" % emitter
            kw['emitter']=EmitterProxy(var)
        elif SCons.Util.is_Dict(emitter):
            kw['emitter']=DictEmitter(emitter)
        elif SCons.Util.is_List(emitter):
            kw['emitter']=ListEmitter(emitter)
    if kw.has_key('src_builder'):
        ret=apply(MultiStepBuilder, (), kw)
    else:
        ret=apply(BuilderBase, (), kw)
    if not composite is None:
        ret=CompositeBuilder(ret, composite)
    return ret
def _init_nodes(builder, env, overrides, tlist, slist):
    for t in tlist:
        if t.side_effect:
            raise UserError, "Multiple ways to build the same target were specified for: %s" % str(t)
        if t.has_builder():
            if not t.env is None and not t.env is env:
                t_contents=t.builder.action.get_contents(tlist, slist, t.env)
                contents=t.builder.action.get_contents(tlist, slist, env)
                if t_contents==contents:
                    SCons.Warnings.warn(SCons.Warnings.DuplicateEnvironmentWarning,
                                        "Two different environments were specified for target %s,\n\tbut they appear to have the same action: %s"%(str(t), t.builder.action.strfunction(tlist, slist, t.env)))
                else:
                    raise UserError, "Two environments with different actions were specified for the same target: %s"%str(t)
            elif t.overrides != overrides:
                raise UserError, "Two different sets of overrides were specified for the same target: %s"%str(t)
            elif builder.target_scanner and t.target_scanner and builder.target_scanner != t.target_scanner:
                raise UserError, "Two different scanners were specified for the same target: %s"%str(t)
            if builder.multi:
                if t.builder != builder:
                    if isinstance(t.builder, ListBuilder) and isinstance(builder, ListBuilder) and t.builder.builder==builder.builder:
                        raise UserError, "Two different target sets have a target in common: %s"%str(t)
                    else:
                        raise UserError, "Two different builders (%s and %s) were specified for the same target: %s"%(t.builder.get_name(env), builder.get_name(env), str(t))
            elif t.sources != slist:
                raise UserError, "Multiple ways to build the same target were specified for: %s" % str(t)
    if builder.single_source:
        if len(slist) > 1:
            raise UserError, "More than one source given for single-source builder: targets=%s sources=%s" % (map(str,tlist), map(str,slist))
    executor=None
    if builder.multi:
        try:
            executor=tlist[0].get_executor(create=0)
        except AttributeError:
            pass
        else:
            executor.add_sources(slist)
    if executor is None:
        executor=SCons.Executor.Executor(builder.action, env or builder.env, [builder.overrides, overrides], tlist, slist)
    for t in tlist:
        t.overrides=overrides
        t.cwd=SCons.Node.FS.default_fs.getcwd()
        t.builder_set(builder)
        t.env_set(env)
        t.add_source(slist)
        t.set_executor(executor)
        if builder.target_scanner:
            t.target_scanner=builder.target_scanner
        if t.source_scanner is None:
            t.source_scanner=builder.source_scanner
    for s in slist:
        if s.source_scanner is None and s.backup_source_scanner is None:
            s.backup_source_scanner=env.get_scanner(s.scanner_key())
00152 class EmitterProxy:
    def __init__(self, var):
        self.var=SCons.Util.to_String(var)
    def __call__(self, target, source, env):
        emitter=self.var
        while SCons.Util.is_String(emitter) and env.has_key(emitter):
            emitter=env[emitter]
        if callable(emitter):
            target, source=emitter(target, source, env)
        elif SCons.Util.is_List(emitter):
            for e in emitter:
                target, source=e(target, source, env)
        return (target, source)
    def __cmp__(self, other):
        return cmp(self.var, other.var)
00167 class BuilderBase:
    def __init__(self,  action=None,
                        prefix='',
                        suffix='',
                        src_suffix='',
                        target_factory=SCons.Node.FS.default_fs.File,
                        source_factory=SCons.Node.FS.default_fs.File,
                        target_scanner=None,
                        source_scanner=None,
                        emitter=None,
                        multi=0,
                        env=None,
                        single_source=0,
                        **overrides):
        if __debug__: logInstanceCreation(self, 'BuilderBase')
        self.action=SCons.Action.Action(action)
        self.multi=multi
        if SCons.Util.is_Dict(prefix):
            prefix=CallableSelector(prefix)
        self.prefix=prefix
        if SCons.Util.is_Dict(suffix):
            suffix=CallableSelector(suffix)
        self.suffix=suffix
        self.env=env
        self.single_source=single_source
        if overrides.has_key('overrides'):
            SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
                "The \"overrides\" keyword to Builder() creation has been deprecated;\n" +\
                "\tspecify the items as keyword arguments to the Builder() call instead.")
            overrides.update(overrides['overrides'])
            del overrides['overrides']
        self.overrides=overrides
        self.set_src_suffix(src_suffix)
        self.target_factory=target_factory
        self.source_factory=source_factory
        self.target_scanner=target_scanner
        self.source_scanner=source_scanner
        self.emitter=emitter
    def __nonzero__(self):
        raise InternalError, "Do not test for the Node.builder attribute directly; use Node.has_builder() instead"
    def get_name(self, env):
        try:
            index=env['BUILDERS'].values().index(self)
            return env['BUILDERS'].keys()[index]
        except (AttributeError, KeyError, ValueError):
            return str(self.__class__)
    def __cmp__(self, other):
        return cmp(self.__dict__, other.__dict__)
    def splitext(self, path):
        return SCons.Util.splitext(path)
    def _create_nodes(self, env, overwarn, target=None, source=None):
        def _adjustixes(files, pre, suf):
            if not files:
                return []
            result=[]
            if not SCons.Util.is_List(files):
                files=[files]
            for f in files:
                if SCons.Util.is_String(f):
                    f=SCons.Util.adjustixes(f, pre, suf)
                result.append(f)
            return result
        overwarn.warn()
        env=env.Override(overwarn.data)
        src_suf=self.get_src_suffix(env)
        source=_adjustixes(source, None, src_suf)
        slist=env.arg2nodes(source, self.source_factory)
        pre=self.get_prefix(env, slist)
        suf=self.get_suffix(env, slist)
        if target is None:
            try:
                t_from_s=slist[0].target_from_source
            except AttributeError:
                raise UserError("Do not know how to create a target from source `%s'" % slist[0])
            tlist=[ t_from_s(pre, suf, self.splitext) ]
        else:
            target=_adjustixes(target, pre, suf)
            tlist=env.arg2nodes(target, self.target_factory)
        if self.emitter:
            new_targets=[]
            for t in tlist:
                if not t.is_derived():
                    t.builder=self
                    new_targets.append(t)
            target, source=self.emitter(target=tlist, source=slist, env=env)
            for t in new_targets:
                if t.builder is self:
                    t.builder=None
            slist=env.arg2nodes(source, self.source_factory)
            tlist=env.arg2nodes(target, self.target_factory)
        return tlist, slist
    def _execute(self, env, target=None, source=_null, overwarn={}):
        if source is _null:
            source=target
            target=None
        if(self.single_source and
           SCons.Util.is_List(source) and
           len(source) > 1 and
           target is None):
            result=[]
            if target is None: target=[None]*len(source)
            for k in range(len(source)):
                t=self._execute(env, target[k], source[k], overwarn)
                if SCons.Util.is_List(t):
                    result.extend(t)
                else:
                    result.append(t)
            return result
        
        tlist, slist=self._create_nodes(env, overwarn, target, source)
        if len(tlist)==1:
            builder=self
        else:
            builder=ListBuilder(self, env, tlist)
        _init_nodes(builder, env, overwarn.data, tlist, slist)
        return tlist
    def __call__(self, env, target=None, source=_null, **kw):
        return self._execute(env, target, source, OverrideWarner(kw))
    def adjust_suffix(self, suff):
        if suff and not suff[0] in [ '.', '_', '$' ]:
            return '.' + suff
        return suff
    def get_prefix(self, env, sources=[]):
        prefix=self.prefix
        if callable(prefix):
            prefix=prefix(env, sources)
        return env.subst(prefix)
    def get_suffix(self, env, sources=[]):
        suffix=self.suffix
        if callable(suffix):
            suffix=suffix(env, sources)
        else:
            suffix=self.adjust_suffix(suffix)
        return env.subst(suffix)
    def src_suffixes(self, env):
        return map(lambda x, s=self, e=env: e.subst(s.adjust_suffix(x)),
                   self.src_suffix)
    def set_src_suffix(self, src_suffix):
        if not src_suffix:
            src_suffix=[]
        elif not SCons.Util.is_List(src_suffix):
            src_suffix=[ src_suffix ]
        self.src_suffix=src_suffix
    def get_src_suffix(self, env):
        ret=self.src_suffixes(env)
        if not ret:
            return ''
        return ret[0]
    def targets(self, node):
        return [ node ]
    def add_emitter(self, suffix, emitter):
        self.emitter[suffix]=emitter
00319 class ListBuilder(SCons.Util.Proxy):
    def __init__(self, builder, env, tlist):
        if __debug__: logInstanceCreation(self)
        SCons.Util.Proxy.__init__(self, builder)
        self.builder=builder
        self.target_scanner=builder.target_scanner
        self.source_scanner=builder.source_scanner
        self.env=env
        self.tlist=tlist
        self.multi=builder.multi
        self.single_source=builder.single_source
    def targets(self, node):
        return self.tlist
    def __cmp__(self, other):
        return cmp(self.__dict__, other.__dict__)
    def get_name(self, env):
        return "ListBuilder(%s)" % self.builder.get_name(env)
00336 class MultiStepBuilder(BuilderBase):
    def __init__(self,  src_builder,
                        action=None,
                        prefix='',
                        suffix='',
                        src_suffix='',
                        target_factory=SCons.Node.FS.default_fs.File,
                        source_factory=SCons.Node.FS.default_fs.File,
                        target_scanner=None,
                        source_scanner=None,
                        emitter=None,
                        single_source=0):
        if __debug__: logInstanceCreation(self)
        BuilderBase.__init__(self, action, prefix, suffix, src_suffix,
                             target_factory, source_factory,
                             target_scanner, source_scanner, emitter,
                             single_source=single_source)
        if not SCons.Util.is_List(src_builder):
            src_builder=[ src_builder ]
        self.src_builder=src_builder
        self.sdict={}
        self.cached_src_suffixes={}
    def _execute(self, env, target=None, source=_null, overwarn={}):
        if source is _null:
            source=target
            target=None
        slist=env.arg2nodes(source, self.source_factory)
        final_sources=[]
        try:
            sdict=self.sdict[id(env)]
        except KeyError:
            sdict={}
            self.sdict[id(env)]=sdict
            for bld in self.src_builder:
                if SCons.Util.is_String(bld):
                    try:
                        bld=env['BUILDERS'][bld]
                    except KeyError:
                        continue
                for suf in bld.src_suffixes(env):
                    sdict[suf]=bld
        src_suffixes=self.src_suffixes(env)
        for snode in slist:
            try:
                get_suffix=snode.get_suffix
            except AttributeError:
                ext=self.splitext(str(snode))
            else:
                ext=get_suffix()
            try:
                subsidiary_builder=sdict[ext]
            except KeyError:
                final_sources.append(snode)
            else:
                tgt=subsidiary_builder._execute(env, None, snode, overwarn)
                if len(tgt) > 1:
                    tgt=filter(lambda x, self=self, suf=src_suffixes:
                                 self.splitext(SCons.Util.to_String(x))[1] in suf, tgt)
                final_sources.extend(tgt)
        return BuilderBase._execute(self, env, target, final_sources, overwarn)
    def get_src_builders(self, env):
        ret=[]
        for bld in self.src_builder:
            if SCons.Util.is_String(bld):
                try:
                    bld=env['BUILDERS'][bld]
                except KeyError:
                    continue
            ret.append(bld)
        return ret
    def src_suffixes(self, env):
        try:
            return self.cached_src_suffixes[id(env)]
        except KeyError:
            suffixes=BuilderBase.src_suffixes(self, env)
            for builder in self.get_src_builders(env):
                suffixes.extend(builder.src_suffixes(env))
            self.cached_src_suffixes[id(env)]=suffixes
            return suffixes
00415 class CompositeBuilder(SCons.Util.Proxy):
    def __init__(self, builder, cmdgen):
        if __debug__: logInstanceCreation(self)
        SCons.Util.Proxy.__init__(self, builder)
        self.cmdgen=cmdgen
        self.builder=builder
    def add_action(self, suffix, action):
        self.cmdgen.add_action(suffix, action)
        self.set_src_suffix(self.cmdgen.src_suffixes())
    def __cmp__(self, other):
        return cmp(self.__dict__, other.__dict__)

Generated by  Doxygen 1.6.0   Back to index