Пример #1
0
    def __validate_artifact_name(self, filename, configured_name=None):
        typecheck(filename, basestring)
        normalized = os.path.normpath(filename).replace("\\", "/")
        if filename != normalized:
            raise DefinitionError(
                "File '%s' is not a normalized path name.  Please use '%s' "
                "instead." % (filename, normalized))

        if filename.startswith("../") or filename.startswith("/"):
            raise DefinitionError(
                "File '%s' points outside the surrounding directory.  To "
                "include a file from another directory, that directory must explicitly "
                "export it." % filename)
Пример #2
0
    def __init__(self, artifact, root_dir, state_map, config):
        typecheck(artifact, Artifact)
        typecheck(root_dir, Directory)
        typecheck(state_map, _StateMap)

        self.artifact = artifact
        self.config = config

        real_name = state_map.real_name(config, artifact)
        if real_name is None:
            # We couldn't get this artifact's name, because some things the name
            # depends on are dirty.  All the artifacts needed to compute this
            # artifact's name will be registered as inputs to the action which
            # creates this artifact, so we know that the creating action won't run
            # until we can compute this artifact's name, and we know that any
            # dependent actions won't run until the creating action runs.  So we're
            # all good.
            assert artifact.action is not None
            self.timestamp = -1
            self.is_dirty = True
        elif root_dir.exists(real_name):
            self.timestamp = root_dir.getmtime(real_name)
            self.is_dirty = self.__decide_if_dirty(state_map)
        elif artifact.action is not None:
            # Derived artifact doesn't exist yet.
            self.timestamp = -1
            self.is_dirty = True
        else:
            raise DefinitionError(
                "The required source file '%s' does not exist." %
                artifact.filename)
Пример #3
0
    def read_previous_output(self, artifact):
        if artifact.action is not self.__action:
            raise DefinitionError("%s is not an output of %s." %
                                  (artifact, self.__action))

        real_name = artifact.real_name(self.read)
        if real_name is not None and self.__config.root_dir.exists(real_name):
            return self.__config.root_dir.read(real_name)
        else:
            return None
Пример #4
0
    def derived_artifact(self, filename, action, configured_name=None):
        typecheck(filename, basestring)
        typecheck(action, Action)

        if filename in self.__derived_artifacts:
            raise DefinitionError(
                "Two different rules claim to build file '%s'.  Conflicting rules are "
                "'%s' and '%s'." %
                (filename, action.rule.name,
                 self.__derived_artifacts[filename].action.rule.name))

        filename = os.path.normpath(filename).replace("\\", "/")
        result = Artifact(filename, action, configured_name=configured_name)
        self.__derived_artifacts[filename] = result
        return result
Пример #5
0
    def import_(self, name):
        typecheck(name, str)

        if (self.__loader is None):
            raise DefinitionError("Imports must occur at file load time.")

        # Absolute imports start with "//".
        if name.startswith("//"):
            name = name[2:]
        else:
            name = self.__prefix + name
        (result, timestamp) = self.__loader.load_with_timestamp(name)
        if timestamp > self.__context.timestamp:
            self.__context.timestamp = timestamp
        return result
Пример #6
0
    def artifact_state(self, config, artifact):
        typecheck(artifact, Artifact)

        while artifact.alt_artifact is not None:
            config = config.alt_configs.get(artifact.alt_config)
            if config is None:
                raise DefinitionError(
                    "Artifact '%s' refers to unknown configuration '%s'." %
                    artifact, artifact.alt_config)
            artifact = artifact.alt_artifact

        result = self.__artifacts.get((config, artifact))
        if result is None:
            result = _ArtifactState(artifact, config.root_dir, self, config)
            self.__artifacts[(config, artifact)] = result
        return result
Пример #7
0
    def load_with_timestamp(self, targetname):
        """Like load(), but returns a tuple where the second element is the target's
    timestamp.  This is most-recent modification time of the SEBS file defining
    the target and those that it imports."""

        typecheck(targetname, basestring)

        parts = targetname.rsplit(":", 1)

        (file, context) = self.load_file(parts[0])

        if len(parts) == 1:
            return (file, context.timestamp)
        else:
            try:
                target = eval(parts[1], file.__dict__.copy())
            except Exception, e:
                raise DefinitionError("%s: %s" % (targetname, e.message))
            return (target, context.timestamp)
