# Part of the A-A-P recipe executive: remember the work specified in the recipe # Copyright (C) 2002 Stichting NLnet Labs # Permission to copy and use this file is specified in the file COPYING. # If this file is missing you can find it here: http://www.a-a-p.org/COPYING # Currently a Work object contains these items: # globals - dictionary of global variables from the recipe # The "_work" variable points back to the Work object. # dependencies - list of dependencies # rules - list of rules # autodepends - list of rules used for automatic dependency checking # nodes - dictionary of nodes from the recipes; index is node.name; # normally used to lookup virtual nodes # absnodes - same contents as nodes, but key is the absolute name: # node.absname import os import os.path import string from Node import Node from RecPos import rpcopy import Global from Util import * from Message import * from Remote import is_url from Version import * class Work: def __init__(self): self.globals = {} self.dependencies = [] self.rules = [] self.autodepends = [] self.nodes = {} self.absnodes = {} # This makes it possible to find "work" from the global variables. self.globals["_work"] = self # # Add the default variables. # from Dictlist import listitem2str, dictlist2str # $HOME if os.environ.has_key("HOME"): self.globals["HOME"] = listitem2str(os.environ["HOME"]) else: self.globals["HOME"] = '' # $CACHE cache = [] if os.path.exists("/var/aap/cache"): cache.append({"name" : "/var/aap/cache"}) if os.environ.has_key("HOME"): if os.name == 'nt' or os.name == 'dos' or os.name == 'os2': n = "aap/cache" else: n = ".aap/cache" cache.append({"name" : listitem2str(os.path.join(os.environ["HOME"], n))}) cache.append({"name" : "aap/cache"}) self.globals["CACHE"] = dictlist2str(cache) # $BDIR if os.name == "posix": def fixname(n): """Change all non-letters, non-digits in "n" to underscores and return the result.""" s = '' for c in n: if c in string.letters + string.digits: s = s + c else: s = s + '_' return s sysname, n, release, v, m = os.uname() self.globals["BDIR"] = ("build-" + fixname(sysname) + fixname(release)) else: self.globals["BDIR"] = "build-" + os.name # $OSTYPE n = os.name if os.name == "dos": n = "msdos" elif os.name == "nt": n = "mswin" self.globals["OSTYPE"] = n # $MESSAGE msg_init(self.globals) # $SRCPATH (to be evaluated when used) self.globals["SRCPATH"] = ". $BDIR" self.globals["$SRCPATH"] = 1 # $cache_update self.globals["cache_update"] = "12 hour" # $aapversion self.globals["aapversion"] = string.atoi(version_number) # Add values set in the command line arguments for k in Global.cmd_args.values.keys(): add = 1 for c in k: if not varchar(c): add = 0 break if add: self.globals[k] = Global.cmd_args.values[k] def add_dependency(self, rpstack, dep, has_commands): """Add a new dependency. This takes care of creating nodes for the sources and targets and setting the dependency for the target nodes if "has_commands" is non-zero.""" self.dependencies.append(dep); # For each target let the Node know this Depend uses it. If there are # commands also let it know this Depend builds it. for item in dep.targetlist: n = item["_node"] n.add_dependency(dep) if has_commands: if (n.get_first_build_dependency() and not n.name in Globals.virtual_targets): from Process import recipe_error recipe_error(rpstack, _('Multiple build commands for target "%s"') % item["name"]) n.add_build_dependency(dep) def dictlist_nodes(self, dictlist): """Make sure there is a global node for each item in "dictlist" and add a reference to the node in the dictlist item. Carry over specific attributes to the node.""" for item in dictlist: n = self.get_node(item["name"], 1) n.set_sticky_attributes(item) item["_node"] = n def add_node(self, node): """Add a Node to the global list of nodes. The Node is the target and/or source in a dependency.""" self.nodes[node.name] = node self.absnodes[node.absname] = node def find_node(self, name, absname = None): """Find an existing Node by name or absname. For a virtual node "absname" should be an empty string.""" # First try the absolute name, it's more reliable. Must not be used # for virtual nodes though. # Then check the short name, only for virtual nodes (may have been used # in another recipe). if absname is None: absname = os.path.abspath(name) if absname and self.absnodes.has_key(absname): return self.absnodes[absname] if self.nodes.has_key(name): n = self.nodes[name] if n.get_virtual(): return n return None def get_node(self, name, add = 0, dict = {}): """Find a Node by name, create a new one if necessary. A new node is added to the global list if "add" is non-zero. When "dict" is given, check for attributes that apply to the Node.""" n = self.find_node(name) if n is None: n = Node(name) if add: self.add_node(n) elif not (os.path.isabs(name) or is_url(name)): # Remember the relative name was used, this matters for where # signatures are stored. n.relative_name() n.set_attributes(dict) return n def add_dictlist_nodes(self, dictlist): """Add nodes for all items in "dictlist". Also carry over attributes to the Node.""" for item in dictlist: self.get_node(item["name"], 1, item) def add_node_attributes(self, dictlist): """Add attributes from existing nodes to the items in "dictlist". Used for sources and targets of executed dependencies and rules. Existing attributes are not overwritten.""" for item in dictlist: node = self.find_node(item["name"]) if node: for k in node.attributes.keys(): if not item.has_key(k): item[k] = node.attributes[k] def add_rule(self, rule): self.rules.append(rule); def add_autodepend(self, rule): self.autodepends.append(rule); def print_comments(self): """Print comments for all dependencies with a comment and for standard targets.""" if not self.dependencies: msg_print(_("No dependencies in recipe")) for d in self.dependencies: for t in d.targetlist: if t.has_key("comment"): msg_print('target "%s": %s' % (t["name"], t["comment"])) elif t["name"] in Global.virtual_targets: msg_print((_('target "%s": standard target, no comment specified') % t["name"])) def getwork(globals): """Return the Work object that contains 'globals'.""" return globals["_work"] def setrpstack(globals, rpstack): """Set the RecPos stack in 'globals'.""" globals["_rpstack"] = rpstack def getrpstack(globals, line_nr = -1): """Return the RecPos stack in 'globals'. When a line number is specified: Make a copy and set the line number for the item at the top of the stack.""" rp = globals["_rpstack"] if line_nr >= 0: rp = rpcopy(rp, line_nr) return rp # vim: set sw=4 sts=4 tw=79 fo+=l: .