17750ad47SMarcel Moolenaar#!/usr/bin/env python 27750ad47SMarcel Moolenaar 37750ad47SMarcel Moolenaar""" 47750ad47SMarcel MoolenaarThis script parses each "meta" file and extracts the 57750ad47SMarcel Moolenaarinformation needed to deduce build and src dependencies. 67750ad47SMarcel Moolenaar 77750ad47SMarcel MoolenaarIt works much the same as the original shell script, but is 87750ad47SMarcel Moolenaar*much* more efficient. 97750ad47SMarcel Moolenaar 107750ad47SMarcel MoolenaarThe parsing work is handled by the class MetaFile. 117750ad47SMarcel MoolenaarWe only pay attention to a subset of the information in the 127750ad47SMarcel Moolenaar"meta" files. Specifically: 137750ad47SMarcel Moolenaar 147750ad47SMarcel Moolenaar'CWD' to initialize our notion. 157750ad47SMarcel Moolenaar 167750ad47SMarcel Moolenaar'C' to track chdir(2) on a per process basis 177750ad47SMarcel Moolenaar 187750ad47SMarcel Moolenaar'R' files read are what we really care about. 197750ad47SMarcel Moolenaar directories read, provide a clue to resolving 207750ad47SMarcel Moolenaar subsequent relative paths. That is if we cannot find 217750ad47SMarcel Moolenaar them relative to 'cwd', we check relative to the last 227750ad47SMarcel Moolenaar dir read. 237750ad47SMarcel Moolenaar 247750ad47SMarcel Moolenaar'W' files opened for write or read-write, 257750ad47SMarcel Moolenaar for filemon V3 and earlier. 267750ad47SMarcel Moolenaar 277750ad47SMarcel Moolenaar'E' files executed. 287750ad47SMarcel Moolenaar 297750ad47SMarcel Moolenaar'L' files linked 307750ad47SMarcel Moolenaar 317750ad47SMarcel Moolenaar'V' the filemon version, this record is used as a clue 327750ad47SMarcel Moolenaar that we have reached the interesting bit. 337750ad47SMarcel Moolenaar 347750ad47SMarcel Moolenaar""" 357750ad47SMarcel Moolenaar 367750ad47SMarcel Moolenaar""" 377750ad47SMarcel MoolenaarRCSid: 38*4ed4429cSSimon J. Gerraty $Id: meta2deps.py,v 1.8 2013/02/10 19:21:46 sjg Exp $ 397750ad47SMarcel Moolenaar 40*4ed4429cSSimon J. Gerraty Copyright (c) 2011-2013, Juniper Networks, Inc. 41*4ed4429cSSimon J. Gerraty All rights reserved. 427750ad47SMarcel Moolenaar 437750ad47SMarcel Moolenaar Redistribution and use in source and binary forms, with or without 447750ad47SMarcel Moolenaar modification, are permitted provided that the following conditions 457750ad47SMarcel Moolenaar are met: 467750ad47SMarcel Moolenaar 1. Redistributions of source code must retain the above copyright 477750ad47SMarcel Moolenaar notice, this list of conditions and the following disclaimer. 487750ad47SMarcel Moolenaar 2. Redistributions in binary form must reproduce the above copyright 497750ad47SMarcel Moolenaar notice, this list of conditions and the following disclaimer in the 507750ad47SMarcel Moolenaar documentation and/or other materials provided with the distribution. 517750ad47SMarcel Moolenaar 527750ad47SMarcel Moolenaar THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 537750ad47SMarcel Moolenaar "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 547750ad47SMarcel Moolenaar LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 557750ad47SMarcel Moolenaar A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 567750ad47SMarcel Moolenaar OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 577750ad47SMarcel Moolenaar SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 587750ad47SMarcel Moolenaar LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 597750ad47SMarcel Moolenaar DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 607750ad47SMarcel Moolenaar THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 617750ad47SMarcel Moolenaar (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 627750ad47SMarcel Moolenaar OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 637750ad47SMarcel Moolenaar 647750ad47SMarcel Moolenaar""" 657750ad47SMarcel Moolenaar 667750ad47SMarcel Moolenaarimport os, re, sys 677750ad47SMarcel Moolenaar 687750ad47SMarcel Moolenaardef getv(dict, key, d=None): 697750ad47SMarcel Moolenaar """Lookup key in dict and return value or the supplied default.""" 707750ad47SMarcel Moolenaar if key in dict: 717750ad47SMarcel Moolenaar return dict[key] 727750ad47SMarcel Moolenaar return d 737750ad47SMarcel Moolenaar 747750ad47SMarcel Moolenaardef resolve(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr): 757750ad47SMarcel Moolenaar """ 767750ad47SMarcel Moolenaar Return an absolute path, resolving via cwd or last_dir if needed. 777750ad47SMarcel Moolenaar """ 787750ad47SMarcel Moolenaar if path.endswith('/.'): 797750ad47SMarcel Moolenaar path = path[0:-2] 807750ad47SMarcel Moolenaar if path[0] == '/': 817750ad47SMarcel Moolenaar return path 827750ad47SMarcel Moolenaar if path == '.': 837750ad47SMarcel Moolenaar return cwd 847750ad47SMarcel Moolenaar if path.startswith('./'): 857750ad47SMarcel Moolenaar return cwd + path[1:] 867750ad47SMarcel Moolenaar if last_dir == cwd: 877750ad47SMarcel Moolenaar last_dir = None 887750ad47SMarcel Moolenaar for d in [last_dir, cwd]: 897750ad47SMarcel Moolenaar if not d: 907750ad47SMarcel Moolenaar continue 917750ad47SMarcel Moolenaar p = '/'.join([d,path]) 927750ad47SMarcel Moolenaar if debug > 2: 937750ad47SMarcel Moolenaar print >> debug_out, "looking for:", p, 947750ad47SMarcel Moolenaar if not os.path.exists(p): 957750ad47SMarcel Moolenaar if debug > 2: 967750ad47SMarcel Moolenaar print >> debug_out, "nope" 977750ad47SMarcel Moolenaar p = None 987750ad47SMarcel Moolenaar continue 997750ad47SMarcel Moolenaar if debug > 2: 1007750ad47SMarcel Moolenaar print >> debug_out, "found:", p 1017750ad47SMarcel Moolenaar return p 1027750ad47SMarcel Moolenaar return None 1037750ad47SMarcel Moolenaar 1047750ad47SMarcel Moolenaardef abspath(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr): 1057750ad47SMarcel Moolenaar """ 1067750ad47SMarcel Moolenaar Return an absolute path, resolving via cwd or last_dir if needed. 1077750ad47SMarcel Moolenaar this gets called a lot, so we try to avoid calling realpath 1087750ad47SMarcel Moolenaar until we know we have something. 1097750ad47SMarcel Moolenaar """ 1107750ad47SMarcel Moolenaar path = resolve(path, cwd, last_dir, debug, debug_out) 1117750ad47SMarcel Moolenaar if path and (path.find('./') > 0 or 1127750ad47SMarcel Moolenaar path.endswith('/..') or 1137750ad47SMarcel Moolenaar os.path.islink(path)): 1147750ad47SMarcel Moolenaar return os.path.realpath(path) 1157750ad47SMarcel Moolenaar return path 1167750ad47SMarcel Moolenaar 1177750ad47SMarcel Moolenaardef sort_unique(list, cmp=None, key=None, reverse=False): 1187750ad47SMarcel Moolenaar list.sort(cmp, key, reverse) 1197750ad47SMarcel Moolenaar nl = [] 1207750ad47SMarcel Moolenaar le = None 1217750ad47SMarcel Moolenaar for e in list: 1227750ad47SMarcel Moolenaar if e == le: 1237750ad47SMarcel Moolenaar continue 1247750ad47SMarcel Moolenaar nl.append(e) 1257750ad47SMarcel Moolenaar return nl 1267750ad47SMarcel Moolenaar 1277750ad47SMarcel Moolenaarclass MetaFile: 1287750ad47SMarcel Moolenaar """class to parse meta files generated by bmake.""" 1297750ad47SMarcel Moolenaar 1307750ad47SMarcel Moolenaar conf = None 1317750ad47SMarcel Moolenaar dirdep_re = None 1327750ad47SMarcel Moolenaar host_target = None 1337750ad47SMarcel Moolenaar srctops = [] 1347750ad47SMarcel Moolenaar objroots = [] 1357750ad47SMarcel Moolenaar 1367750ad47SMarcel Moolenaar seen = {} 1377750ad47SMarcel Moolenaar obj_deps = [] 1387750ad47SMarcel Moolenaar src_deps = [] 1397750ad47SMarcel Moolenaar file_deps = [] 1407750ad47SMarcel Moolenaar 1417750ad47SMarcel Moolenaar def __init__(self, name, conf={}): 1427750ad47SMarcel Moolenaar """if name is set we will parse it now. 1437750ad47SMarcel Moolenaar conf can have the follwing keys: 1447750ad47SMarcel Moolenaar 1457750ad47SMarcel Moolenaar SRCTOPS list of tops of the src tree(s). 1467750ad47SMarcel Moolenaar 1477750ad47SMarcel Moolenaar CURDIR the src directory 'bmake' was run from. 1487750ad47SMarcel Moolenaar 1497750ad47SMarcel Moolenaar RELDIR the relative path from SRCTOP to CURDIR 1507750ad47SMarcel Moolenaar 1517750ad47SMarcel Moolenaar MACHINE the machine we built for. 1527750ad47SMarcel Moolenaar set to 'none' if we are not cross-building. 1537750ad47SMarcel Moolenaar 1547750ad47SMarcel Moolenaar HOST_TARGET 1557750ad47SMarcel Moolenaar when we build for the psuedo machine 'host' 1567750ad47SMarcel Moolenaar the object tree uses HOST_TARGET rather than MACHINE. 1577750ad47SMarcel Moolenaar 1587750ad47SMarcel Moolenaar OBJROOTS a list of the common prefix for all obj dirs it might 1597750ad47SMarcel Moolenaar end in '/' or '-'. 1607750ad47SMarcel Moolenaar 1617750ad47SMarcel Moolenaar DPDEPS names an optional file to which per file dependencies 1627750ad47SMarcel Moolenaar will be appended. 1637750ad47SMarcel Moolenaar For example if 'some/path/foo.h' is read from SRCTOP 1647750ad47SMarcel Moolenaar then 'DPDEPS_some/path/foo.h +=' "RELDIR" is output. 1657750ad47SMarcel Moolenaar This can allow 'bmake' to learn all the dirs within 1667750ad47SMarcel Moolenaar the tree that depend on 'foo.h' 1677750ad47SMarcel Moolenaar 1687750ad47SMarcel Moolenaar debug desired debug level 1697750ad47SMarcel Moolenaar 1707750ad47SMarcel Moolenaar debug_out open file to send debug output to (sys.stderr) 1717750ad47SMarcel Moolenaar 1727750ad47SMarcel Moolenaar """ 1737750ad47SMarcel Moolenaar 1747750ad47SMarcel Moolenaar self.name = name 1757750ad47SMarcel Moolenaar self.debug = getv(conf, 'debug', 0) 1767750ad47SMarcel Moolenaar self.debug_out = getv(conf, 'debug_out', sys.stderr) 1777750ad47SMarcel Moolenaar 178*4ed4429cSSimon J. Gerraty self.machine = getv(conf, 'MACHINE', '') 179*4ed4429cSSimon J. Gerraty 1807750ad47SMarcel Moolenaar if not self.conf: 1817750ad47SMarcel Moolenaar # some of the steps below we want to do only once 1827750ad47SMarcel Moolenaar self.conf = conf 1837750ad47SMarcel Moolenaar self.host_target = getv(conf, 'HOST_TARGET') 1847750ad47SMarcel Moolenaar for srctop in getv(conf, 'SRCTOPS', []): 1857750ad47SMarcel Moolenaar if srctop[-1] != '/': 1867750ad47SMarcel Moolenaar srctop += '/' 1877750ad47SMarcel Moolenaar if not srctop in self.srctops: 1887750ad47SMarcel Moolenaar self.srctops.append(srctop) 189fbc1b149SSimon J. Gerraty _srctop = os.path.realpath(srctop) 190fbc1b149SSimon J. Gerraty if _srctop[-1] != '/': 191fbc1b149SSimon J. Gerraty _srctop += '/' 192fbc1b149SSimon J. Gerraty if not _srctop in self.srctops: 193fbc1b149SSimon J. Gerraty self.srctops.append(_srctop) 1947750ad47SMarcel Moolenaar 1957750ad47SMarcel Moolenaar for objroot in getv(conf, 'OBJROOTS', []): 196*4ed4429cSSimon J. Gerraty for e in ['/' + self.machine, '/' + self.machine + '/']: 197*4ed4429cSSimon J. Gerraty if objroot.endswith(e): 198*4ed4429cSSimon J. Gerraty # this is not what we want - fix it 199*4ed4429cSSimon J. Gerraty objroot = objroot[0:-len(e)] 200*4ed4429cSSimon J. Gerraty if e.endswith('/'): 201*4ed4429cSSimon J. Gerraty objroot += '/' 2027750ad47SMarcel Moolenaar if not objroot in self.objroots: 2037750ad47SMarcel Moolenaar self.objroots.append(objroot) 2047750ad47SMarcel Moolenaar _objroot = os.path.realpath(objroot) 2057750ad47SMarcel Moolenaar if objroot[-1] == '/': 2067750ad47SMarcel Moolenaar _objroot += '/' 2077750ad47SMarcel Moolenaar if not _objroot in self.objroots: 2087750ad47SMarcel Moolenaar self.objroots.append(_objroot) 2097750ad47SMarcel Moolenaar 210*4ed4429cSSimon J. Gerraty # we want the longest match 211*4ed4429cSSimon J. Gerraty self.srctops.sort(reverse=True) 212*4ed4429cSSimon J. Gerraty self.objroots.sort(reverse=True) 213*4ed4429cSSimon J. Gerraty 2147750ad47SMarcel Moolenaar if self.debug: 2157750ad47SMarcel Moolenaar print >> self.debug_out, "host_target=", self.host_target 2167750ad47SMarcel Moolenaar print >> self.debug_out, "srctops=", self.srctops 2177750ad47SMarcel Moolenaar print >> self.debug_out, "objroots=", self.objroots 2187750ad47SMarcel Moolenaar 2197750ad47SMarcel Moolenaar self.dirdep_re = re.compile(r'([^/]+)/(.+)') 2207750ad47SMarcel Moolenaar 2217750ad47SMarcel Moolenaar self.curdir = getv(conf, 'CURDIR') 2227750ad47SMarcel Moolenaar self.reldir = getv(conf, 'RELDIR') 2237750ad47SMarcel Moolenaar self.dpdeps = getv(conf, 'DPDEPS') 2247750ad47SMarcel Moolenaar if self.dpdeps and not self.reldir: 2257750ad47SMarcel Moolenaar if self.debug: 2267750ad47SMarcel Moolenaar print >> self.debug_out, "need reldir:", 2277750ad47SMarcel Moolenaar if self.curdir: 2287750ad47SMarcel Moolenaar srctop = self.find_top(self.curdir, self.srctops) 2297750ad47SMarcel Moolenaar if srctop: 2307750ad47SMarcel Moolenaar self.reldir = self.curdir.replace(srctop,'') 2317750ad47SMarcel Moolenaar if self.debug: 2327750ad47SMarcel Moolenaar print >> self.debug_out, self.reldir 2337750ad47SMarcel Moolenaar if not self.reldir: 2347750ad47SMarcel Moolenaar self.dpdeps = None # we cannot do it? 2357750ad47SMarcel Moolenaar 2367750ad47SMarcel Moolenaar if name: 2377750ad47SMarcel Moolenaar self.parse() 2387750ad47SMarcel Moolenaar 2397750ad47SMarcel Moolenaar def reset(self): 2407750ad47SMarcel Moolenaar """reset state if we are being passed meta files from multiple directories.""" 2417750ad47SMarcel Moolenaar self.seen = {} 2427750ad47SMarcel Moolenaar self.obj_deps = [] 2437750ad47SMarcel Moolenaar self.src_deps = [] 2447750ad47SMarcel Moolenaar self.file_deps = [] 2457750ad47SMarcel Moolenaar 2467750ad47SMarcel Moolenaar def dirdeps(self, sep='\n'): 2477750ad47SMarcel Moolenaar """return DIRDEPS""" 2487750ad47SMarcel Moolenaar return sep.strip() + sep.join(self.obj_deps) 2497750ad47SMarcel Moolenaar 2507750ad47SMarcel Moolenaar def src_dirdeps(self, sep='\n'): 2517750ad47SMarcel Moolenaar """return SRC_DIRDEPS""" 2527750ad47SMarcel Moolenaar return sep.strip() + sep.join(self.src_deps) 2537750ad47SMarcel Moolenaar 2547750ad47SMarcel Moolenaar def file_depends(self, out=None): 2557750ad47SMarcel Moolenaar """Append DPDEPS_${file} += ${RELDIR} 2567750ad47SMarcel Moolenaar for each file we saw, to the output file.""" 2577750ad47SMarcel Moolenaar if not self.reldir: 2587750ad47SMarcel Moolenaar return None 2597750ad47SMarcel Moolenaar for f in sort_unique(self.file_deps): 2607750ad47SMarcel Moolenaar print >> out, 'DPDEPS_%s += %s' % (f, self.reldir) 2617750ad47SMarcel Moolenaar 2627750ad47SMarcel Moolenaar def seenit(self, dir): 2637750ad47SMarcel Moolenaar """rememer that we have seen dir.""" 2647750ad47SMarcel Moolenaar self.seen[dir] = 1 2657750ad47SMarcel Moolenaar 2667750ad47SMarcel Moolenaar def add(self, list, data, clue=''): 2677750ad47SMarcel Moolenaar """add data to list if it isn't already there.""" 2687750ad47SMarcel Moolenaar if data not in list: 2697750ad47SMarcel Moolenaar list.append(data) 2707750ad47SMarcel Moolenaar if self.debug: 2717750ad47SMarcel Moolenaar print >> self.debug_out, "%s: %sAdd: %s" % (self.name, clue, data) 2727750ad47SMarcel Moolenaar 2737750ad47SMarcel Moolenaar def find_top(self, path, list): 2747750ad47SMarcel Moolenaar """the logical tree may be split accross multiple trees""" 2757750ad47SMarcel Moolenaar for top in list: 2767750ad47SMarcel Moolenaar if path.startswith(top): 2777750ad47SMarcel Moolenaar if self.debug > 2: 2787750ad47SMarcel Moolenaar print >> self.debug_out, "found in", top 2797750ad47SMarcel Moolenaar return top 2807750ad47SMarcel Moolenaar return None 2817750ad47SMarcel Moolenaar 2827750ad47SMarcel Moolenaar def find_obj(self, objroot, dir, path, input): 2837750ad47SMarcel Moolenaar """return path within objroot, taking care of .dirdep files""" 2847750ad47SMarcel Moolenaar ddep = None 2857750ad47SMarcel Moolenaar for ddepf in [path + '.dirdep', dir + '/.dirdep']: 2867750ad47SMarcel Moolenaar if not ddep and os.path.exists(ddepf): 2877750ad47SMarcel Moolenaar ddep = open(ddepf, 'rb').readline().strip('# \n') 2887750ad47SMarcel Moolenaar if self.debug > 1: 2897750ad47SMarcel Moolenaar print >> self.debug_out, "found %s: %s\n" % (ddepf, ddep) 2907750ad47SMarcel Moolenaar if ddep.endswith(self.machine): 2917750ad47SMarcel Moolenaar ddep = ddep[0:-(1+len(self.machine))] 2927750ad47SMarcel Moolenaar 2937750ad47SMarcel Moolenaar if not ddep: 2947750ad47SMarcel Moolenaar # no .dirdeps, so remember that we've seen the raw input 2957750ad47SMarcel Moolenaar self.seenit(input) 2967750ad47SMarcel Moolenaar self.seenit(dir) 2977750ad47SMarcel Moolenaar if self.machine == 'none': 2987750ad47SMarcel Moolenaar if dir.startswith(objroot): 2997750ad47SMarcel Moolenaar return dir.replace(objroot,'') 3007750ad47SMarcel Moolenaar return None 3017750ad47SMarcel Moolenaar m = self.dirdep_re.match(dir.replace(objroot,'')) 3027750ad47SMarcel Moolenaar if m: 3037750ad47SMarcel Moolenaar ddep = m.group(2) 3047750ad47SMarcel Moolenaar dmachine = m.group(1) 3057750ad47SMarcel Moolenaar if dmachine != self.machine: 3067750ad47SMarcel Moolenaar if not (self.machine == 'host' and 3077750ad47SMarcel Moolenaar dmachine == self.host_target): 3087750ad47SMarcel Moolenaar if self.debug > 2: 3097750ad47SMarcel Moolenaar print >> self.debug_out, "adding .%s to %s" % (dmachine, ddep) 3107750ad47SMarcel Moolenaar ddep += '.' + dmachine 3117750ad47SMarcel Moolenaar 3127750ad47SMarcel Moolenaar return ddep 3137750ad47SMarcel Moolenaar 3147750ad47SMarcel Moolenaar def parse(self, name=None, file=None): 3157750ad47SMarcel Moolenaar """A meta file looks like: 3167750ad47SMarcel Moolenaar 3177750ad47SMarcel Moolenaar # Meta data file "path" 3187750ad47SMarcel Moolenaar CMD "command-line" 3197750ad47SMarcel Moolenaar CWD "cwd" 3207750ad47SMarcel Moolenaar TARGET "target" 3217750ad47SMarcel Moolenaar -- command output -- 3227750ad47SMarcel Moolenaar -- filemon acquired metadata -- 3237750ad47SMarcel Moolenaar # buildmon version 3 3247750ad47SMarcel Moolenaar V 3 3257750ad47SMarcel Moolenaar C "pid" "cwd" 3267750ad47SMarcel Moolenaar E "pid" "path" 3277750ad47SMarcel Moolenaar F "pid" "child" 3287750ad47SMarcel Moolenaar R "pid" "path" 3297750ad47SMarcel Moolenaar W "pid" "path" 3307750ad47SMarcel Moolenaar X "pid" "status" 3317750ad47SMarcel Moolenaar D "pid" "path" 3327750ad47SMarcel Moolenaar L "pid" "src" "target" 3337750ad47SMarcel Moolenaar M "pid" "old" "new" 3347750ad47SMarcel Moolenaar S "pid" "path" 3357750ad47SMarcel Moolenaar # Bye bye 3367750ad47SMarcel Moolenaar 3377750ad47SMarcel Moolenaar We go to some effort to avoid processing a dependency more than once. 3387750ad47SMarcel Moolenaar Of the above record types only C,E,F,L,R,V and W are of interest. 3397750ad47SMarcel Moolenaar """ 3407750ad47SMarcel Moolenaar 3417750ad47SMarcel Moolenaar version = 0 # unknown 3427750ad47SMarcel Moolenaar if name: 3437750ad47SMarcel Moolenaar self.name = name; 3447750ad47SMarcel Moolenaar if file: 3457750ad47SMarcel Moolenaar f = file 3467750ad47SMarcel Moolenaar cwd = last_dir = self.cwd 3477750ad47SMarcel Moolenaar else: 3487750ad47SMarcel Moolenaar f = open(self.name, 'rb') 3497750ad47SMarcel Moolenaar skip = True 3507750ad47SMarcel Moolenaar pid_cwd = {} 3517750ad47SMarcel Moolenaar pid_last_dir = {} 3527750ad47SMarcel Moolenaar last_pid = 0 3537750ad47SMarcel Moolenaar 3547750ad47SMarcel Moolenaar if self.curdir: 3557750ad47SMarcel Moolenaar self.seenit(self.curdir) # we ignore this 3567750ad47SMarcel Moolenaar 3577750ad47SMarcel Moolenaar interesting = 'CEFLRV' 3587750ad47SMarcel Moolenaar for line in f: 3597750ad47SMarcel Moolenaar # ignore anything we don't care about 3607750ad47SMarcel Moolenaar if not line[0] in interesting: 3617750ad47SMarcel Moolenaar continue 3627750ad47SMarcel Moolenaar if self.debug > 2: 3637750ad47SMarcel Moolenaar print >> self.debug_out, "input:", line, 3647750ad47SMarcel Moolenaar w = line.split() 3657750ad47SMarcel Moolenaar 3667750ad47SMarcel Moolenaar if skip: 3677750ad47SMarcel Moolenaar if w[0] == 'V': 3687750ad47SMarcel Moolenaar skip = False 3697750ad47SMarcel Moolenaar version = int(w[1]) 3707750ad47SMarcel Moolenaar """ 3717750ad47SMarcel Moolenaar if version < 4: 3727750ad47SMarcel Moolenaar # we cannot ignore 'W' records 3737750ad47SMarcel Moolenaar # as they may be 'rw' 3747750ad47SMarcel Moolenaar interesting += 'W' 3757750ad47SMarcel Moolenaar """ 3767750ad47SMarcel Moolenaar elif w[0] == 'CWD': 3777750ad47SMarcel Moolenaar self.cwd = cwd = last_dir = w[1] 3787750ad47SMarcel Moolenaar self.seenit(cwd) # ignore this 3797750ad47SMarcel Moolenaar if self.debug: 3807750ad47SMarcel Moolenaar print >> self.debug_out, "%s: CWD=%s" % (self.name, cwd) 3817750ad47SMarcel Moolenaar continue 3827750ad47SMarcel Moolenaar 3837750ad47SMarcel Moolenaar pid = int(w[1]) 3847750ad47SMarcel Moolenaar if pid != last_pid: 3857750ad47SMarcel Moolenaar if last_pid: 3867750ad47SMarcel Moolenaar pid_cwd[last_pid] = cwd 3877750ad47SMarcel Moolenaar pid_last_dir[last_pid] = last_dir 3887750ad47SMarcel Moolenaar cwd = getv(pid_cwd, pid, self.cwd) 3897750ad47SMarcel Moolenaar last_dir = getv(pid_last_dir, pid, self.cwd) 3907750ad47SMarcel Moolenaar last_pid = pid 3917750ad47SMarcel Moolenaar 3927750ad47SMarcel Moolenaar # process operations 3937750ad47SMarcel Moolenaar if w[0] == 'F': 3947750ad47SMarcel Moolenaar npid = int(w[2]) 3957750ad47SMarcel Moolenaar pid_cwd[npid] = cwd 3967750ad47SMarcel Moolenaar pid_last_dir[npid] = cwd 3977750ad47SMarcel Moolenaar last_pid = npid 3987750ad47SMarcel Moolenaar continue 3997750ad47SMarcel Moolenaar elif w[0] == 'C': 4007750ad47SMarcel Moolenaar cwd = abspath(w[2], cwd, None, self.debug, self.debug_out) 4017750ad47SMarcel Moolenaar if cwd.endswith('/.'): 4027750ad47SMarcel Moolenaar cwd = cwd[0:-2] 4037750ad47SMarcel Moolenaar last_dir = cwd 4047750ad47SMarcel Moolenaar if self.debug > 1: 4057750ad47SMarcel Moolenaar print >> self.debug_out, "cwd=", cwd 4067750ad47SMarcel Moolenaar continue 4077750ad47SMarcel Moolenaar 4087750ad47SMarcel Moolenaar if w[2] in self.seen: 4097750ad47SMarcel Moolenaar if self.debug > 2: 4107750ad47SMarcel Moolenaar print >> self.debug_out, "seen:", w[2] 4117750ad47SMarcel Moolenaar continue 4127750ad47SMarcel Moolenaar # file operations 4137750ad47SMarcel Moolenaar if w[0] in 'ML': 4147750ad47SMarcel Moolenaar path = w[2].strip("'") 4157750ad47SMarcel Moolenaar else: 4167750ad47SMarcel Moolenaar path = w[2] 417fbc1b149SSimon J. Gerraty # we are never interested in .dirdep files as dependencies 418fbc1b149SSimon J. Gerraty if path.endswith('.dirdep'): 419fbc1b149SSimon J. Gerraty continue 4207750ad47SMarcel Moolenaar # we don't want to resolve the last component if it is 4217750ad47SMarcel Moolenaar # a symlink 4227750ad47SMarcel Moolenaar path = resolve(path, cwd, last_dir, self.debug, self.debug_out) 4237750ad47SMarcel Moolenaar if not path: 4247750ad47SMarcel Moolenaar continue 4257750ad47SMarcel Moolenaar dir,base = os.path.split(path) 4267750ad47SMarcel Moolenaar if dir in self.seen: 4277750ad47SMarcel Moolenaar if self.debug > 2: 4287750ad47SMarcel Moolenaar print >> self.debug_out, "seen:", dir 4297750ad47SMarcel Moolenaar continue 4307750ad47SMarcel Moolenaar # we can have a path in an objdir which is a link 4317750ad47SMarcel Moolenaar # to the src dir, we may need to add dependencies for each 4327750ad47SMarcel Moolenaar rdir = dir 4337750ad47SMarcel Moolenaar dir = abspath(dir, cwd, last_dir, self.debug, self.debug_out) 4347750ad47SMarcel Moolenaar if rdir == dir or rdir.find('./') > 0: 4357750ad47SMarcel Moolenaar rdir = None 4367750ad47SMarcel Moolenaar # now put path back together 4377750ad47SMarcel Moolenaar path = '/'.join([dir,base]) 4387750ad47SMarcel Moolenaar if self.debug > 1: 4397750ad47SMarcel Moolenaar print >> self.debug_out, "raw=%s rdir=%s dir=%s path=%s" % (w[2], rdir, dir, path) 4407750ad47SMarcel Moolenaar if w[0] in 'SRWL': 4417750ad47SMarcel Moolenaar if w[0] == 'W' and path.endswith('.dirdep'): 4427750ad47SMarcel Moolenaar continue 4437750ad47SMarcel Moolenaar if path in [last_dir, cwd, self.cwd, self.curdir]: 4447750ad47SMarcel Moolenaar if self.debug > 1: 4457750ad47SMarcel Moolenaar print >> self.debug_out, "skipping:", path 4467750ad47SMarcel Moolenaar continue 4477750ad47SMarcel Moolenaar if os.path.isdir(path): 4487750ad47SMarcel Moolenaar if w[0] in 'RW': 4497750ad47SMarcel Moolenaar last_dir = path; 4507750ad47SMarcel Moolenaar if self.debug > 1: 4517750ad47SMarcel Moolenaar print >> self.debug_out, "ldir=", last_dir 4527750ad47SMarcel Moolenaar continue 4537750ad47SMarcel Moolenaar 4547750ad47SMarcel Moolenaar if w[0] in 'REWML': 4557750ad47SMarcel Moolenaar # finally, we get down to it 4567750ad47SMarcel Moolenaar if dir == self.cwd or dir == self.curdir: 4577750ad47SMarcel Moolenaar continue 4587750ad47SMarcel Moolenaar srctop = self.find_top(path, self.srctops) 4597750ad47SMarcel Moolenaar if srctop: 4607750ad47SMarcel Moolenaar if self.dpdeps: 4617750ad47SMarcel Moolenaar self.add(self.file_deps, path.replace(srctop,''), 'file') 4627750ad47SMarcel Moolenaar self.add(self.src_deps, dir.replace(srctop,''), 'src') 4637750ad47SMarcel Moolenaar self.seenit(w[2]) 4647750ad47SMarcel Moolenaar self.seenit(dir) 4657750ad47SMarcel Moolenaar if rdir and not rdir.startswith(srctop): 4667750ad47SMarcel Moolenaar dir = rdir # for below 4677750ad47SMarcel Moolenaar rdir = None 4687750ad47SMarcel Moolenaar else: 4697750ad47SMarcel Moolenaar continue 4707750ad47SMarcel Moolenaar 4717750ad47SMarcel Moolenaar objroot = None 4727750ad47SMarcel Moolenaar for dir in [dir,rdir]: 4737750ad47SMarcel Moolenaar if not dir: 4747750ad47SMarcel Moolenaar continue 4757750ad47SMarcel Moolenaar objroot = self.find_top(dir, self.objroots) 4767750ad47SMarcel Moolenaar if objroot: 4777750ad47SMarcel Moolenaar break 4787750ad47SMarcel Moolenaar if objroot: 4797750ad47SMarcel Moolenaar ddep = self.find_obj(objroot, dir, path, w[2]) 4807750ad47SMarcel Moolenaar if ddep: 4817750ad47SMarcel Moolenaar self.add(self.obj_deps, ddep, 'obj') 4827750ad47SMarcel Moolenaar else: 4837750ad47SMarcel Moolenaar # don't waste time looking again 4847750ad47SMarcel Moolenaar self.seenit(w[2]) 4857750ad47SMarcel Moolenaar self.seenit(dir) 4867750ad47SMarcel Moolenaar if not file: 4877750ad47SMarcel Moolenaar f.close() 4887750ad47SMarcel Moolenaar 4897750ad47SMarcel Moolenaar 4907750ad47SMarcel Moolenaardef main(argv, klass=MetaFile, xopts='', xoptf=None): 4917750ad47SMarcel Moolenaar """Simple driver for class MetaFile. 4927750ad47SMarcel Moolenaar 4937750ad47SMarcel Moolenaar Usage: 4947750ad47SMarcel Moolenaar script [options] [key=value ...] "meta" ... 4957750ad47SMarcel Moolenaar 4967750ad47SMarcel Moolenaar Options and key=value pairs contribute to the 4977750ad47SMarcel Moolenaar dictionary passed to MetaFile. 4987750ad47SMarcel Moolenaar 4997750ad47SMarcel Moolenaar -S "SRCTOP" 5007750ad47SMarcel Moolenaar add "SRCTOP" to the "SRCTOPS" list. 5017750ad47SMarcel Moolenaar 5027750ad47SMarcel Moolenaar -C "CURDIR" 5037750ad47SMarcel Moolenaar 5047750ad47SMarcel Moolenaar -O "OBJROOT" 5057750ad47SMarcel Moolenaar add "OBJROOT" to the "OBJROOTS" list. 5067750ad47SMarcel Moolenaar 5077750ad47SMarcel Moolenaar -m "MACHINE" 5087750ad47SMarcel Moolenaar 5097750ad47SMarcel Moolenaar -H "HOST_TARGET" 5107750ad47SMarcel Moolenaar 5117750ad47SMarcel Moolenaar -D "DPDEPS" 5127750ad47SMarcel Moolenaar 5137750ad47SMarcel Moolenaar -d bumps debug level 5147750ad47SMarcel Moolenaar 5157750ad47SMarcel Moolenaar """ 5167750ad47SMarcel Moolenaar import getopt 5177750ad47SMarcel Moolenaar 5187750ad47SMarcel Moolenaar # import Psyco if we can 5197750ad47SMarcel Moolenaar # it can speed things up quite a bit 5207750ad47SMarcel Moolenaar have_psyco = 0 5217750ad47SMarcel Moolenaar try: 5227750ad47SMarcel Moolenaar import psyco 5237750ad47SMarcel Moolenaar psyco.full() 5247750ad47SMarcel Moolenaar have_psyco = 1 5257750ad47SMarcel Moolenaar except: 5267750ad47SMarcel Moolenaar pass 5277750ad47SMarcel Moolenaar 5287750ad47SMarcel Moolenaar conf = { 5297750ad47SMarcel Moolenaar 'SRCTOPS': [], 5307750ad47SMarcel Moolenaar 'OBJROOTS': [], 5317750ad47SMarcel Moolenaar } 5327750ad47SMarcel Moolenaar 5337750ad47SMarcel Moolenaar try: 5347750ad47SMarcel Moolenaar machine = os.environ['MACHINE'] 5357750ad47SMarcel Moolenaar if machine: 5367750ad47SMarcel Moolenaar conf['MACHINE'] = machine 5377750ad47SMarcel Moolenaar srctop = os.environ['SB_SRC'] 5387750ad47SMarcel Moolenaar if srctop: 5397750ad47SMarcel Moolenaar conf['SRCTOPS'].append(srctop) 5407750ad47SMarcel Moolenaar objroot = os.environ['SB_OBJROOT'] 5417750ad47SMarcel Moolenaar if objroot: 5427750ad47SMarcel Moolenaar conf['OBJROOTS'].append(objroot) 5437750ad47SMarcel Moolenaar except: 5447750ad47SMarcel Moolenaar pass 5457750ad47SMarcel Moolenaar 5467750ad47SMarcel Moolenaar debug = 0 5477750ad47SMarcel Moolenaar output = True 5487750ad47SMarcel Moolenaar 5497750ad47SMarcel Moolenaar opts, args = getopt.getopt(argv[1:], 'dS:C:O:R:m:D:H:q' + xopts) 5507750ad47SMarcel Moolenaar for o, a in opts: 5517750ad47SMarcel Moolenaar if o == '-d': 5527750ad47SMarcel Moolenaar debug += 1 5537750ad47SMarcel Moolenaar elif o == '-q': 5547750ad47SMarcel Moolenaar output = False 5557750ad47SMarcel Moolenaar elif o == '-H': 5567750ad47SMarcel Moolenaar conf['HOST_TARGET'] = a 5577750ad47SMarcel Moolenaar elif o == '-S': 5587750ad47SMarcel Moolenaar if a not in conf['SRCTOPS']: 5597750ad47SMarcel Moolenaar conf['SRCTOPS'].append(a) 5607750ad47SMarcel Moolenaar elif o == '-C': 5617750ad47SMarcel Moolenaar conf['CURDIR'] = a 5627750ad47SMarcel Moolenaar elif o == '-O': 5637750ad47SMarcel Moolenaar if a not in conf['OBJROOTS']: 5647750ad47SMarcel Moolenaar conf['OBJROOTS'].append(a) 5657750ad47SMarcel Moolenaar elif o == '-R': 5667750ad47SMarcel Moolenaar conf['RELDIR'] = a 5677750ad47SMarcel Moolenaar elif o == '-D': 5687750ad47SMarcel Moolenaar conf['DPDEPS'] = a 5697750ad47SMarcel Moolenaar elif o == '-m': 5707750ad47SMarcel Moolenaar conf['MACHINE'] = a 5717750ad47SMarcel Moolenaar elif xoptf: 5727750ad47SMarcel Moolenaar xoptf(o, a, conf) 5737750ad47SMarcel Moolenaar 5747750ad47SMarcel Moolenaar conf['debug'] = debug 5757750ad47SMarcel Moolenaar 5767750ad47SMarcel Moolenaar # get any var=val assignments 5777750ad47SMarcel Moolenaar eaten = [] 5787750ad47SMarcel Moolenaar for a in args: 5797750ad47SMarcel Moolenaar if a.find('=') > 0: 5807750ad47SMarcel Moolenaar k,v = a.split('=') 5817750ad47SMarcel Moolenaar if k in ['SRCTOP','OBJROOT','SRCTOPS','OBJROOTS']: 5827750ad47SMarcel Moolenaar if k == 'SRCTOP': 5837750ad47SMarcel Moolenaar k = 'SRCTOPS' 5847750ad47SMarcel Moolenaar elif k == 'OBJROOT': 5857750ad47SMarcel Moolenaar k = 'OBJROOTS' 5867750ad47SMarcel Moolenaar if v not in conf[k]: 5877750ad47SMarcel Moolenaar conf[k].append(v) 5887750ad47SMarcel Moolenaar else: 5897750ad47SMarcel Moolenaar conf[k] = v 5907750ad47SMarcel Moolenaar eaten.append(a) 5917750ad47SMarcel Moolenaar continue 5927750ad47SMarcel Moolenaar break 5937750ad47SMarcel Moolenaar 5947750ad47SMarcel Moolenaar for a in eaten: 5957750ad47SMarcel Moolenaar args.remove(a) 5967750ad47SMarcel Moolenaar 5977750ad47SMarcel Moolenaar debug_out = getv(conf, 'debug_out', sys.stderr) 5987750ad47SMarcel Moolenaar 5997750ad47SMarcel Moolenaar if debug: 6007750ad47SMarcel Moolenaar print >> debug_out, "config:" 6017750ad47SMarcel Moolenaar print >> debug_out, "psyco=", have_psyco 6027750ad47SMarcel Moolenaar for k,v in conf.items(): 6037750ad47SMarcel Moolenaar print >> debug_out, "%s=%s" % (k,v) 6047750ad47SMarcel Moolenaar 6057750ad47SMarcel Moolenaar for a in args: 6067750ad47SMarcel Moolenaar m = klass(a, conf) 6077750ad47SMarcel Moolenaar 6087750ad47SMarcel Moolenaar if output: 6097750ad47SMarcel Moolenaar print m.dirdeps() 6107750ad47SMarcel Moolenaar 6117750ad47SMarcel Moolenaar print m.src_dirdeps('\nsrc:') 6127750ad47SMarcel Moolenaar 6137750ad47SMarcel Moolenaar dpdeps = getv(conf, 'DPDEPS') 6147750ad47SMarcel Moolenaar if dpdeps: 6157750ad47SMarcel Moolenaar m.file_depends(open(dpdeps, 'wb')) 6167750ad47SMarcel Moolenaar 6177750ad47SMarcel Moolenaar return m 6187750ad47SMarcel Moolenaar 6197750ad47SMarcel Moolenaarif __name__ == '__main__': 6207750ad47SMarcel Moolenaar try: 6217750ad47SMarcel Moolenaar main(sys.argv) 6227750ad47SMarcel Moolenaar except: 6237750ad47SMarcel Moolenaar # yes, this goes to stdout 6247750ad47SMarcel Moolenaar print "ERROR: ", sys.exc_info()[1] 6257750ad47SMarcel Moolenaar raise 6267750ad47SMarcel Moolenaar 627