示例#1
0
    def __call__(self, target, source, env, for_signature):
        if not source:
            return []

        if self.source_ext_match:
            suffixes = self.src_suffixes()
            ext = None
            for src in map(str, source):
                my_ext = match_splitext(src, suffixes)[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
        else:
            ext = match_splitext(str(source[0]), self.src_suffixes())[1]

        if not ext:
            #return 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, ext)
        except KeyError as 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' from `%s': Don't know how to build from a source file with suffix `%s'.  Expected a suffix in this list: %s." % \
                            (repr(map(str, target)), repr(map(str, source)), ext, repr(self.keys())))
        return ret
示例#2
0
    def __call__(self, target, source, env, for_signature):
        if not source:
            return []

        if self.source_ext_match:
            suffixes = self.src_suffixes()
            ext = None
            for src in map(str, source):
                my_ext = match_splitext(src, suffixes)[1]
                if ext and my_ext != ext:
                    raise UserError(
                        "While building `%s' from `%s': Cannot build multiple sources with different extensions: %s, %s"
                        % (repr(list(map(str, target))), src, ext, my_ext))
                ext = my_ext
        else:
            ext = match_splitext(str(source[0]), self.src_suffixes())[1]

        if not ext:
            #return ext
            raise UserError(
                "While building `%s': "
                "Cannot deduce file extension from source files: %s" %
                (repr(list(map(str, target))), repr(list(map(str, source)))))

        try:
            ret = SCons.Util.Selector.__call__(self, env, source, ext)
        except KeyError, e:
            raise UserError(
                "Ambiguous suffixes after environment substitution: %s == %s == %s"
                % (e.args[0], e.args[1], e.args[2]))
示例#3
0
def SymlinkAction(target, source, env):
    target = target if is_List(target) else [target]
    source = source if is_List(source) else [source]

    if len(target) != 1 or len(source) != 1:
        raise UserError("Symlink only takes a single target and source")

    abs_src = os.path.abspath(str(source[0]))
    abs_trg = os.path.abspath(str(target[0]))

    if not os.path.isdir(abs_src):
        raise UserError(
            "Only folder symlink are allowed due to Windows limitation")

    try:
        os.unlink(abs_trg)
    except Exception:
        pass

    if env["HOST_OS"] == "win32":
        try:
            import _winapi

            _winapi.CreateJunction(abs_src, abs_trg)
        except Exception as e:
            raise UserError(
                f"Can't do a NTFS junction as symlink fallback ({abs_src} -> {abs_trg})"
            ) from e

    else:
        try:
            os.symlink(abs_src, abs_trg)
        except Exception as e:
            raise UserError(
                f"Can't create symlink ({abs_src} -> {abs_trg})") from e
示例#4
0
    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]))
示例#5
0
def _install_files(env, target, source, exclude=None, glob=None, recurse=True):
    """
    Install the given source paths to the given target location(s).
    """
    if exclude is None:
        exclude = []
    exclude = Flatten([exclude])
    exclude.extend(['.*', '*~', '*.pyc', '*.o', '*.os'])

    if glob is None:
        glob = []
    glob = Flatten([glob])

    target = Flatten([target])
    source = Flatten([source])
    if len(target) != len(source):
        if len(target) == 1:
            target = target * len(source)
        else:
            raise UserError('Export files mismatch')

    results = []
    for (t, s) in zip(target, source):
        if not isinstance(t, SConsFSBase):
            t = env.Dir(t)
        if not isinstance(s, SConsFSBase):
            s = env.Entry(s)
        for (dest, src) in _get_files(t, s, exclude, glob, recurse):
            results.extend(env.InstallAs(dest, src))
    return results
示例#6
0
class DictCmdGenerator(SCons.Util.Selector):
    """This is a callable class that can be used as a
    command generator function.  It holds on to a dictionary
    mapping file suffixes to Actions.  It uses that dictionary
    to return the proper action based on the file suffix of
    the source file."""

    def src_suffixes(self):
        return self.keys()

    def add_action(self, suffix, action):
        """Add a suffix-action pair to the mapping.
        """
        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