Пример #8
0
    def update_readiness(self, state_map):
        """Update self.is_ready based on input.  If no inputs are dirty, is_ready
    is set true, otherwise it is set false.  This method returns true if
    is_ready was modified (from false to true), or false if it kept its previous
    value."""

        typecheck(state_map, _StateMap)

        if self.is_ready:
            # Already ready.  No change is possible.
            return False

        enumerator = _ArtifactEnumeratorImpl(state_map, self.config,
                                             self.action)
        self.action.command.enumerate_artifacts(enumerator)

        self.blocking = set()
        for input in enumerator.inputs:
            input_state = state_map.artifact_state(self.config, input)

            if input_state.is_dirty:
                # Input is dirty, therefore it must have an action.
                blocking_state = state_map.action_state(
                    input_state.config, input_state.artifact.action)
                if blocking_state.is_ready and \
                   input_state.artifact not in blocking_state.outputs:
                    raise DefinitionError(
                        "%s is needed, but %s didn't generate it." %
                        (input_state.config, input_state.artifact.action))
                blocking_state.blocked.add(self)
                self.blocking.add(blocking_state)

        if len(self.blocking) > 0:
            # At least one input is still dirty.
            return False

        self.is_ready = True
        self.inputs = enumerator.inputs
        self.disk_inputs = enumerator.disk_inputs
        self.outputs = enumerator.outputs
        return True
Пример #9
0
    def output_artifact(self,
                        directory,
                        filename,
                        action,
                        configured_name=None):
        typecheck(directory, basestring)
        self.__validate_artifact_name(filename, configured_name)
        typecheck(action, Action)

        if directory not in ("bin", "include", "lib", "share"):
            raise DefinitionError("'%s' is not a valid output directory." %
                                  directory)

        if configured_name is not None:
            # caihsiaoster: use tree structure for binary
            configured_name = [directory + "/" + self.directory + "/"
                               ] + configured_name
#      configured_name = [directory + "/"] + configured_name

        return self.__loader.derived_artifact(
            # caihsiaoster: use tree structure for library
            os.path.join(directory, self.directory, filename),
            action,
            configured_name=configured_name)
Пример #10
0
 def get_disk_directory_path(self, dirname):
     result = self.__working_dir.get_disk_path(dirname)
     if result is None:
         raise DefinitionError("Not a disk directory: " + dirname)
     else:
         return result
Пример #11
0
    def load_file(self, filename):
        """Load a SEBS file.  The filename is given relative to the root of
    the source tree (the "src" directory).  Returns an object whose fields
    correspond to the globals defined in that file."""

        typecheck(filename, basestring)

        normalized = os.path.normpath(filename).replace("\\", "/")
        if filename != normalized:
            raise DefinitionError(
                "'%s' is not a normalized path name.  Please use '%s' instead."
                % (filename, normalized))

        if filename.startswith("../") or filename.startswith("/"):
            raise DefinitionError("'%s' is not within src." % filename)

        if self.__root_dir.isdir("src/" + filename):
            filename = filename + "/SEBS"

        if filename in self.__loaded_files:
            existing = self.__loaded_files[filename]
            if existing is None:
                raise DefinitionError("File recursively imports itself: %s",
                                      filename)
            return existing

        context = _ContextImpl(self, filename, self.__root_dir)
        builtins = _Builtins(self, context)

        def run():
            # TODO(kenton):  Remove SEBS itself from PYTHONPATH before parsing, since
            #   SEBS files should not be importing the SEBS implementation.
            vars = {"sebs": builtins}
            self.__root_dir.execfile(context.full_filename, vars)
            return vars

        self.__loaded_files[filename] = None
        try:
            vars = context.run(run)
        finally:
            del self.__loaded_files[filename]

        # Prohibit lazy imports.
        builtins.disable()

        # Copy the vars before deleting anything because any functions defined in
        # the file still hold a reference to the original map as part of their
        # environment, so modifying the original map could break those functions.
        vars = vars.copy()

        # Delete "builtins", but not if the user replaced them with their own defs.
        if "sebs" in vars and vars["sebs"] is builtins:
            del vars["sebs"]

        for name, value in vars.items():
            if isinstance(value, Rule) and value.context is context:
                # Set label on rule instance.
                value.label = name
            if name.startswith("_"):
                # Delete private variable.
                del vars[name]

        build_file = BuildFile(vars)
        self.__loaded_files[filename] = (build_file, context)
        return (build_file, context)
Пример #12
0
 def __validate_env_name(self, name):
     typecheck(name, basestring)
     if not name.replace("_", "").isalnum():
         raise DefinitionError(
             "'%s' is not a valid environment  variable name" % name)