meta2deps.py revision 250837
1139804Simp#!/usr/bin/env python 21541Srgrimes 31541Srgrimes""" 41541SrgrimesThis script parses each "meta" file and extracts the 51541Srgrimesinformation needed to deduce build and src dependencies. 61541Srgrimes 71541SrgrimesIt works much the same as the original shell script, but is 81541Srgrimes*much* more efficient. 91541Srgrimes 101541SrgrimesThe parsing work is handled by the class MetaFile. 111541SrgrimesWe only pay attention to a subset of the information in the 121541Srgrimes"meta" files. Specifically: 131541Srgrimes 141541Srgrimes'CWD' to initialize our notion. 151541Srgrimes 161541Srgrimes'C' to track chdir(2) on a per process basis 171541Srgrimes 181541Srgrimes'R' files read are what we really care about. 191541Srgrimes directories read, provide a clue to resolving 201541Srgrimes subsequent relative paths. That is if we cannot find 211541Srgrimes them relative to 'cwd', we check relative to the last 221541Srgrimes dir read. 231541Srgrimes 241541Srgrimes'W' files opened for write or read-write, 251541Srgrimes for filemon V3 and earlier. 261541Srgrimes 271541Srgrimes'E' files executed. 281541Srgrimes 291541Srgrimes'L' files linked 301541Srgrimes 311541Srgrimes'V' the filemon version, this record is used as a clue 321541Srgrimes that we have reached the interesting bit. 331541Srgrimes 341541Srgrimes""" 351541Srgrimes 361541Srgrimes""" 37116182SobrienRCSid: 38116182Sobrien $Id: meta2deps.py,v 1.13 2013/05/11 05:16:26 sjg Exp $ 39116182Sobrien 4013203Swollman Copyright (c) 2011-2013, Juniper Networks, Inc. 41101127Srwatson All rights reserved. 42144613Sjeff 4313203Swollman Redistribution and use in source and binary forms, with or without 441541Srgrimes modification, are permitted provided that the following conditions 452112Swollman are met: 4669664Speter 1. Redistributions of source code must retain the above copyright 4776166Smarkm notice, this list of conditions and the following disclaimer. 48101127Srwatson 2. Redistributions in binary form must reproduce the above copyright 4989316Salfred notice, this list of conditions and the following disclaimer in the 501541Srgrimes documentation and/or other materials provided with the distribution. 511541Srgrimes 521541Srgrimes THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 531541Srgrimes "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 541541Srgrimes LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 55141471Sjhb A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 56144613Sjeff OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 571541Srgrimes SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 581541Srgrimes LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 591541Srgrimes DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 601541Srgrimes THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 61155334Srwatson (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 62155334Srwatson OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 6392751Sjeff 6432011Sbde""" 65155168Sjeff 66138345Sphkimport os, re, sys 67138345Sphk 681541Srgrimesdef getv(dict, key, d=None): 6969664Speter """Lookup key in dict and return value or the supplied default.""" 7069664Speter if key in dict: 7192751Sjeff return dict[key] 7269664Speter return d 7369664Speter 7469664Speterdef resolve(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr): 7569664Speter """ 7692654Sjeff Return an absolute path, resolving via cwd or last_dir if needed. 7792654Sjeff """ 7869664Speter if path.endswith('/.'): 7969664Speter path = path[0:-2] 8069664Speter if path[0] == '/': 8169664Speter return path 82144613Sjeff if path == '.': 83144613Sjeff return cwd 84144613Sjeff if path.startswith('./'): 85144613Sjeff return cwd + path[1:] 86144613Sjeff if last_dir == cwd: 87144613Sjeff last_dir = None 88144613Sjeff for d in [last_dir, cwd]: 89144613Sjeff if not d: 9069664Speter continue 91161010Srwatson p = '/'.join([d,path]) 921541Srgrimes if debug > 2: 931541Srgrimes print >> debug_out, "looking for:", p, 941541Srgrimes if not os.path.exists(p): 951541Srgrimes if debug > 2: 961541Srgrimes print >> debug_out, "nope" 971541Srgrimes p = None 981541Srgrimes continue 991541Srgrimes if debug > 2: 1001541Srgrimes print >> debug_out, "found:", p 1011541Srgrimes return p 1021541Srgrimes return None 1031541Srgrimes 1041541Srgrimesdef abspath(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr): 1051541Srgrimes """ 1061541Srgrimes Return an absolute path, resolving via cwd or last_dir if needed. 1071541Srgrimes this gets called a lot, so we try to avoid calling realpath 1081541Srgrimes until we know we have something. 1091541Srgrimes """ 1101541Srgrimes path = resolve(path, cwd, last_dir, debug, debug_out) 111161011Srwatson if path and (path.find('./') > 0 or 1121541Srgrimes path.endswith('/..') or 113161011Srwatson os.path.islink(path)): 114161011Srwatson return os.path.realpath(path) 115161011Srwatson return path 1161541Srgrimes 1171541Srgrimesdef sort_unique(list, cmp=None, key=None, reverse=False): 1181541Srgrimes list.sort(cmp, key, reverse) 1191541Srgrimes nl = [] 12083366Sjulian le = None 12183366Sjulian for e in list: 122140714Sjeff if e == le: 1231541Srgrimes continue 124150164Scsjp nl.append(e) 125150164Scsjp return nl 12691419Sjhb 12783366Sjuliandef add_trims(x): 12842408Seivind return ['/' + x + '/', 12942453Seivind '/' + x, 13042408Seivind x + '/', 13142453Seivind x] 132144613Sjeff 133144613Sjeffclass MetaFile: 13483366Sjulian """class to parse meta files generated by bmake.""" 1351541Srgrimes 1361541Srgrimes conf = None 1371541Srgrimes dirdep_re = None 1381541Srgrimes host_target = None 1391541Srgrimes srctops = [] 1401541Srgrimes objroots = [] 141111119Simp 1421541Srgrimes seen = {} 1431541Srgrimes obj_deps = [] 14436735Sdfr src_deps = [] 1451541Srgrimes file_deps = [] 1461541Srgrimes 14736735Sdfr def __init__(self, name, conf={}): 14820069Sbde """if name is set we will parse it now. 149155334Srwatson conf can have the follwing keys: 150155334Srwatson 151155334Srwatson SRCTOPS list of tops of the src tree(s). 152155334Srwatson 153155334Srwatson CURDIR the src directory 'bmake' was run from. 154155334Srwatson 15520069Sbde RELDIR the relative path from SRCTOP to CURDIR 15620069Sbde 15720069Sbde MACHINE the machine we built for. 15820069Sbde set to 'none' if we are not cross-building. 15920069Sbde More specifically if machine cannot be deduced from objdirs. 16020069Sbde 1611541Srgrimes TARGET_SPEC 16292751Sjeff Sometimes MACHINE isn't enough. 163100613Srwatson 164100613Srwatson HOST_TARGET 165100613Srwatson when we build for the psuedo machine 'host' 166100613Srwatson the object tree uses HOST_TARGET rather than MACHINE. 1671541Srgrimes 1681541Srgrimes OBJROOTS a list of the common prefix for all obj dirs it might 1691541Srgrimes end in '/' or '-'. 1701541Srgrimes 1711541Srgrimes DPDEPS names an optional file to which per file dependencies 17297994Sjhb will be appended. 17397994Sjhb For example if 'some/path/foo.h' is read from SRCTOP 17497994Sjhb then 'DPDEPS_some/path/foo.h +=' "RELDIR" is output. 17597994Sjhb This can allow 'bmake' to learn all the dirs within 17697994Sjhb the tree that depend on 'foo.h' 1771541Srgrimes 1781541Srgrimes debug desired debug level 1791541Srgrimes 1801541Srgrimes debug_out open file to send debug output to (sys.stderr) 1811541Srgrimes 18289306Salfred """ 18333360Sdyson 18451649Sphk self.name = name 18533360Sdyson self.debug = getv(conf, 'debug', 0) 1861541Srgrimes self.debug_out = getv(conf, 'debug_out', sys.stderr) 187140714Sjeff 1881541Srgrimes self.machine = getv(conf, 'MACHINE', '') 18989306Salfred self.machine_arch = getv(conf, 'MACHINE_ARCH', '') 1901541Srgrimes self.target_spec = getv(conf, 'TARGET_SPEC', '') 1911541Srgrimes self.curdir = getv(conf, 'CURDIR') 1921541Srgrimes self.reldir = getv(conf, 'RELDIR') 1931541Srgrimes self.dpdeps = getv(conf, 'DPDEPS') 1941541Srgrimes 1951541Srgrimes if not self.conf: 1961541Srgrimes # some of the steps below we want to do only once 1971541Srgrimes self.conf = conf 198140714Sjeff self.host_target = getv(conf, 'HOST_TARGET') 1991541Srgrimes for srctop in getv(conf, 'SRCTOPS', []): 2001541Srgrimes if srctop[-1] != '/': 2011541Srgrimes srctop += '/' 2021541Srgrimes if not srctop in self.srctops: 2031541Srgrimes self.srctops.append(srctop) 204140714Sjeff _srctop = os.path.realpath(srctop) 2051541Srgrimes if _srctop[-1] != '/': 2061541Srgrimes _srctop += '/' 207140714Sjeff if not _srctop in self.srctops: 208140714Sjeff self.srctops.append(_srctop) 2091541Srgrimes 2103148Sphk trim_list = add_trims(self.machine) 2113148Sphk if self.machine == 'host': 21292751Sjeff trim_list += add_trims(self.host_target) 213100613Srwatson if self.target_spec: 214100613Srwatson trim_list += add_trims(self.target_spec) 215100613Srwatson 216100613Srwatson for objroot in getv(conf, 'OBJROOTS', []): 2171541Srgrimes for e in trim_list: 2181541Srgrimes if objroot.endswith(e): 219140714Sjeff # this is not what we want - fix it 220140714Sjeff objroot = objroot[0:-len(e)] 2211541Srgrimes if e.endswith('/'): 2221541Srgrimes objroot += '/' 2231541Srgrimes if not objroot in self.objroots: 2241541Srgrimes self.objroots.append(objroot) 225100613Srwatson _objroot = os.path.realpath(objroot) 22692751Sjeff if objroot[-1] == '/': 227100613Srwatson _objroot += '/' 228100613Srwatson if not _objroot in self.objroots: 229100613Srwatson self.objroots.append(_objroot) 230100613Srwatson 231100613Srwatson # we want the longest match 2321541Srgrimes self.srctops.sort(reverse=True) 23332286Sdyson self.objroots.sort(reverse=True) 234140714Sjeff 235140714Sjeff if self.debug: 236140714Sjeff print >> self.debug_out, "host_target=", self.host_target 237140714Sjeff print >> self.debug_out, "srctops=", self.srctops 2381541Srgrimes print >> self.debug_out, "objroots=", self.objroots 2391541Srgrimes 2401541Srgrimes self.dirdep_re = re.compile(r'([^/]+)/(.+)') 2411541Srgrimes 2421541Srgrimes if self.dpdeps and not self.reldir: 2431541Srgrimes if self.debug: 244101127Srwatson print >> self.debug_out, "need reldir:", 245105479Srwatson if self.curdir: 246105479Srwatson srctop = self.find_top(self.curdir, self.srctops) 247105479Srwatson if srctop: 248105479Srwatson self.reldir = self.curdir.replace(srctop,'') 249105479Srwatson if self.debug: 250105479Srwatson print >> self.debug_out, self.reldir 251101127Srwatson if not self.reldir: 2521541Srgrimes self.dpdeps = None # we cannot do it? 253111119Simp 2541541Srgrimes self.cwd = os.getcwd() # make sure this is initialized 2551541Srgrimes 2561541Srgrimes if name: 2571541Srgrimes self.parse() 2581541Srgrimes 2591541Srgrimes def reset(self): 2601541Srgrimes """reset state if we are being passed meta files from multiple directories.""" 2611541Srgrimes self.seen = {} 2621541Srgrimes self.obj_deps = [] 26383366Sjulian self.src_deps = [] 2641541Srgrimes self.file_deps = [] 2653148Sphk 2663148Sphk def dirdeps(self, sep='\n'): 2671541Srgrimes """return DIRDEPS""" 26892751Sjeff return sep.strip() + sep.join(self.obj_deps) 2691541Srgrimes 2701541Srgrimes def src_dirdeps(self, sep='\n'): 2711541Srgrimes """return SRC_DIRDEPS""" 27278692Sdillon return sep.strip() + sep.join(self.src_deps) 27378692Sdillon 27492751Sjeff def file_depends(self, out=None): 27578692Sdillon """Append DPDEPS_${file} += ${RELDIR} 27678692Sdillon for each file we saw, to the output file.""" 27778692Sdillon if not self.reldir: 2781541Srgrimes return None 2791541Srgrimes for f in sort_unique(self.file_deps): 28092751Sjeff print >> out, 'DPDEPS_%s += %s' % (f, self.reldir) 2811541Srgrimes 2821541Srgrimes def seenit(self, dir): 2831541Srgrimes """rememer that we have seen dir.""" 2841541Srgrimes self.seen[dir] = 1 2851541Srgrimes 28692751Sjeff def add(self, list, data, clue=''): 2871541Srgrimes """add data to list if it isn't already there.""" 2881541Srgrimes if data not in list: 2891541Srgrimes list.append(data) 2901541Srgrimes if self.debug: 2911541Srgrimes print >> self.debug_out, "%s: %sAdd: %s" % (self.name, clue, data) 2921541Srgrimes 2931541Srgrimes def find_top(self, path, list): 29492751Sjeff """the logical tree may be split accross multiple trees""" 295100613Srwatson for top in list: 296100613Srwatson if path.startswith(top): 297100613Srwatson if self.debug > 2: 298100613Srwatson print >> self.debug_out, "found in", top 299144833Sjeff return top 300144833Sjeff return None 3011541Srgrimes 302140714Sjeff def find_obj(self, objroot, dir, path, input): 3031541Srgrimes """return path within objroot, taking care of .dirdep files""" 3041541Srgrimes ddep = None 3051541Srgrimes for ddepf in [path + '.dirdep', dir + '/.dirdep']: 306162288Smohans if not ddep and os.path.exists(ddepf): 307162288Smohans ddep = open(ddepf, 'rb').readline().strip('# \n') 308162288Smohans if self.debug > 1: 309162288Smohans print >> self.debug_out, "found %s: %s\n" % (ddepf, ddep) 310162288Smohans if ddep.endswith(self.machine): 311162288Smohans ddep = ddep[0:-(1+len(self.machine))] 312162288Smohans elif self.target_spec and ddep.endswith(self.target_spec): 313162288Smohans ddep = ddep[0:-(1+len(self.target_spec))] 314162288Smohans 315162288Smohans if not ddep: 3161541Srgrimes # no .dirdeps, so remember that we've seen the raw input 3171541Srgrimes self.seenit(input) 3181541Srgrimes self.seenit(dir) 3191541Srgrimes if self.machine == 'none': 3201541Srgrimes if dir.startswith(objroot): 3211541Srgrimes return dir.replace(objroot,'') 3221541Srgrimes return None 3231541Srgrimes m = self.dirdep_re.match(dir.replace(objroot,'')) 3241541Srgrimes if m: 3251541Srgrimes ddep = m.group(2) 3261541Srgrimes dmachine = m.group(1) 3271541Srgrimes if dmachine != self.machine: 3281541Srgrimes if not (self.machine == 'host' and 3291541Srgrimes dmachine == self.host_target): 3301541Srgrimes if self.debug > 2: 3311541Srgrimes print >> self.debug_out, "adding .%s to %s" % (dmachine, ddep) 3321541Srgrimes ddep += '.' + dmachine 3331541Srgrimes 3341541Srgrimes return ddep 3351541Srgrimes 3361541Srgrimes def parse(self, name=None, file=None): 3378876Srgrimes """A meta file looks like: 3381541Srgrimes 3391541Srgrimes # Meta data file "path" 3401541Srgrimes CMD "command-line" 3411541Srgrimes CWD "cwd" 3421541Srgrimes TARGET "target" 3431541Srgrimes -- command output -- 3441541Srgrimes -- filemon acquired metadata -- 3451541Srgrimes # buildmon version 3 3461541Srgrimes V 3 3471541Srgrimes C "pid" "cwd" 3481541Srgrimes E "pid" "path" 3491541Srgrimes F "pid" "child" 3501541Srgrimes R "pid" "path" 3511541Srgrimes W "pid" "path" 3521541Srgrimes X "pid" "status" 3531541Srgrimes D "pid" "path" 3541541Srgrimes L "pid" "src" "target" 355161011Srwatson M "pid" "old" "new" 3561541Srgrimes S "pid" "path" 357161011Srwatson # Bye bye 358161011Srwatson 3591541Srgrimes We go to some effort to avoid processing a dependency more than once. 3601541Srgrimes Of the above record types only C,E,F,L,R,V and W are of interest. 3611541Srgrimes """ 3621541Srgrimes 3631541Srgrimes version = 0 # unknown 3649804Sbde if name: 3651541Srgrimes self.name = name; 36665805Sbp if file: 3671541Srgrimes f = file 36883366Sjulian cwd = last_dir = self.cwd 369158094Sjeff else: 370158094Sjeff f = open(self.name, 'rb') 371140714Sjeff skip = True 372162288Smohans pid_cwd = {} 373162288Smohans pid_last_dir = {} 3741541Srgrimes last_pid = 0 3751541Srgrimes 3761541Srgrimes if self.curdir: 377158094Sjeff self.seenit(self.curdir) # we ignore this 378158094Sjeff 379140714Sjeff interesting = 'CEFLRV' 3801541Srgrimes for line in f: 381144229Sjeff # ignore anything we don't care about 382144229Sjeff if not line[0] in interesting: 3831541Srgrimes continue 3841541Srgrimes if self.debug > 2: 38522874Sbde print >> self.debug_out, "input:", line, 38622874Sbde w = line.split() 3871541Srgrimes 3881541Srgrimes if skip: 389144286Sjeff if w[0] == 'V': 3901541Srgrimes skip = False 391144286Sjeff version = int(w[1]) 392144286Sjeff """ 393144286Sjeff if version < 4: 394144286Sjeff # we cannot ignore 'W' records 395144613Sjeff # as they may be 'rw' 396144613Sjeff interesting += 'W' 397144613Sjeff """ 398144613Sjeff elif w[0] == 'CWD': 3991541Srgrimes self.cwd = cwd = last_dir = w[1] 4001541Srgrimes self.seenit(cwd) # ignore this 401162288Smohans if self.debug: 4021541Srgrimes print >> self.debug_out, "%s: CWD=%s" % (self.name, cwd) 4031541Srgrimes continue 4041541Srgrimes 4051541Srgrimes pid = int(w[1]) 4061541Srgrimes if pid != last_pid: 4071541Srgrimes if last_pid: 4081541Srgrimes pid_cwd[last_pid] = cwd 4091541Srgrimes pid_last_dir[last_pid] = last_dir 4101541Srgrimes cwd = getv(pid_cwd, pid, self.cwd) 4111541Srgrimes last_dir = getv(pid_last_dir, pid, self.cwd) 4121541Srgrimes last_pid = pid 4131541Srgrimes 41451906Sphk # process operations 4151541Srgrimes if w[0] == 'F': 4161541Srgrimes npid = int(w[2]) 4171541Srgrimes pid_cwd[npid] = cwd 4181541Srgrimes pid_last_dir[npid] = cwd 4191541Srgrimes last_pid = npid 4201541Srgrimes continue 4211541Srgrimes elif w[0] == 'C': 4221541Srgrimes cwd = abspath(w[2], cwd, None, self.debug, self.debug_out) 4231541Srgrimes if cwd.endswith('/.'): 4241541Srgrimes cwd = cwd[0:-2] 4251541Srgrimes last_dir = cwd 4261541Srgrimes if self.debug > 1: 4271541Srgrimes print >> self.debug_out, "cwd=", cwd 4289804Sbde continue 4299804Sbde 4309804Sbde if w[2] in self.seen: 4319804Sbde if self.debug > 2: 4329804Sbde print >> self.debug_out, "seen:", w[2] 4339804Sbde continue 4349804Sbde # file operations 4359804Sbde if w[0] in 'ML': 4369804Sbde path = w[2].strip("'") 4379804Sbde else: 4389804Sbde path = w[2] 4399804Sbde # we are never interested in .dirdep files as dependencies 4409804Sbde if path.endswith('.dirdep'): 4419804Sbde continue 4429804Sbde # we don't want to resolve the last component if it is 4439804Sbde # a symlink 4449804Sbde path = resolve(path, cwd, last_dir, self.debug, self.debug_out) 4459804Sbde if not path: 4469804Sbde continue 4471541Srgrimes dir,base = os.path.split(path) 4481541Srgrimes if dir in self.seen: 4491541Srgrimes if self.debug > 2: 4501541Srgrimes print >> self.debug_out, "seen:", dir 4511541Srgrimes continue 4521541Srgrimes # we can have a path in an objdir which is a link 4531541Srgrimes # to the src dir, we may need to add dependencies for each 4541541Srgrimes rdir = dir 4551541Srgrimes dir = abspath(dir, cwd, last_dir, self.debug, self.debug_out) 4561541Srgrimes if rdir == dir or rdir.find('./') > 0: 4571541Srgrimes rdir = None 4581541Srgrimes # now put path back together 4591541Srgrimes path = '/'.join([dir,base]) 4601541Srgrimes if self.debug > 1: 4611541Srgrimes print >> self.debug_out, "raw=%s rdir=%s dir=%s path=%s" % (w[2], rdir, dir, path) 4621541Srgrimes if w[0] in 'SRWL': 4631541Srgrimes if w[0] == 'W' and path.endswith('.dirdep'): 4641541Srgrimes continue 4651541Srgrimes if path in [last_dir, cwd, self.cwd, self.curdir]: 4661541Srgrimes if self.debug > 1: 46722521Sdyson print >> self.debug_out, "skipping:", path 46822521Sdyson continue 46922521Sdyson if os.path.isdir(path): 47022521Sdyson if w[0] in 'RW': 4711541Srgrimes last_dir = path; 4721541Srgrimes if self.debug > 1: 4731541Srgrimes print >> self.debug_out, "ldir=", last_dir 4741541Srgrimes continue 4751541Srgrimes 4761541Srgrimes if w[0] in 'REWML': 4771541Srgrimes # finally, we get down to it 4781541Srgrimes if dir == self.cwd or dir == self.curdir: 4791541Srgrimes continue 480155334Srwatson srctop = self.find_top(path, self.srctops) 481155334Srwatson if srctop: 482155334Srwatson if self.dpdeps: 483155334Srwatson self.add(self.file_deps, path.replace(srctop,''), 'file') 484155334Srwatson self.add(self.src_deps, dir.replace(srctop,''), 'src') 485155334Srwatson self.seenit(w[2]) 4861541Srgrimes self.seenit(dir) 48783366Sjulian if rdir and not rdir.startswith(srctop): 48854655Seivind dir = rdir # for below 4891541Srgrimes rdir = None 4901541Srgrimes else: 491140714Sjeff continue 4921541Srgrimes 4931541Srgrimes objroot = None 4941541Srgrimes for dir in [dir,rdir]: 495154649Struckman if not dir: 496154649Struckman continue 497154649Struckman objroot = self.find_top(dir, self.objroots) 498154649Struckman if objroot: 4991541Srgrimes break 5001541Srgrimes if objroot: 501154649Struckman ddep = self.find_obj(objroot, dir, path, w[2]) 5021541Srgrimes if ddep: 5031541Srgrimes self.add(self.obj_deps, ddep, 'obj') 50496755Strhodes else: 505154649Struckman # don't waste time looking again 50651649Sphk self.seenit(w[2]) 5071541Srgrimes self.seenit(dir) 5081541Srgrimes if not file: 509154649Struckman f.close() 510154649Struckman 511154690Struckman 512154649Struckmandef main(argv, klass=MetaFile, xopts='', xoptf=None): 513154649Struckman """Simple driver for class MetaFile. 5141541Srgrimes 51551649Sphk Usage: 51651649Sphk script [options] [key=value ...] "meta" ... 51751649Sphk 5181541Srgrimes Options and key=value pairs contribute to the 5191541Srgrimes dictionary passed to MetaFile. 520158142Skris 5211541Srgrimes -S "SRCTOP" 5221541Srgrimes add "SRCTOP" to the "SRCTOPS" list. 5231541Srgrimes 524101308Sjeff -C "CURDIR" 5251541Srgrimes 5261541Srgrimes -O "OBJROOT" 527155385Sjeff add "OBJROOT" to the "OBJROOTS" list. 52869405Salfred 52969405Salfred -m "MACHINE" 53069405Salfred 5311541Srgrimes -a "MACHINE_ARCH" 532144833Sjeff 533158094Sjeff -H "HOST_TARGET" 534158094Sjeff 535144833Sjeff -D "DPDEPS" 5361541Srgrimes 537140714Sjeff -d bumps debug level 538162288Smohans 5391541Srgrimes """ 5401541Srgrimes import getopt 5411541Srgrimes 5421541Srgrimes # import Psyco if we can 5431541Srgrimes # it can speed things up quite a bit 5441541Srgrimes have_psyco = 0 5451541Srgrimes try: 546101127Srwatson import psyco 547105479Srwatson psyco.full() 548105479Srwatson have_psyco = 1 549105479Srwatson except: 550105479Srwatson pass 551105479Srwatson 552101127Srwatson conf = { 5531541Srgrimes 'SRCTOPS': [], 55422521Sdyson 'OBJROOTS': [], 55524624Sdfr } 556158094Sjeff 557144286Sjeff try: 558144286Sjeff machine = os.environ['MACHINE'] 559144286Sjeff if machine: 560144286Sjeff conf['MACHINE'] = machine 561144286Sjeff machine_arch = os.environ['MACHINE_ARCH'] 562144286Sjeff if machine_arch: 563144286Sjeff conf['MACHINE_ARCH'] = machine_arch 564144286Sjeff srctop = os.environ['SB_SRC'] 565144286Sjeff if srctop: 566144286Sjeff conf['SRCTOPS'].append(srctop) 567144286Sjeff objroot = os.environ['SB_OBJROOT'] 568144286Sjeff if objroot: 569144286Sjeff conf['OBJROOTS'].append(objroot) 570144286Sjeff except: 571138345Sphk pass 572138345Sphk 573138345Sphk debug = 0 574162288Smohans output = True 575162288Smohans 57643301Sdillon opts, args = getopt.getopt(argv[1:], 'a:dS:C:O:R:m:D:H:qT:' + xopts) 577162288Smohans for o, a in opts: 57842408Seivind if o == '-a': 5791541Srgrimes conf['MACHINE_ARCH'] = a 5801541Srgrimes elif o == '-d': 5811541Srgrimes debug += 1 5821541Srgrimes elif o == '-q': 583101308Sjeff output = False 5841541Srgrimes elif o == '-H': 5851541Srgrimes conf['HOST_TARGET'] = a 586144833Sjeff elif o == '-S': 587158094Sjeff if a not in conf['SRCTOPS']: 588158094Sjeff conf['SRCTOPS'].append(a) 589144833Sjeff elif o == '-C': 590144203Sjeff conf['CURDIR'] = a 591140714Sjeff elif o == '-O': 592162288Smohans if a not in conf['OBJROOTS']: 5931541Srgrimes conf['OBJROOTS'].append(a) 5941541Srgrimes elif o == '-R': 5951541Srgrimes conf['RELDIR'] = a 5961541Srgrimes elif o == '-D': 5971541Srgrimes conf['DPDEPS'] = a 5981541Srgrimes elif o == '-m': 5991541Srgrimes conf['MACHINE'] = a 6001541Srgrimes elif o == '-T': 6011541Srgrimes conf['TARGET_SPEC'] = a 60211644Sdg elif xoptf: 6031541Srgrimes xoptf(o, a, conf) 6041541Srgrimes 6051541Srgrimes conf['debug'] = debug 6069804Sbde 6079804Sbde # get any var=val assignments 6089804Sbde eaten = [] 6099804Sbde for a in args: 6109804Sbde if a.find('=') > 0: 611144203Sjeff k,v = a.split('=') 612144203Sjeff if k in ['SRCTOP','OBJROOT','SRCTOPS','OBJROOTS']: 6131541Srgrimes if k == 'SRCTOP': 614144203Sjeff k = 'SRCTOPS' 615144203Sjeff elif k == 'OBJROOT': 616144203Sjeff k = 'OBJROOTS' 617144203Sjeff if v not in conf[k]: 618144203Sjeff conf[k].append(v) 619144203Sjeff else: 6201541Srgrimes conf[k] = v 6211541Srgrimes eaten.append(a) 622161010Srwatson continue 6231541Srgrimes break 6241541Srgrimes 6251541Srgrimes for a in eaten: 6261541Srgrimes args.remove(a) 6271541Srgrimes 628140714Sjeff debug_out = getv(conf, 'debug_out', sys.stderr) 629162288Smohans 630162288Smohans if debug: 6311541Srgrimes print >> debug_out, "config:" 6321541Srgrimes print >> debug_out, "psyco=", have_psyco 6331541Srgrimes for k,v in conf.items(): 634144203Sjeff print >> debug_out, "%s=%s" % (k,v) 6351541Srgrimes 6361541Srgrimes for a in args: 6371541Srgrimes m = klass(a, conf) 6381541Srgrimes 6391541Srgrimes if output: 6401541Srgrimes print m.dirdeps() 6411541Srgrimes 6421541Srgrimes print m.src_dirdeps('\nsrc:') 6431541Srgrimes 6441541Srgrimes dpdeps = getv(conf, 'DPDEPS') 6451541Srgrimes if dpdeps: 646158094Sjeff m.file_depends(open(dpdeps, 'wb')) 6471541Srgrimes 6481541Srgrimes return m 6491541Srgrimes 65096755Strhodesif __name__ == '__main__': 6511541Srgrimes try: 6521541Srgrimes main(sys.argv) 6531541Srgrimes except: 65483366Sjulian # yes, this goes to stdout 6551541Srgrimes print "ERROR: ", sys.exc_info()[1] 656144833Sjeff raise 657158094Sjeff 658155168Sjeff