示例#7
0
def CythonModule(env, target, source=None):
    if not target:
        target = []
    elif not is_List(target):
        target = [target]

    if not source:
        source = []
    elif not is_List(source):
        source = [source]

    # mod_target is passed to the compile builder
    mod_target, *other_targets = target

    if not source:
        source.append(f"{mod_target}.pyx")

    pyx_mod, *too_much_mods = [x for x in source if str(x).endswith(".pyx")]
    if too_much_mods:
        raise UserError(
            f"Must have exactly one .pyx file in sources (got `{[mod, *too_much_mods]}`)"
        )
    c_mod = pyx_mod.split(".",
                          1)[0] + ".c"  # Useful to do `xxx.gen.pyx` ==> `xxx`
    CythonToCBuilder(env, target=[c_mod, *other_targets], source=source)

    c_compile_target = CythonCompile(env, target=mod_target, source=[c_mod])

    return [*c_compile_target, *other_targets]
示例#8
0
def load_profile(utils, env, profile_name):
    """Imports the variables defined by the profile."""

    compiler, available_profile = list_profile(env)
    if profile_name not in available_profile:
        msg = ""
        if profile_name != '?':
            msg += "[ERROR] No '{0}' profile found for '{1}'\n"\
                      .format(profile_name, compiler)
        if not available_profile:
            msg += "[WARNING] No available profile.\n"
        else:
            msg += "List of available profiles for '{0}':\n".format(compiler)
            profile_list = available_profile.items()
            profile_list.sort()
            for p_name, p_func in profile_list:
                if p_func.__doc__:
                    p_doc = p_func.__doc__
                else:
                    p_doc = "(no documentation yet.)"
                msg += """
 '{0}'
 {1}
{2}""".format(p_name, '-' * (len(p_name) + 2), p_doc)
        profile_dir = os.path.dirname(scons_ext.profile.__file__)
        msg += """

------------------------------------------------------------------------
|  IMPORTANT: Profiles can be added and enriched, just have a look in: |
|  "{0}"
----------------------------------------------------------------------/
""".format(profile_dir)
        raise UserError(msg)

    available_profile[profile_name](utils)
示例#9
0
def package(env, target, source, PACKAGEROOT, NAME, VERSION, PACKAGEVERSION,
            DESCRIPTION, SUMMARY, X_RPM_GROUP, LICENSE, **kw):
    # initialize the rpm tool
    SCons.Tool.Tool('rpm').generate(env)

    bld = env['BUILDERS']['Rpm']

    # Generate a UserError whenever the target name has been set explicitly,
    # since rpm does not allow for controlling it. This is detected by
    # checking if the target has been set to the default by the Package()
    # Environment function.
    if str(target[0]) != "%s-%s" % (NAME, VERSION):
        raise UserError("Setting target is not supported for rpm.")
    else:
        # This should be overridable from the construction environment,
        # which it is by using ARCHITECTURE=.
        # Guessing based on what os.uname() returns at least allows it
        # to work for both i386 and x86_64 Linux systems.
        archmap = {
            'i686': 'i386',
            'i586': 'i386',
            'i486': 'i386',
        }

        buildarchitecture = os.uname()[4]
        buildarchitecture = archmap.get(buildarchitecture, buildarchitecture)

        if kw.has_key('ARCHITECTURE'):
            buildarchitecture = kw['ARCHITECTURE']

        fmt = '%s-%s-%s.%s.rpm'
        #srcrpm = fmt % (NAME, VERSION, PACKAGEVERSION, 'src')
        binrpm = fmt % (NAME, VERSION, PACKAGEVERSION, buildarchitecture)

        #target = [ srcrpm, binrpm ]
        target = [
            binrpm,
        ]

    # get the correct arguments into the kw hash
    loc = locals()
    del loc['kw']
    kw.update(loc)
    del kw['source'], kw['target'], kw['env']

    # if no "SOURCE_URL" tag is given add a default one.
    if not kw.has_key('SOURCE_URL'):
        #kw['SOURCE_URL']=(str(target[0])+".tar.gz").replace('.rpm', '')
        kw['SOURCE_URL'] = string.replace(
            str(target[0]) + ".tar.gz", '.rpm', '')

    # mangle the source and target list for the rpmbuild
    env = OverrideEnvironment(env, kw)
    target, source = stripinstallbuilder(target, source, env)
    target, source = addspecfile(target, source, env)
    target, source = collectintargz(target, source, env)

    # now call the rpm builder to actually build the packet.
    return apply(bld, [env, target, source], kw)
