# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/.
import os import re from collections.abc import Iterable
class Makefile(object): """Provides an interface for writing simple makefiles
Instances of this class are created, populated with rules, then
written. """
def __init__(self):
self._statements = []
def create_rule(self, targets=()): """
Create a new rule in the makefile for the given targets.
Returns the corresponding Rule instance. """
targets = list(targets) for target in targets: assert isinstance(target, str)
rule = Rule(targets)
self._statements.append(rule) return rule
def add_statement(self, statement): """
Add a raw statement in the makefile. Meant to be used for
simple variable assignments. """ assert isinstance(statement, str)
self._statements.append(statement)
def dump(self, fh, removal_guard=True): """
Dump all the rules to the given file handle. Optionally (and by
default), add guard rules for file removals (empty rules for other
rules' dependencies) """
all_deps = set()
all_targets = set() for statement in self._statements: if isinstance(statement, Rule):
statement.dump(fh)
all_deps.update(statement.dependencies())
all_targets.update(statement.targets()) else:
fh.write("%s\n" % statement) if removal_guard:
guard = Rule(sorted(all_deps - all_targets))
guard.dump(fh)
class _SimpleOrderedSet(object): """
Simple ordered set, specialized for used in Rule below only.
It doesn't expose a complete API, and normalizes path separators
at insertion. """
def __contains__(self, key): return key in self._set
def update(self, iterable): def _add(iterable):
emitted = set() for i in iterable:
i = i.replace(os.sep, "/") if i notin self._set and i notin emitted: yield i
emitted.add(i)
def add_targets(self, targets): """Add additional targets to the rule.""" assert isinstance(targets, Iterable) andnot isinstance(targets, str)
targets = list(targets) for target in targets: assert isinstance(target, str)
self._targets.update(targets) return self
def add_dependencies(self, deps): """Add dependencies to the rule.""" assert isinstance(deps, Iterable) andnot isinstance(deps, str)
deps = list(deps) for dep in deps: assert isinstance(dep, str)
self._dependencies.update(deps) return self
def add_commands(self, commands): """Add commands to the rule.""" assert isinstance(commands, Iterable) andnot isinstance(commands, str)
commands = list(commands) for command in commands: assert isinstance(command, str)
self._commands.extend(commands) return self
def targets(self): """Return an iterator on the rule targets.""" # Ensure the returned iterator is actually just that, an iterator. # Avoids caller fiddling with the set itself. return iter(self._targets)
def dependencies(self): """Return an iterator on the rule dependencies.""" return iter(d for d in self._dependencies if d notin self._targets)
def commands(self): """Return an iterator on the rule commands.""" return iter(self._commands)
def dump(self, fh): """
Dump the rule to the given file handle. """ ifnot self._targets: return
fh.write("%s:" % " ".join(self._targets)) if self._dependencies:
fh.write(" %s" % " ".join(self.dependencies()))
fh.write("\n") for cmd in self._commands:
fh.write("\t%s\n" % cmd)
# colon followed by anything except a slash (Windows path detection)
_depfilesplitter = re.compile(r":(?![\\/])")
def read_dep_makefile(fh): """
Read the file handler containing a dep makefile (simple makefile only
containing dependencies) and returns an iterator of the corresponding Rules
it contains. Ignores removal guard rules. """
rule = "" for line in fh.readlines(): assertnot line.startswith("\t")
line = line.strip() if line.endswith("\\"):
rule += line[:-1] else:
rule += line
split_rule = _depfilesplitter.split(rule, 1) if len(split_rule) > 1 and split_rule[1].strip(): yield Rule(split_rule[0].strip().split()).add_dependencies(
split_rule[1].strip().split()
)
rule = ""
if rule: raise Exception("Makefile finishes with a backslash. Expected more input.")
def write_dep_makefile(fh, target, deps): """
Write a Makefile containing only target's dependencies to the file handle
specified. """
mk = Makefile()
rule = mk.create_rule(targets=[target])
rule.add_dependencies(deps)
mk.dump(fh, removal_guard=True)
¤ Dauer der Verarbeitung: 0.28 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.