# Part of the A-A-P recipe executive: Dependency rules # 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 # A Depend object contains: # targetlist - dictlist of targets # build_attr - dictlist of build attributes (right after the ":") # sourcelist - dictlist of sources # rpstack - RecPos stack for where the commands were defined # commands - string of command lines # builddir - directory where "commands" are to be executed # matchstr - for a rule: the string that matched % # # Illustration: # targetlist : {build_attr} sourcelist # commands import os import os.path import string from Error import * import Filetype from Util import * from Message import * class Depend: def __init__(self, targetlist, build_attr, sourcelist, work, rpstack, commands, builddir = None): self.targetlist = targetlist self.build_attr = build_attr self.sourcelist = sourcelist self.rpstack = rpstack self.commands = commands if builddir is None: self.builddir = os.getcwd() else: self.builddir = builddir self.matchstr = '' # Add nodes for all sources and targets, with a pointer back to the # node. Also carries over the attributes to the node. work.dictlist_nodes(self.targetlist) work.dictlist_nodes(self.sourcelist) def __str__(self): from Dictlist import dictlist2str, dictlistattr2str return (dictlist2str(self.targetlist) + " : " + dictlistattr2str(self.build_attr) + dictlist2str(self.sourcelist) + "\n" + self.commands) def depend_auto(work, node): """Find the implied dependencies for "node". They are returned in node.auto_depend. If "node" changed since last time, regenerate the dependencies.""" # Return quickly when the automatic dependencies were already generated. if not node.auto_depend is None: return # Don't generate automatic dependencies when "autodepend" is "off". if ((work.globals.has_key("autodepend") and work.globals["autodepend"] == "off") or (node.attributes.has_key("autodepend") and node.attributes["autodepend"] == "off")): return # Get the file type. node_name = node.get_name() if node.attributes.has_key("filetype"): ftype = node.attributes["filetype"] else: ftype = Filetype.ft_detect(node_name) if not ftype: msg_depend(_('Unknown type of file, no dependency check for "%s"') % node.short_name()) return # Make the name for the recipe that contains the automatic dependencies for # this node: "node_directory/aap/node_basename.aap" recipe_name = os.path.join(os.path.dirname(node_name), os.path.join("aap", os.path.basename(node_name))) + ".aap" recipe = work.get_node(recipe_name, 1) # Trigger the rule to produce a dependency recipe for this node. from DoBuild import build_autodepend if not build_autodepend(work, recipe, ftype, node): return if not os.path.exists(recipe.name): msg_warning(_('Dependency file was not created: "%s"') % recipe.name) return # Read the generated recipe file. node.auto_depend = read_auto_depend(recipe, node_name) def read_auto_depend(recipe, skipname): """Read a generated recipe file from node "recipe". We only want the part after the ":", the item before it may be wrong (gcc generates foo.o: foo.c foo.h). Ignore "skipname". Don't read the recipe as a normal recipe, that would cause trouble with things we don't want to find in there. """ try: file = open(recipe.name, "r") except: raise UserError, _('Cannot open "%s" for reading.') % recipe.name from RecPos import RecPos from ParsePos import ParsePos rpstack = [ RecPos(recipe.name) ] # create an object to contain the file position fp = ParsePos(rpstack, file = file) fp.nextline() # read the first (and only) line if fp.line is None: raise UserError, _('Nothing to read from "%s".') % recipe.name i = string.find(fp.line, ":") if i < 0: raise UserError, _('No colon found in "%s".') % recipe.name auto_depend = None if i + 1 < fp.line_len: from Dictlist import string2dictlist auto_depend = string2dictlist(rpstack, fp.line[i + 1:]) # Remove the node itself. for k in auto_depend: if k["name"] == skipname: auto_depend.remove(k) # Check for trailing text. fp.nextline() if not fp.line is None: msg_warning(_('Found trailing text in "%s"') % recipe.name) file.close() return auto_depend # vim: set sw=4 sts=4 tw=79 fo+=l: .