示例#10
0
 def _rm(env, target, source):
     # assert len(target) == 1
     try:
         os.unlink(abs_trg)
     except FileNotFoundError:
         pass
     except Exception as e:
         raise UserError(f"Can't remove NTFS junction {abs_trg}") from e
示例#11
0
def Builder(**kw):
    """A factory for builder objects."""
    composite = None
    if 'generator' in kw:
        if 'action' in kw:
            raise UserError(
                "You must not specify both an action and a generator.")
        kw['action'] = SCons.Action.CommandGeneratorAction(kw['generator'], {})
        del kw['generator']
    elif 'action' in kw:
        source_ext_match = kw.get('source_ext_match', 1)
        if 'source_ext_match' in kw:
            del kw['source_ext_match']
        if SCons.Util.is_Dict(kw['action']):
            composite = DictCmdGenerator(kw['action'], source_ext_match)
            kw['action'] = SCons.Action.CommandGeneratorAction(composite, {})
            kw['src_suffix'] = composite.src_suffixes()
        else:
            kw['action'] = SCons.Action.Action(kw['action'])

    if 'emitter' in kw:
        emitter = kw['emitter']
        if SCons.Util.is_String(emitter):
            # This allows users to pass in an Environment
            # variable reference (like "$FOO") as an emitter.
            # We will look in that Environment variable for
            # a callable to use as the actual 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)

    result = BuilderBase(**kw)

    if not composite is None:
        result = CompositeBuilder(result, composite)

    return result
示例#12
0
def _soname(target, source, env, for_signature):
    if "SONAME" in env:
        # Now verify that SOVERSION is not also set as that is not allowed
        if "SOVERSION" in env:
            raise UserError(
                "Ambiguous library .so naming, both SONAME: %s and SOVERSION: %s are defined. "
                "Only one can be defined for a target library." %
                (env["SONAME"], env["SOVERSION"]))
        return "$SONAME"
    else:
        return "$SHLIBPREFIX$_get_shlib_stem${SHLIBSUFFIX}$_SHLIBSOVERSION"
示例#13
0
    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(
                    "Cannot build multiple sources with different extensions: %s, %s"
                    % (ext, my_ext))
            ext = my_ext

        if ext is None:
            raise UserError(
                "Cannot deduce file extension from source files: %s" %
                repr(map(str, source)))
        try:
            # XXX Do we need to perform Environment substitution
            # on the keys of action_dict before looking it up?
            return self.action_dict[ext]
        except KeyError:
            raise UserError("Don't know how to build a file with suffix %s." %
                            ext)
示例#14
0
class DictCmdGenerator(SCons.Util.Selector):
    """This is a callable class that can be used as a
    command generator function.  It holds on to a dictionary
    mapping file suffixes to Actions.  It uses that dictionary
    to return the proper action based on the file suffix of
    the source file."""
    def __init__(self, dict=None, source_ext_match=1):
        SCons.Util.Selector.__init__(self, dict)
        self.source_ext_match = source_ext_match

    def src_suffixes(self):
        return list(self.keys())

    def add_action(self, suffix, action):
        """Add a suffix-action pair to the mapping.
        """
        self[suffix] = action

    def __call__(self, target, source, env, for_signature):
        if not source:
            return []

        if self.source_ext_match:
            suffixes = self.src_suffixes()
            ext = None
            for src in map(str, source):
                my_ext = match_splitext(src, suffixes)[1]
                if ext and my_ext != ext:
                    raise UserError(
                        "While building `%s' from `%s': Cannot build multiple sources with different extensions: %s, %s"
                        % (repr(list(map(str, target))), src, ext, my_ext))
                ext = my_ext
        else:
            ext = match_splitext(str(source[0]), self.src_suffixes())[1]

        if not ext:
            #return ext
            raise UserError(
                "While building `%s': "
                "Cannot deduce file extension from source files: %s" %
                (repr(list(map(str, target))), repr(list(map(str, source)))))

        try:
            ret = SCons.Util.Selector.__call__(self, env, source, ext)
        except KeyError, e:
            raise UserError(
                "Ambiguous suffixes after environment substitution: %s == %s == %s"
                % (e.args[0], e.args[1], e.args[2]))
        if ret is None:
            raise UserError("While building `%s' from `%s': Don't know how to build from a source file with suffix `%s'.  Expected a suffix in this list: %s." % \
                            (repr(list(map(str, target))), repr(list(map(str, source))), ext, repr(list(self.keys()))))
        return ret
示例#15
0
def get_android_has_code(fname):
    parsed = minidom.parse(open(fname))
    application = parsed.getElementsByTagName('application')[0]
    hasCode = application.getAttributeNS(NSURI, 'hasCode')
    if not hasCode:
        return True # Default value

    if hasCode.lower() in ("yes", "true", "1"):
        return True

    if hasCode.lower() in ("no", "false", "0"):
        return False

    raise UserError("Value of hasCode is unknown")
示例#16
0
文件: rpm.py 项目: wsniper/Nuitka
def package(env, target, source, PACKAGEROOT, NAME, VERSION,
            PACKAGEVERSION, DESCRIPTION, SUMMARY, X_RPM_GROUP, LICENSE,
            **kw):
    # initialize the rpm tool
    SCons.Tool.Tool('rpm').generate(env)

    bld = env['BUILDERS']['Rpm']

    # Generate a UserError whenever the target name has been set explicitly,
    # since rpm does not allow for controlling it. This is detected by
    # checking if the target has been set to the default by the Package()
    # Environment function.
    if str(target[0])!="%s-%s"%(NAME, VERSION):
        raise UserError( "Setting target is not supported for rpm." )
    else:
        # This should be overridable from the construction environment,
        # which it is by using ARCHITECTURE=.
        buildarchitecture = SCons.Tool.rpmutils.defaultMachine()

        if 'ARCHITECTURE' in kw:
            buildarchitecture = kw['ARCHITECTURE']

        fmt = '%s-%s-%s.%s.rpm'
        srcrpm = fmt % (NAME, VERSION, PACKAGEVERSION, 'src')
        binrpm = fmt % (NAME, VERSION, PACKAGEVERSION, buildarchitecture)

        target = [ srcrpm, binrpm ]

    # get the correct arguments into the kw hash
    loc=locals()
    del loc['kw']
    kw.update(loc)
    del kw['source'], kw['target'], kw['env']

    # if no "SOURCE_URL" tag is given add a default one.
    if 'SOURCE_URL' not in kw:
        #kw['SOURCE_URL']=(str(target[0])+".tar.gz").replace('.rpm', '')
        kw['SOURCE_URL']=(str(target[0])+".tar.gz").replace('.rpm', '')

    # mangle the source and target list for the rpmbuild
    env = OverrideEnvironment(env, kw)
    target, source = stripinstallbuilder(target, source, env)
    target, source = addspecfile(target, source, env)
    target, source = collectintargz(target, source, env)

    # now call the rpm builder to actually build the packet.
    return bld(env, target, source, **kw)
示例#17
0
def _node_errors(builder, env, tlist, slist):
    """Validate that the lists of target and source nodes are
    legal for this builder and environment.  Raise errors or
    issue warnings as appropriate.
    """

    # First, figure out if there are any errors in the way the targets
    # were specified.
    for t in tlist:
        if t.side_effect:
            raise UserError(
                "Multiple ways to build the same target were specified for: %s"
                % t)
        if t.has_explicit_builder():
            if not t.env is None and not t.env is env:
                action = t.builder.action
                t_contents = t.builder.action.get_contents(tlist, slist, t.env)
                contents = builder.action.get_contents(tlist, slist, env)

                if t_contents == contents:
                    msg = "Two different environments were specified for target %s,\n\tbut they appear to have the same action: %s" % (
                        t, action.genstring(tlist, slist, t.env))
                    SCons.Warnings.warn(
                        SCons.Warnings.DuplicateEnvironmentWarning, msg)
                else:
                    msg = "Two environments with different actions were specified for the same target: %s\n(action 1: %s)\n(action 2: %s)" % (
                        t, t_contents.decode('utf-8'),
                        contents.decode('utf-8'))
                    raise UserError(msg)
            if builder.multi:
                if t.builder != builder:
                    msg = "Two different builders (%s and %s) were specified for the same target: %s" % (
                        t.builder.get_name(env), builder.get_name(env), t)
                    raise UserError(msg)
                # TODO(batch):  list constructed each time!
                if t.get_executor().get_all_targets() != tlist:
                    msg = "Two different target lists have a target in common: %s  (from %s and from %s)" % (
                        t, list(map(str,
                                    t.get_executor().get_all_targets())),
                        list(map(str, tlist)))
                    raise UserError(msg)
            elif t.sources != slist:
                msg = "Multiple ways to build the same target were specified for: %s  (from %s and from %s)" % (
                    t, list(map(str, t.sources)), list(map(str, slist)))
                raise UserError(msg)

    if builder.single_source:
        if len(slist) > 1:
            raise UserError(
                "More than one source given for single-source builder: targets=%s sources=%s"
                % (list(map(str, tlist)), list(map(str, slist))))
示例#18
0
def virtual_target_command(env, marker, condition, source, action):
    if not isinstance(marker, File):
        raise UserError("`marker` must be a File")

    if not condition(env) and os.path.exists(marker.abspath):
        # Condition has changed in our back, force rebuild
        env.Execute(Delete(marker))

    return env.Command(
        marker,
        source,
        [
            *(action if is_List(action) else [action]),
            Action(
                lambda target, source, env: install_marker(target[0]),
                "Write $TARGET to mark task complete",
            ),
        ],
    )
示例#19
0
def Tag(env, target, source, *more_tags, **kw_tags):
    """ Tag a file with the given arguments.

    Just sets the accordingly named attribute on the file object.

    TODO: FIXME
    """
    if not target:
        target = source
        first_tag = None
    else:
        first_tag = source

    if first_tag:
        kw_tags[first_tag[0]] = ''

    if not kw_tags and not more_tags:
        raise UserError("No tags given.")

    # XXX: sanity checks
    for x in more_tags:
        kw_tags[x] = ''

    if not SCons.Util.is_List(target):
        target = [target]
    else:
        # hmm, sometimes the target list is a list of a list
        # make sure it is flattened prior to processing.
        # TODO: perhaps some bug ?!?
        target = env.Flatten(target)

    for t in target:
        for k, v in kw_tags.items():
            # all file tags have to start with PACKAGING_, so we can later
            # differentiate between "normal" object attributes and the
            # packaging attributes. As the user should not be bothered with
            # that, the prefix will be added here if missing.
            if not k.startswith('PACKAGING_'):
                k = 'PACKAGING_' + k
            t.Tag(k, v)
示例#20
0
    def _execute(self, env, target, source, overwarn={}, executor_kw={}):
        # We now assume that target and source are lists or None.
        if self.src_builder:
            source = self.src_builder_sources(env, source, overwarn)

        if self.single_source and len(source) > 1 and target is None:
            result = []
            if target is None: target = [None] * len(source)
            for tgt, src in zip(target, source):
                if not tgt is None: tgt = [tgt]
                if not src is None: src = [src]
                result.extend(self._execute(env, tgt, src, overwarn))
            return SCons.Node.NodeList(result)

        overwarn.warn()

        tlist, slist = self._create_nodes(env, target, source)

        # Check for errors with the specified target/source lists.
        _node_errors(self, env, tlist, slist)

        # The targets are fine, so find or make the appropriate Executor to
        # build this particular list of targets from this particular list of
        # sources.

        executor = None
        key = None

        if self.multi:
            try:
                executor = tlist[0].get_executor(create=0)
            except (AttributeError, IndexError):
                pass
            else:
                executor.add_sources(slist)

        if executor is None:
            if not self.action:
                fmt = "Builder %s must have an action to build %s."
                raise UserError(
                    fmt %
                    (self.get_name(env or self.env), list(map(str, tlist))))
            key = self.action.batch_key(env or self.env, tlist, slist)
            if key:
                try:
                    executor = SCons.Executor.GetBatchExecutor(key)
                except KeyError:
                    pass
                else:
                    executor.add_batch(tlist, slist)

        if executor is None:
            executor = SCons.Executor.Executor(self.action, env, [], tlist,
                                               slist, executor_kw)
            if key:
                SCons.Executor.AddBatchExecutor(key, executor)

        # Now set up the relevant information in the target Nodes themselves.
        for t in tlist:
            t.cwd = env.fs.getcwd()
            t.builder_set(self)
            t.env_set(env)
            t.add_source(slist)
            t.set_executor(executor)
            t.set_explicit(self.is_explicit)

        return SCons.Node.NodeList(tlist)
示例#21
0
    def _create_nodes(self, env, target=None, source=None):
        """Create and return lists of target and source nodes.
        """
        src_suf = self.get_src_suffix(env)

        target_factory = env.get_factory(self.target_factory)
        source_factory = env.get_factory(self.source_factory)

        source = self._adjustixes(source, None, src_suf)
        slist = env.arg2nodes(source, 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])
            except IndexError:
                tlist = []
            else:
                splitext = lambda S: self.splitext(S, env)
                tlist = [t_from_s(pre, suf, splitext)]
        else:
            target = self._adjustixes(target, pre, suf, self.ensure_suffix)
            tlist = env.arg2nodes(target,
                                  target_factory,
                                  target=target,
                                  source=source)

        if self.emitter:
            # The emitter is going to do str(node), but because we're
            # being called *from* a builder invocation, the new targets
            # don't yet have a builder set on them and will look like
            # source files.  Fool the emitter's str() calls by setting
            # up a temporary builder on the new targets.
            new_targets = []
            for t in tlist:
                if not t.is_derived():
                    t.builder_set(self)
                    new_targets.append(t)

            orig_tlist = tlist[:]
            orig_slist = slist[:]

            target, source = self.emitter(target=tlist, source=slist, env=env)

            # Now delete the temporary builders that we attached to any
            # new targets, so that _node_errors() doesn't do weird stuff
            # to them because it thinks they already have builders.
            for t in new_targets:
                if t.builder is self:
                    # Only delete the temporary builder if the emitter
                    # didn't change it on us.
                    t.builder_set(None)

            # Have to call arg2nodes yet again, since it is legal for
            # emitters to spit out strings as well as Node instances.
            tlist = env.arg2nodes(target,
                                  target_factory,
                                  target=orig_tlist,
                                  source=orig_slist)
            slist = env.arg2nodes(source,
                                  source_factory,
                                  target=orig_tlist,
                                  source=orig_slist)

        return tlist, slist
示例#22
0
    def _create_nodes(self, env, overrides, target = None, source = None):
        """Create and return lists of target and source nodes.
        """
        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

        env = env.Override(overrides)

        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:
            # The emitter is going to do str(node), but because we're
            # being called *from* a builder invocation, the new targets
            # don't yet have a builder set on them and will look like
            # source files.  Fool the emitter's str() calls by setting
            # up a temporary builder on the new targets.
            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)

            # Now delete the temporary builders that we attached to any
            # new targets, so that _init_nodes() doesn't do weird stuff
            # to them because it thinks they already have builders.
            for t in new_targets:
                if t.builder is self:
                    # Only delete the temporary builder if the emitter
                    # didn't change it on us.
                    t.builder = None

            # Have to call arg2nodes yet again, since it is legal for
            # emitters to spit out strings as well as Node instances.
            slist = env.arg2nodes(source, self.source_factory)
            tlist = env.arg2nodes(target, self.target_factory)

        return tlist, slist
示例#23
0
def Package(env, target=None, source=None, **kw):
    """ Entry point for the package tool.
    """
    # check if we need to find the source files ourselves
    if not source:
        source = env.FindInstalledFiles()

    if not source:
        raise UserError("No source for Package() given")

    # decide which types of packages shall be built. Can be defined through
    # four mechanisms: command line argument, keyword argument,
    # environment argument and default selection (zip or tar.gz) in that
    # order.
    try:
        kw['PACKAGETYPE'] = env['PACKAGETYPE']
    except KeyError:
        pass

    if not kw.get('PACKAGETYPE'):
        kw['PACKAGETYPE'] = GetOption('package_type')

    if kw['PACKAGETYPE'] is None:
        if 'Tar' in env['BUILDERS']:
            kw['PACKAGETYPE'] = 'targz'
        elif 'Zip' in env['BUILDERS']:
            kw['PACKAGETYPE'] = 'zip'
        else:
            raise UserError("No type for Package() given")

    packagetype = kw['PACKAGETYPE']
    if not is_List(packagetype):
        packagetype = packagetype.split(',')

    # load the needed packagers.
    def load_packager(pkgtype):
        try:
            # the specific packager is a relative import
            return importlib.import_module("." + pkgtype, __name__)
        except ImportError as e:
            raise SConsEnvironmentError("packager %s not available: %s" %
                                        (pkgtype, str(e)))

    packagers = [load_packager(p) for p in packagetype]

    # set up targets and the PACKAGEROOT
    try:
        # fill up the target list with a default target name until the
        # PACKAGETYPE list is of the same size as the target list.
        if not target:
            target = []

        size_diff = len(packagetype) - len(target)
        default_name = "%(NAME)s-%(VERSION)s"

        if size_diff > 0:
            default_target = default_name % kw
            target.extend([default_target] * size_diff)

        if 'PACKAGEROOT' not in kw:
            kw['PACKAGEROOT'] = default_name % kw

    except KeyError as e:
        raise UserError("Missing Packagetag '%s'" % e.args[0])

    # setup the source files
    source = env.arg2nodes(source, env.fs.Entry)

    # call the packager to setup the dependencies.
    targets = []
    try:
        for packager in packagers:
            t = [target.pop(0)]
            t = packager.package(env, t, source, **kw)
            targets.extend(t)

        assert len(target) == 0

    except KeyError as e:
        raise UserError("Missing Packagetag '%s' for %s packager" %
                        (e.args[0], packager.__name__))
    except TypeError:
        # this exception means that a needed argument for the packager is
        # missing. As our packagers get their "tags" as named function
        # arguments we need to find out which one is missing.
        argspec = getfullargspec(packager.package)
        args = argspec.args
        if argspec.defaults:
            # throw away arguments with default values
            args = args[:-len(argspec.defaults)]
        args.remove('env')
        args.remove('target')
        args.remove('source')
        # now remove any args for which we have a value in kw.
        args = [x for x in args if x not in kw]

        if not args:
            raise  # must be a different error, so re-raise
        elif len(args) == 1:
            raise UserError("Missing Packagetag '%s' for %s packager" %
                            (args[0], packager.__name__))
        raise UserError("Missing Packagetags '%s' for %s packager" %
                        (", ".join(args), packager.__name__))

    target = env.arg2nodes(target, env.fs.Entry)
    #XXX: target set above unused... what was the intent?
    targets.extend(env.Alias('package', targets))
    return targets