17750ad47SMarcel Moolenaar#!/usr/bin/env python 27750ad47SMarcel Moolenaar 310ea6facSSimon J. Gerratyfrom __future__ import print_function 410ea6facSSimon J. Gerraty 57750ad47SMarcel Moolenaar""" 67750ad47SMarcel MoolenaarThis script parses each "meta" file and extracts the 77750ad47SMarcel Moolenaarinformation needed to deduce build and src dependencies. 87750ad47SMarcel Moolenaar 97750ad47SMarcel MoolenaarIt works much the same as the original shell script, but is 107750ad47SMarcel Moolenaar*much* more efficient. 117750ad47SMarcel Moolenaar 127750ad47SMarcel MoolenaarThe parsing work is handled by the class MetaFile. 137750ad47SMarcel MoolenaarWe only pay attention to a subset of the information in the 147750ad47SMarcel Moolenaar"meta" files. Specifically: 157750ad47SMarcel Moolenaar 167750ad47SMarcel Moolenaar'CWD' to initialize our notion. 177750ad47SMarcel Moolenaar 187750ad47SMarcel Moolenaar'C' to track chdir(2) on a per process basis 197750ad47SMarcel Moolenaar 207750ad47SMarcel Moolenaar'R' files read are what we really care about. 217750ad47SMarcel Moolenaar directories read, provide a clue to resolving 227750ad47SMarcel Moolenaar subsequent relative paths. That is if we cannot find 237750ad47SMarcel Moolenaar them relative to 'cwd', we check relative to the last 247750ad47SMarcel Moolenaar dir read. 257750ad47SMarcel Moolenaar 267750ad47SMarcel Moolenaar'W' files opened for write or read-write, 277750ad47SMarcel Moolenaar for filemon V3 and earlier. 287750ad47SMarcel Moolenaar 297750ad47SMarcel Moolenaar'E' files executed. 307750ad47SMarcel Moolenaar 317750ad47SMarcel Moolenaar'L' files linked 327750ad47SMarcel Moolenaar 337750ad47SMarcel Moolenaar'V' the filemon version, this record is used as a clue 347750ad47SMarcel Moolenaar that we have reached the interesting bit. 357750ad47SMarcel Moolenaar 367750ad47SMarcel Moolenaar""" 377750ad47SMarcel Moolenaar 387750ad47SMarcel Moolenaar""" 397750ad47SMarcel MoolenaarRCSid: 40*bf7aa99aSSimon J. Gerraty $Id: meta2deps.py,v 1.45 2023/01/18 01:35:24 sjg Exp $ 417750ad47SMarcel Moolenaar 42960b77beSSimon J. Gerraty Copyright (c) 2011-2020, Simon J. Gerraty 43960b77beSSimon J. Gerraty Copyright (c) 2011-2017, Juniper Networks, Inc. 444ed4429cSSimon J. Gerraty All rights reserved. 457750ad47SMarcel Moolenaar 467750ad47SMarcel Moolenaar Redistribution and use in source and binary forms, with or without 477750ad47SMarcel Moolenaar modification, are permitted provided that the following conditions 487750ad47SMarcel Moolenaar are met: 497750ad47SMarcel Moolenaar 1. Redistributions of source code must retain the above copyright 507750ad47SMarcel Moolenaar notice, this list of conditions and the following disclaimer. 517750ad47SMarcel Moolenaar 2. Redistributions in binary form must reproduce the above copyright 527750ad47SMarcel Moolenaar notice, this list of conditions and the following disclaimer in the 537750ad47SMarcel Moolenaar documentation and/or other materials provided with the distribution. 547750ad47SMarcel Moolenaar 557750ad47SMarcel Moolenaar THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 567750ad47SMarcel Moolenaar "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 577750ad47SMarcel Moolenaar LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 587750ad47SMarcel Moolenaar A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 597750ad47SMarcel Moolenaar OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 607750ad47SMarcel Moolenaar SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 617750ad47SMarcel Moolenaar LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 627750ad47SMarcel Moolenaar DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 637750ad47SMarcel Moolenaar THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 647750ad47SMarcel Moolenaar (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 657750ad47SMarcel Moolenaar OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 667750ad47SMarcel Moolenaar 677750ad47SMarcel Moolenaar""" 687750ad47SMarcel Moolenaar 69*bf7aa99aSSimon J. Gerratyimport os 70*bf7aa99aSSimon J. Gerratyimport re 71*bf7aa99aSSimon J. Gerratyimport sys 72*bf7aa99aSSimon J. Gerratyimport stat 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] 80d5ddb276SSimon J. Gerraty if len(path) > 0 and path[0] == '/': 81960b77beSSimon J. Gerraty if os.path.exists(path): 827750ad47SMarcel Moolenaar return path 83960b77beSSimon J. Gerraty if debug > 2: 84960b77beSSimon J. Gerraty print("skipping non-existent:", path, file=debug_out) 85960b77beSSimon J. Gerraty return None 867750ad47SMarcel Moolenaar if path == '.': 877750ad47SMarcel Moolenaar return cwd 887750ad47SMarcel Moolenaar if path.startswith('./'): 897750ad47SMarcel Moolenaar return cwd + path[1:] 907750ad47SMarcel Moolenaar if last_dir == cwd: 917750ad47SMarcel Moolenaar last_dir = None 927750ad47SMarcel Moolenaar for d in [last_dir, cwd]: 937750ad47SMarcel Moolenaar if not d: 947750ad47SMarcel Moolenaar continue 95a6589ab7SSimon J. Gerraty if path == '..': 96a6589ab7SSimon J. Gerraty dw = d.split('/') 97a6589ab7SSimon J. Gerraty p = '/'.join(dw[:-1]) 98a6589ab7SSimon J. Gerraty if not p: 99a6589ab7SSimon J. Gerraty p = '/' 100a6589ab7SSimon J. Gerraty return p 1017750ad47SMarcel Moolenaar p = '/'.join([d,path]) 1027750ad47SMarcel Moolenaar if debug > 2: 10310ea6facSSimon J. Gerraty print("looking for:", p, end=' ', file=debug_out) 1047750ad47SMarcel Moolenaar if not os.path.exists(p): 1057750ad47SMarcel Moolenaar if debug > 2: 10610ea6facSSimon J. Gerraty print("nope", file=debug_out) 1077750ad47SMarcel Moolenaar p = None 1087750ad47SMarcel Moolenaar continue 1097750ad47SMarcel Moolenaar if debug > 2: 11010ea6facSSimon J. Gerraty print("found:", p, file=debug_out) 1117750ad47SMarcel Moolenaar return p 1127750ad47SMarcel Moolenaar return None 1137750ad47SMarcel Moolenaar 1146d4f05fdSSimon J. Gerratydef cleanpath(path): 1156d4f05fdSSimon J. Gerraty """cleanup path without using realpath(3)""" 1166d4f05fdSSimon J. Gerraty if path.startswith('/'): 1176d4f05fdSSimon J. Gerraty r = '/' 1186d4f05fdSSimon J. Gerraty else: 1196d4f05fdSSimon J. Gerraty r = '' 1206d4f05fdSSimon J. Gerraty p = [] 1216d4f05fdSSimon J. Gerraty w = path.split('/') 1226d4f05fdSSimon J. Gerraty for d in w: 1236d4f05fdSSimon J. Gerraty if not d or d == '.': 1246d4f05fdSSimon J. Gerraty continue 1256d4f05fdSSimon J. Gerraty if d == '..': 126a6589ab7SSimon J. Gerraty try: 1276d4f05fdSSimon J. Gerraty p.pop() 1286d4f05fdSSimon J. Gerraty continue 129a6589ab7SSimon J. Gerraty except: 130a6589ab7SSimon J. Gerraty break 1316d4f05fdSSimon J. Gerraty p.append(d) 1326d4f05fdSSimon J. Gerraty 1336d4f05fdSSimon J. Gerraty return r + '/'.join(p) 1346d4f05fdSSimon J. Gerraty 1357750ad47SMarcel Moolenaardef abspath(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr): 1367750ad47SMarcel Moolenaar """ 1377750ad47SMarcel Moolenaar Return an absolute path, resolving via cwd or last_dir if needed. 1386d4f05fdSSimon J. Gerraty this gets called a lot, so we try to avoid calling realpath. 1397750ad47SMarcel Moolenaar """ 140d5ddb276SSimon J. Gerraty rpath = resolve(path, cwd, last_dir, debug, debug_out) 141d5ddb276SSimon J. Gerraty if rpath: 142d5ddb276SSimon J. Gerraty path = rpath 143960b77beSSimon J. Gerraty elif len(path) > 0 and path[0] == '/': 144960b77beSSimon J. Gerraty return None 145ccfb9654SSimon J. Gerraty if (path.find('/') < 0 or 146ccfb9654SSimon J. Gerraty path.find('./') > 0 or 1476d4f05fdSSimon J. Gerraty path.endswith('/..')): 1486d4f05fdSSimon J. Gerraty path = cleanpath(path) 1497750ad47SMarcel Moolenaar return path 1507750ad47SMarcel Moolenaar 1517750ad47SMarcel Moolenaardef sort_unique(list, cmp=None, key=None, reverse=False): 1523b26e5a4SSimon J. Gerraty if sys.version_info[0] == 2: 1537750ad47SMarcel Moolenaar list.sort(cmp, key, reverse) 1543b26e5a4SSimon J. Gerraty else: 1553b26e5a4SSimon J. Gerraty list.sort(reverse=reverse) 1567750ad47SMarcel Moolenaar nl = [] 1577750ad47SMarcel Moolenaar le = None 1587750ad47SMarcel Moolenaar for e in list: 1597750ad47SMarcel Moolenaar if e == le: 1607750ad47SMarcel Moolenaar continue 1616d4f05fdSSimon J. Gerraty le = e 1627750ad47SMarcel Moolenaar nl.append(e) 1637750ad47SMarcel Moolenaar return nl 1647750ad47SMarcel Moolenaar 165bf062775SSimon J. Gerratydef add_trims(x): 166bf062775SSimon J. Gerraty return ['/' + x + '/', 167bf062775SSimon J. Gerraty '/' + x, 168bf062775SSimon J. Gerraty x + '/', 169bf062775SSimon J. Gerraty x] 170bf062775SSimon J. Gerraty 1713b26e5a4SSimon J. Gerratydef target_spec_exts(target_spec): 1723b26e5a4SSimon J. Gerraty """return a list of dirdep extensions that could match target_spec""" 1733b26e5a4SSimon J. Gerraty 1743b26e5a4SSimon J. Gerraty if target_spec.find(',') < 0: 1753b26e5a4SSimon J. Gerraty return ['.'+target_spec] 1763b26e5a4SSimon J. Gerraty w = target_spec.split(',') 1773b26e5a4SSimon J. Gerraty n = len(w) 1783b26e5a4SSimon J. Gerraty e = [] 1793b26e5a4SSimon J. Gerraty while n > 0: 1803b26e5a4SSimon J. Gerraty e.append('.'+','.join(w[0:n])) 1813b26e5a4SSimon J. Gerraty n -= 1 1823b26e5a4SSimon J. Gerraty return e 1833b26e5a4SSimon J. Gerraty 1847750ad47SMarcel Moolenaarclass MetaFile: 1857750ad47SMarcel Moolenaar """class to parse meta files generated by bmake.""" 1867750ad47SMarcel Moolenaar 1877750ad47SMarcel Moolenaar conf = None 1887750ad47SMarcel Moolenaar dirdep_re = None 1897750ad47SMarcel Moolenaar host_target = None 1907750ad47SMarcel Moolenaar srctops = [] 1917750ad47SMarcel Moolenaar objroots = [] 192ccfb9654SSimon J. Gerraty excludes = [] 1937750ad47SMarcel Moolenaar seen = {} 1947750ad47SMarcel Moolenaar obj_deps = [] 1957750ad47SMarcel Moolenaar src_deps = [] 1967750ad47SMarcel Moolenaar file_deps = [] 1977750ad47SMarcel Moolenaar 1987750ad47SMarcel Moolenaar def __init__(self, name, conf={}): 1997750ad47SMarcel Moolenaar """if name is set we will parse it now. 2007750ad47SMarcel Moolenaar conf can have the follwing keys: 2017750ad47SMarcel Moolenaar 2027750ad47SMarcel Moolenaar SRCTOPS list of tops of the src tree(s). 2037750ad47SMarcel Moolenaar 2047750ad47SMarcel Moolenaar CURDIR the src directory 'bmake' was run from. 2057750ad47SMarcel Moolenaar 2067750ad47SMarcel Moolenaar RELDIR the relative path from SRCTOP to CURDIR 2077750ad47SMarcel Moolenaar 2087750ad47SMarcel Moolenaar MACHINE the machine we built for. 2097750ad47SMarcel Moolenaar set to 'none' if we are not cross-building. 21051048477SSimon J. Gerraty More specifically if machine cannot be deduced from objdirs. 2117750ad47SMarcel Moolenaar 212bf062775SSimon J. Gerraty TARGET_SPEC 213bf062775SSimon J. Gerraty Sometimes MACHINE isn't enough. 214bf062775SSimon J. Gerraty 2157750ad47SMarcel Moolenaar HOST_TARGET 216ccfb9654SSimon J. Gerraty when we build for the pseudo machine 'host' 2177750ad47SMarcel Moolenaar the object tree uses HOST_TARGET rather than MACHINE. 2187750ad47SMarcel Moolenaar 2197750ad47SMarcel Moolenaar OBJROOTS a list of the common prefix for all obj dirs it might 2207750ad47SMarcel Moolenaar end in '/' or '-'. 2217750ad47SMarcel Moolenaar 2227750ad47SMarcel Moolenaar DPDEPS names an optional file to which per file dependencies 2237750ad47SMarcel Moolenaar will be appended. 2247750ad47SMarcel Moolenaar For example if 'some/path/foo.h' is read from SRCTOP 2257750ad47SMarcel Moolenaar then 'DPDEPS_some/path/foo.h +=' "RELDIR" is output. 2267750ad47SMarcel Moolenaar This can allow 'bmake' to learn all the dirs within 2277750ad47SMarcel Moolenaar the tree that depend on 'foo.h' 2287750ad47SMarcel Moolenaar 229ccfb9654SSimon J. Gerraty EXCLUDES 230ccfb9654SSimon J. Gerraty A list of paths to ignore. 231ccfb9654SSimon J. Gerraty ccache(1) can otherwise be trouble. 232ccfb9654SSimon J. Gerraty 2337750ad47SMarcel Moolenaar debug desired debug level 2347750ad47SMarcel Moolenaar 2357750ad47SMarcel Moolenaar debug_out open file to send debug output to (sys.stderr) 2367750ad47SMarcel Moolenaar 2377750ad47SMarcel Moolenaar """ 2387750ad47SMarcel Moolenaar 2397750ad47SMarcel Moolenaar self.name = name 2403b26e5a4SSimon J. Gerraty self.debug = conf.get('debug', 0) 2413b26e5a4SSimon J. Gerraty self.debug_out = conf.get('debug_out', sys.stderr) 2427750ad47SMarcel Moolenaar 2433b26e5a4SSimon J. Gerraty self.machine = conf.get('MACHINE', '') 2443b26e5a4SSimon J. Gerraty self.machine_arch = conf.get('MACHINE_ARCH', '') 2453b26e5a4SSimon J. Gerraty self.target_spec = conf.get('TARGET_SPEC', self.machine) 2463b26e5a4SSimon J. Gerraty self.exts = target_spec_exts(self.target_spec) 2473b26e5a4SSimon J. Gerraty self.curdir = conf.get('CURDIR') 2483b26e5a4SSimon J. Gerraty self.reldir = conf.get('RELDIR') 2493b26e5a4SSimon J. Gerraty self.dpdeps = conf.get('DPDEPS') 250*bf7aa99aSSimon J. Gerraty self.pids = {} 251d5ddb276SSimon J. Gerraty self.line = 0 2524ed4429cSSimon J. Gerraty 2537750ad47SMarcel Moolenaar if not self.conf: 2547750ad47SMarcel Moolenaar # some of the steps below we want to do only once 2557750ad47SMarcel Moolenaar self.conf = conf 2563b26e5a4SSimon J. Gerraty self.host_target = conf.get('HOST_TARGET') 2573b26e5a4SSimon J. Gerraty for srctop in conf.get('SRCTOPS', []): 2587750ad47SMarcel Moolenaar if srctop[-1] != '/': 2597750ad47SMarcel Moolenaar srctop += '/' 2607750ad47SMarcel Moolenaar if not srctop in self.srctops: 2617750ad47SMarcel Moolenaar self.srctops.append(srctop) 262fbc1b149SSimon J. Gerraty _srctop = os.path.realpath(srctop) 263fbc1b149SSimon J. Gerraty if _srctop[-1] != '/': 264fbc1b149SSimon J. Gerraty _srctop += '/' 265fbc1b149SSimon J. Gerraty if not _srctop in self.srctops: 266fbc1b149SSimon J. Gerraty self.srctops.append(_srctop) 2677750ad47SMarcel Moolenaar 268bf062775SSimon J. Gerraty trim_list = add_trims(self.machine) 2698c95c434SSimon J. Gerraty if self.machine == 'host': 270bf062775SSimon J. Gerraty trim_list += add_trims(self.host_target) 2713b26e5a4SSimon J. Gerraty if self.target_spec != self.machine: 272bf062775SSimon J. Gerraty trim_list += add_trims(self.target_spec) 273876336c8SSimon J. Gerraty 2743b26e5a4SSimon J. Gerraty for objroot in conf.get('OBJROOTS', []): 2758c95c434SSimon J. Gerraty for e in trim_list: 2764ed4429cSSimon J. Gerraty if objroot.endswith(e): 2774ed4429cSSimon J. Gerraty # this is not what we want - fix it 2784ed4429cSSimon J. Gerraty objroot = objroot[0:-len(e)] 279b47b9f6bSSimon J. Gerraty 280b47b9f6bSSimon J. Gerraty if objroot[-1] != '/': 2814ed4429cSSimon J. Gerraty objroot += '/' 2827750ad47SMarcel Moolenaar if not objroot in self.objroots: 2837750ad47SMarcel Moolenaar self.objroots.append(objroot) 2847750ad47SMarcel Moolenaar _objroot = os.path.realpath(objroot) 2857750ad47SMarcel Moolenaar if objroot[-1] == '/': 2867750ad47SMarcel Moolenaar _objroot += '/' 2877750ad47SMarcel Moolenaar if not _objroot in self.objroots: 2887750ad47SMarcel Moolenaar self.objroots.append(_objroot) 2897750ad47SMarcel Moolenaar 2904ed4429cSSimon J. Gerraty # we want the longest match 2914ed4429cSSimon J. Gerraty self.srctops.sort(reverse=True) 2924ed4429cSSimon J. Gerraty self.objroots.sort(reverse=True) 2934ed4429cSSimon J. Gerraty 2943b26e5a4SSimon J. Gerraty self.excludes = conf.get('EXCLUDES', []) 295ccfb9654SSimon J. Gerraty 2967750ad47SMarcel Moolenaar if self.debug: 29710ea6facSSimon J. Gerraty print("host_target=", self.host_target, file=self.debug_out) 29810ea6facSSimon J. Gerraty print("srctops=", self.srctops, file=self.debug_out) 29910ea6facSSimon J. Gerraty print("objroots=", self.objroots, file=self.debug_out) 300ccfb9654SSimon J. Gerraty print("excludes=", self.excludes, file=self.debug_out) 3013b26e5a4SSimon J. Gerraty print("ext_list=", self.exts, file=self.debug_out) 3027750ad47SMarcel Moolenaar 3037750ad47SMarcel Moolenaar self.dirdep_re = re.compile(r'([^/]+)/(.+)') 3047750ad47SMarcel Moolenaar 3057750ad47SMarcel Moolenaar if self.dpdeps and not self.reldir: 3067750ad47SMarcel Moolenaar if self.debug: 30710ea6facSSimon J. Gerraty print("need reldir:", end=' ', file=self.debug_out) 3087750ad47SMarcel Moolenaar if self.curdir: 3097750ad47SMarcel Moolenaar srctop = self.find_top(self.curdir, self.srctops) 3107750ad47SMarcel Moolenaar if srctop: 3117750ad47SMarcel Moolenaar self.reldir = self.curdir.replace(srctop,'') 3127750ad47SMarcel Moolenaar if self.debug: 31310ea6facSSimon J. Gerraty print(self.reldir, file=self.debug_out) 3147750ad47SMarcel Moolenaar if not self.reldir: 3157750ad47SMarcel Moolenaar self.dpdeps = None # we cannot do it? 3167750ad47SMarcel Moolenaar 317876336c8SSimon J. Gerraty self.cwd = os.getcwd() # make sure this is initialized 318ccfb9654SSimon J. Gerraty self.last_dir = self.cwd 319876336c8SSimon J. Gerraty 3207750ad47SMarcel Moolenaar if name: 321d5ddb276SSimon J. Gerraty self.try_parse() 3227750ad47SMarcel Moolenaar 3237750ad47SMarcel Moolenaar def reset(self): 3247750ad47SMarcel Moolenaar """reset state if we are being passed meta files from multiple directories.""" 3257750ad47SMarcel Moolenaar self.seen = {} 3267750ad47SMarcel Moolenaar self.obj_deps = [] 3277750ad47SMarcel Moolenaar self.src_deps = [] 3287750ad47SMarcel Moolenaar self.file_deps = [] 3297750ad47SMarcel Moolenaar 3307750ad47SMarcel Moolenaar def dirdeps(self, sep='\n'): 3317750ad47SMarcel Moolenaar """return DIRDEPS""" 3327750ad47SMarcel Moolenaar return sep.strip() + sep.join(self.obj_deps) 3337750ad47SMarcel Moolenaar 3347750ad47SMarcel Moolenaar def src_dirdeps(self, sep='\n'): 3357750ad47SMarcel Moolenaar """return SRC_DIRDEPS""" 3367750ad47SMarcel Moolenaar return sep.strip() + sep.join(self.src_deps) 3377750ad47SMarcel Moolenaar 3387750ad47SMarcel Moolenaar def file_depends(self, out=None): 3397750ad47SMarcel Moolenaar """Append DPDEPS_${file} += ${RELDIR} 3407750ad47SMarcel Moolenaar for each file we saw, to the output file.""" 3417750ad47SMarcel Moolenaar if not self.reldir: 3427750ad47SMarcel Moolenaar return None 3437750ad47SMarcel Moolenaar for f in sort_unique(self.file_deps): 34410ea6facSSimon J. Gerraty print('DPDEPS_%s += %s' % (f, self.reldir), file=out) 345b47b9f6bSSimon J. Gerraty # these entries provide for reverse DIRDEPS lookup 346b47b9f6bSSimon J. Gerraty for f in self.obj_deps: 347b47b9f6bSSimon J. Gerraty print('DEPDIRS_%s += %s' % (f, self.reldir), file=out) 3487750ad47SMarcel Moolenaar 3497750ad47SMarcel Moolenaar def seenit(self, dir): 3507750ad47SMarcel Moolenaar """rememer that we have seen dir.""" 3517750ad47SMarcel Moolenaar self.seen[dir] = 1 3527750ad47SMarcel Moolenaar 3537750ad47SMarcel Moolenaar def add(self, list, data, clue=''): 3547750ad47SMarcel Moolenaar """add data to list if it isn't already there.""" 3557750ad47SMarcel Moolenaar if data not in list: 3567750ad47SMarcel Moolenaar list.append(data) 3577750ad47SMarcel Moolenaar if self.debug: 35810ea6facSSimon J. Gerraty print("%s: %sAdd: %s" % (self.name, clue, data), file=self.debug_out) 3597750ad47SMarcel Moolenaar 3607750ad47SMarcel Moolenaar def find_top(self, path, list): 361ccfb9654SSimon J. Gerraty """the logical tree may be split across multiple trees""" 3627750ad47SMarcel Moolenaar for top in list: 3637750ad47SMarcel Moolenaar if path.startswith(top): 3647750ad47SMarcel Moolenaar if self.debug > 2: 36510ea6facSSimon J. Gerraty print("found in", top, file=self.debug_out) 3667750ad47SMarcel Moolenaar return top 3677750ad47SMarcel Moolenaar return None 3687750ad47SMarcel Moolenaar 3697750ad47SMarcel Moolenaar def find_obj(self, objroot, dir, path, input): 3707750ad47SMarcel Moolenaar """return path within objroot, taking care of .dirdep files""" 3717750ad47SMarcel Moolenaar ddep = None 3727750ad47SMarcel Moolenaar for ddepf in [path + '.dirdep', dir + '/.dirdep']: 3737750ad47SMarcel Moolenaar if not ddep and os.path.exists(ddepf): 37410ea6facSSimon J. Gerraty ddep = open(ddepf, 'r').readline().strip('# \n') 3757750ad47SMarcel Moolenaar if self.debug > 1: 37610ea6facSSimon J. Gerraty print("found %s: %s\n" % (ddepf, ddep), file=self.debug_out) 3773b26e5a4SSimon J. Gerraty for e in self.exts: 3783b26e5a4SSimon J. Gerraty if ddep.endswith(e): 3793b26e5a4SSimon J. Gerraty ddep = ddep[0:-len(e)] 3803b26e5a4SSimon J. Gerraty break 3817750ad47SMarcel Moolenaar 3827750ad47SMarcel Moolenaar if not ddep: 3837750ad47SMarcel Moolenaar # no .dirdeps, so remember that we've seen the raw input 3847750ad47SMarcel Moolenaar self.seenit(input) 3857750ad47SMarcel Moolenaar self.seenit(dir) 3867750ad47SMarcel Moolenaar if self.machine == 'none': 3877750ad47SMarcel Moolenaar if dir.startswith(objroot): 3887750ad47SMarcel Moolenaar return dir.replace(objroot,'') 3897750ad47SMarcel Moolenaar return None 3907750ad47SMarcel Moolenaar m = self.dirdep_re.match(dir.replace(objroot,'')) 3917750ad47SMarcel Moolenaar if m: 3927750ad47SMarcel Moolenaar ddep = m.group(2) 3937750ad47SMarcel Moolenaar dmachine = m.group(1) 3947750ad47SMarcel Moolenaar if dmachine != self.machine: 3957750ad47SMarcel Moolenaar if not (self.machine == 'host' and 3967750ad47SMarcel Moolenaar dmachine == self.host_target): 3977750ad47SMarcel Moolenaar if self.debug > 2: 39810ea6facSSimon J. Gerraty print("adding .%s to %s" % (dmachine, ddep), file=self.debug_out) 3997750ad47SMarcel Moolenaar ddep += '.' + dmachine 4007750ad47SMarcel Moolenaar 4017750ad47SMarcel Moolenaar return ddep 4027750ad47SMarcel Moolenaar 403d5ddb276SSimon J. Gerraty def try_parse(self, name=None, file=None): 404d5ddb276SSimon J. Gerraty """give file and line number causing exception""" 405d5ddb276SSimon J. Gerraty try: 406d5ddb276SSimon J. Gerraty self.parse(name, file) 407d5ddb276SSimon J. Gerraty except: 408d5ddb276SSimon J. Gerraty # give a useful clue 40910ea6facSSimon J. Gerraty print('{}:{}: '.format(self.name, self.line), end=' ', file=sys.stderr) 410d5ddb276SSimon J. Gerraty raise 411d5ddb276SSimon J. Gerraty 4127750ad47SMarcel Moolenaar def parse(self, name=None, file=None): 4137750ad47SMarcel Moolenaar """A meta file looks like: 4147750ad47SMarcel Moolenaar 4157750ad47SMarcel Moolenaar # Meta data file "path" 4167750ad47SMarcel Moolenaar CMD "command-line" 4177750ad47SMarcel Moolenaar CWD "cwd" 4187750ad47SMarcel Moolenaar TARGET "target" 4197750ad47SMarcel Moolenaar -- command output -- 4207750ad47SMarcel Moolenaar -- filemon acquired metadata -- 4217750ad47SMarcel Moolenaar # buildmon version 3 4227750ad47SMarcel Moolenaar V 3 4237750ad47SMarcel Moolenaar C "pid" "cwd" 4247750ad47SMarcel Moolenaar E "pid" "path" 4257750ad47SMarcel Moolenaar F "pid" "child" 4267750ad47SMarcel Moolenaar R "pid" "path" 4277750ad47SMarcel Moolenaar W "pid" "path" 4287750ad47SMarcel Moolenaar X "pid" "status" 4297750ad47SMarcel Moolenaar D "pid" "path" 4307750ad47SMarcel Moolenaar L "pid" "src" "target" 4317750ad47SMarcel Moolenaar M "pid" "old" "new" 4327750ad47SMarcel Moolenaar S "pid" "path" 4337750ad47SMarcel Moolenaar # Bye bye 4347750ad47SMarcel Moolenaar 4357750ad47SMarcel Moolenaar We go to some effort to avoid processing a dependency more than once. 4367750ad47SMarcel Moolenaar Of the above record types only C,E,F,L,R,V and W are of interest. 4377750ad47SMarcel Moolenaar """ 4387750ad47SMarcel Moolenaar 4397750ad47SMarcel Moolenaar version = 0 # unknown 4407750ad47SMarcel Moolenaar if name: 4417750ad47SMarcel Moolenaar self.name = name; 4427750ad47SMarcel Moolenaar if file: 4437750ad47SMarcel Moolenaar f = file 444ccfb9654SSimon J. Gerraty cwd = self.last_dir = self.cwd 4457750ad47SMarcel Moolenaar else: 44610ea6facSSimon J. Gerraty f = open(self.name, 'r') 4477750ad47SMarcel Moolenaar skip = True 4487750ad47SMarcel Moolenaar pid_cwd = {} 4497750ad47SMarcel Moolenaar pid_last_dir = {} 4507750ad47SMarcel Moolenaar last_pid = 0 451*bf7aa99aSSimon J. Gerraty eof_token = False 4527750ad47SMarcel Moolenaar 453d5ddb276SSimon J. Gerraty self.line = 0 4547750ad47SMarcel Moolenaar if self.curdir: 4557750ad47SMarcel Moolenaar self.seenit(self.curdir) # we ignore this 4567750ad47SMarcel Moolenaar 457*bf7aa99aSSimon J. Gerraty interesting = '#CEFLRVX' 4587750ad47SMarcel Moolenaar for line in f: 459d5ddb276SSimon J. Gerraty self.line += 1 4607750ad47SMarcel Moolenaar # ignore anything we don't care about 4617750ad47SMarcel Moolenaar if not line[0] in interesting: 4627750ad47SMarcel Moolenaar continue 4637750ad47SMarcel Moolenaar if self.debug > 2: 46410ea6facSSimon J. Gerraty print("input:", line, end=' ', file=self.debug_out) 4657750ad47SMarcel Moolenaar w = line.split() 4667750ad47SMarcel Moolenaar 4677750ad47SMarcel Moolenaar if skip: 4687750ad47SMarcel Moolenaar if w[0] == 'V': 4697750ad47SMarcel Moolenaar skip = False 4707750ad47SMarcel Moolenaar version = int(w[1]) 4717750ad47SMarcel Moolenaar """ 4727750ad47SMarcel Moolenaar if version < 4: 4737750ad47SMarcel Moolenaar # we cannot ignore 'W' records 4747750ad47SMarcel Moolenaar # as they may be 'rw' 4757750ad47SMarcel Moolenaar interesting += 'W' 4767750ad47SMarcel Moolenaar """ 4777750ad47SMarcel Moolenaar elif w[0] == 'CWD': 478ccfb9654SSimon J. Gerraty self.cwd = cwd = self.last_dir = w[1] 4797750ad47SMarcel Moolenaar self.seenit(cwd) # ignore this 4807750ad47SMarcel Moolenaar if self.debug: 48110ea6facSSimon J. Gerraty print("%s: CWD=%s" % (self.name, cwd), file=self.debug_out) 4827750ad47SMarcel Moolenaar continue 4837750ad47SMarcel Moolenaar 484*bf7aa99aSSimon J. Gerraty if w[0] == '#': 485*bf7aa99aSSimon J. Gerraty # check the file has not been truncated 486*bf7aa99aSSimon J. Gerraty if line.find('Bye') > 0: 487*bf7aa99aSSimon J. Gerraty eof_token = True 488*bf7aa99aSSimon J. Gerraty continue 489*bf7aa99aSSimon J. Gerraty 4907750ad47SMarcel Moolenaar pid = int(w[1]) 4917750ad47SMarcel Moolenaar if pid != last_pid: 4927750ad47SMarcel Moolenaar if last_pid: 493ccfb9654SSimon J. Gerraty pid_last_dir[last_pid] = self.last_dir 4943b26e5a4SSimon J. Gerraty cwd = pid_cwd.get(pid, self.cwd) 4953b26e5a4SSimon J. Gerraty self.last_dir = pid_last_dir.get(pid, self.cwd) 4967750ad47SMarcel Moolenaar last_pid = pid 4977750ad47SMarcel Moolenaar 4987750ad47SMarcel Moolenaar # process operations 4997750ad47SMarcel Moolenaar if w[0] == 'F': 5007750ad47SMarcel Moolenaar npid = int(w[2]) 5017750ad47SMarcel Moolenaar pid_cwd[npid] = cwd 5027750ad47SMarcel Moolenaar pid_last_dir[npid] = cwd 5037750ad47SMarcel Moolenaar last_pid = npid 5047750ad47SMarcel Moolenaar continue 5057750ad47SMarcel Moolenaar elif w[0] == 'C': 5067750ad47SMarcel Moolenaar cwd = abspath(w[2], cwd, None, self.debug, self.debug_out) 507960b77beSSimon J. Gerraty if not cwd: 508960b77beSSimon J. Gerraty cwd = w[2] 509960b77beSSimon J. Gerraty if self.debug > 1: 510960b77beSSimon J. Gerraty print("missing cwd=", cwd, file=self.debug_out) 5117750ad47SMarcel Moolenaar if cwd.endswith('/.'): 5127750ad47SMarcel Moolenaar cwd = cwd[0:-2] 513b47b9f6bSSimon J. Gerraty self.last_dir = pid_last_dir[pid] = cwd 514b47b9f6bSSimon J. Gerraty pid_cwd[pid] = cwd 5157750ad47SMarcel Moolenaar if self.debug > 1: 51610ea6facSSimon J. Gerraty print("cwd=", cwd, file=self.debug_out) 5177750ad47SMarcel Moolenaar continue 5187750ad47SMarcel Moolenaar 519*bf7aa99aSSimon J. Gerraty if w[0] == 'X': 520*bf7aa99aSSimon J. Gerraty try: 521*bf7aa99aSSimon J. Gerraty del self.pids[pid] 522*bf7aa99aSSimon J. Gerraty except KeyError: 523*bf7aa99aSSimon J. Gerraty pass 524*bf7aa99aSSimon J. Gerraty continue 525*bf7aa99aSSimon J. Gerraty 5267750ad47SMarcel Moolenaar if w[2] in self.seen: 5277750ad47SMarcel Moolenaar if self.debug > 2: 52810ea6facSSimon J. Gerraty print("seen:", w[2], file=self.debug_out) 5297750ad47SMarcel Moolenaar continue 5307750ad47SMarcel Moolenaar # file operations 5317750ad47SMarcel Moolenaar if w[0] in 'ML': 532ccfb9654SSimon J. Gerraty # these are special, tread src as read and 533ccfb9654SSimon J. Gerraty # target as write 534960b77beSSimon J. Gerraty self.parse_path(w[2].strip("'"), cwd, 'R', w) 535960b77beSSimon J. Gerraty self.parse_path(w[3].strip("'"), cwd, 'W', w) 536ccfb9654SSimon J. Gerraty continue 537ccfb9654SSimon J. Gerraty elif w[0] in 'ERWS': 5387750ad47SMarcel Moolenaar path = w[2] 539*bf7aa99aSSimon J. Gerraty if w[0] == 'E': 540*bf7aa99aSSimon J. Gerraty self.pids[pid] = path 541*bf7aa99aSSimon J. Gerraty elif path == '.': 542960b77beSSimon J. Gerraty continue 543ccfb9654SSimon J. Gerraty self.parse_path(path, cwd, w[0], w) 544ccfb9654SSimon J. Gerraty 545*bf7aa99aSSimon J. Gerraty if version == 0: 546*bf7aa99aSSimon J. Gerraty raise AssertionError('missing filemon data') 547*bf7aa99aSSimon J. Gerraty if not eof_token: 548*bf7aa99aSSimon J. Gerraty raise AssertionError('truncated filemon data') 549*bf7aa99aSSimon J. Gerraty 550*bf7aa99aSSimon J. Gerraty setid_pids = [] 551*bf7aa99aSSimon J. Gerraty # self.pids should be empty! 552*bf7aa99aSSimon J. Gerraty for pid,path in self.pids.items(): 553*bf7aa99aSSimon J. Gerraty try: 554*bf7aa99aSSimon J. Gerraty # no guarantee that path is still valid 555*bf7aa99aSSimon J. Gerraty if os.stat(path).st_mode & (stat.S_ISUID|stat.S_ISGID): 556*bf7aa99aSSimon J. Gerraty # we do not expect anything after Exec 557*bf7aa99aSSimon J. Gerraty setid_pids.append(pid) 558*bf7aa99aSSimon J. Gerraty continue 559*bf7aa99aSSimon J. Gerraty except: 560*bf7aa99aSSimon J. Gerraty # we do not care why the above fails, 561*bf7aa99aSSimon J. Gerraty # we do not want to miss the ERROR below. 562*bf7aa99aSSimon J. Gerraty pass 563*bf7aa99aSSimon J. Gerraty print("ERROR: missing eXit for {} pid {}".format(path, pid)) 564*bf7aa99aSSimon J. Gerraty for pid in setid_pids: 565*bf7aa99aSSimon J. Gerraty del self.pids[pid] 566*bf7aa99aSSimon J. Gerraty assert(len(self.pids) == 0) 567ccfb9654SSimon J. Gerraty if not file: 568ccfb9654SSimon J. Gerraty f.close() 569ccfb9654SSimon J. Gerraty 570c0339e7dSSimon J. Gerraty def is_src(self, base, dir, rdir): 571c0339e7dSSimon J. Gerraty """is base in srctop""" 572c0339e7dSSimon J. Gerraty for dir in [dir,rdir]: 573c0339e7dSSimon J. Gerraty if not dir: 574c0339e7dSSimon J. Gerraty continue 575c0339e7dSSimon J. Gerraty path = '/'.join([dir,base]) 576c0339e7dSSimon J. Gerraty srctop = self.find_top(path, self.srctops) 577c0339e7dSSimon J. Gerraty if srctop: 578c0339e7dSSimon J. Gerraty if self.dpdeps: 579c0339e7dSSimon J. Gerraty self.add(self.file_deps, path.replace(srctop,''), 'file') 580c0339e7dSSimon J. Gerraty self.add(self.src_deps, dir.replace(srctop,''), 'src') 581c0339e7dSSimon J. Gerraty self.seenit(dir) 582c0339e7dSSimon J. Gerraty return True 583c0339e7dSSimon J. Gerraty return False 584c0339e7dSSimon J. Gerraty 585ccfb9654SSimon J. Gerraty def parse_path(self, path, cwd, op=None, w=[]): 586ccfb9654SSimon J. Gerraty """look at a path for the op specified""" 587ccfb9654SSimon J. Gerraty 588ccfb9654SSimon J. Gerraty if not op: 589ccfb9654SSimon J. Gerraty op = w[0] 590ccfb9654SSimon J. Gerraty 591fbc1b149SSimon J. Gerraty # we are never interested in .dirdep files as dependencies 592fbc1b149SSimon J. Gerraty if path.endswith('.dirdep'): 593ccfb9654SSimon J. Gerraty return 594ccfb9654SSimon J. Gerraty for p in self.excludes: 595ccfb9654SSimon J. Gerraty if p and path.startswith(p): 596ccfb9654SSimon J. Gerraty if self.debug > 2: 597e1dfa657SBryan Drewery print("exclude:", p, path, file=self.debug_out) 598ccfb9654SSimon J. Gerraty return 5997750ad47SMarcel Moolenaar # we don't want to resolve the last component if it is 6007750ad47SMarcel Moolenaar # a symlink 601ccfb9654SSimon J. Gerraty path = resolve(path, cwd, self.last_dir, self.debug, self.debug_out) 6027750ad47SMarcel Moolenaar if not path: 603ccfb9654SSimon J. Gerraty return 6047750ad47SMarcel Moolenaar dir,base = os.path.split(path) 6057750ad47SMarcel Moolenaar if dir in self.seen: 6067750ad47SMarcel Moolenaar if self.debug > 2: 60710ea6facSSimon J. Gerraty print("seen:", dir, file=self.debug_out) 608ccfb9654SSimon J. Gerraty return 6097750ad47SMarcel Moolenaar # we can have a path in an objdir which is a link 6107750ad47SMarcel Moolenaar # to the src dir, we may need to add dependencies for each 6117750ad47SMarcel Moolenaar rdir = dir 612ccfb9654SSimon J. Gerraty dir = abspath(dir, cwd, self.last_dir, self.debug, self.debug_out) 6133b26e5a4SSimon J. Gerraty if dir: 6146d4f05fdSSimon J. Gerraty rdir = os.path.realpath(dir) 6153b26e5a4SSimon J. Gerraty else: 6163b26e5a4SSimon J. Gerraty dir = rdir 617c0339e7dSSimon J. Gerraty if rdir == dir: 618c0339e7dSSimon J. Gerraty rdir = None 6197750ad47SMarcel Moolenaar # now put path back together 6207750ad47SMarcel Moolenaar path = '/'.join([dir,base]) 6217750ad47SMarcel Moolenaar if self.debug > 1: 62210ea6facSSimon J. Gerraty print("raw=%s rdir=%s dir=%s path=%s" % (w[2], rdir, dir, path), file=self.debug_out) 623ccfb9654SSimon J. Gerraty if op in 'RWS': 624ccfb9654SSimon J. Gerraty if path in [self.last_dir, cwd, self.cwd, self.curdir]: 6257750ad47SMarcel Moolenaar if self.debug > 1: 62610ea6facSSimon J. Gerraty print("skipping:", path, file=self.debug_out) 627ccfb9654SSimon J. Gerraty return 6287750ad47SMarcel Moolenaar if os.path.isdir(path): 629ccfb9654SSimon J. Gerraty if op in 'RW': 630ccfb9654SSimon J. Gerraty self.last_dir = path; 6317750ad47SMarcel Moolenaar if self.debug > 1: 632ccfb9654SSimon J. Gerraty print("ldir=", self.last_dir, file=self.debug_out) 633ccfb9654SSimon J. Gerraty return 6347750ad47SMarcel Moolenaar 635960b77beSSimon J. Gerraty if op in 'ER': 6367750ad47SMarcel Moolenaar # finally, we get down to it 6377750ad47SMarcel Moolenaar if dir == self.cwd or dir == self.curdir: 638ccfb9654SSimon J. Gerraty return 639c0339e7dSSimon J. Gerraty if self.is_src(base, dir, rdir): 6407750ad47SMarcel Moolenaar self.seenit(w[2]) 641c0339e7dSSimon J. Gerraty if not rdir: 642ccfb9654SSimon J. Gerraty return 6437750ad47SMarcel Moolenaar 6447750ad47SMarcel Moolenaar objroot = None 6457750ad47SMarcel Moolenaar for dir in [dir,rdir]: 6467750ad47SMarcel Moolenaar if not dir: 6477750ad47SMarcel Moolenaar continue 6487750ad47SMarcel Moolenaar objroot = self.find_top(dir, self.objroots) 6497750ad47SMarcel Moolenaar if objroot: 6507750ad47SMarcel Moolenaar break 6517750ad47SMarcel Moolenaar if objroot: 6527750ad47SMarcel Moolenaar ddep = self.find_obj(objroot, dir, path, w[2]) 6537750ad47SMarcel Moolenaar if ddep: 6547750ad47SMarcel Moolenaar self.add(self.obj_deps, ddep, 'obj') 655b47b9f6bSSimon J. Gerraty if self.dpdeps and objroot.endswith('/stage/'): 656b47b9f6bSSimon J. Gerraty sp = '/'.join(path.replace(objroot,'').split('/')[1:]) 657b47b9f6bSSimon J. Gerraty self.add(self.file_deps, sp, 'file') 6587750ad47SMarcel Moolenaar else: 6597750ad47SMarcel Moolenaar # don't waste time looking again 6607750ad47SMarcel Moolenaar self.seenit(w[2]) 6617750ad47SMarcel Moolenaar self.seenit(dir) 6627750ad47SMarcel Moolenaar 6637750ad47SMarcel Moolenaar 6647750ad47SMarcel Moolenaardef main(argv, klass=MetaFile, xopts='', xoptf=None): 6657750ad47SMarcel Moolenaar """Simple driver for class MetaFile. 6667750ad47SMarcel Moolenaar 6677750ad47SMarcel Moolenaar Usage: 6687750ad47SMarcel Moolenaar script [options] [key=value ...] "meta" ... 6697750ad47SMarcel Moolenaar 6707750ad47SMarcel Moolenaar Options and key=value pairs contribute to the 6717750ad47SMarcel Moolenaar dictionary passed to MetaFile. 6727750ad47SMarcel Moolenaar 6737750ad47SMarcel Moolenaar -S "SRCTOP" 6747750ad47SMarcel Moolenaar add "SRCTOP" to the "SRCTOPS" list. 6757750ad47SMarcel Moolenaar 6767750ad47SMarcel Moolenaar -C "CURDIR" 6777750ad47SMarcel Moolenaar 6787750ad47SMarcel Moolenaar -O "OBJROOT" 6797750ad47SMarcel Moolenaar add "OBJROOT" to the "OBJROOTS" list. 6807750ad47SMarcel Moolenaar 6817750ad47SMarcel Moolenaar -m "MACHINE" 6827750ad47SMarcel Moolenaar 683bf062775SSimon J. Gerraty -a "MACHINE_ARCH" 684bf062775SSimon J. Gerraty 6857750ad47SMarcel Moolenaar -H "HOST_TARGET" 6867750ad47SMarcel Moolenaar 6877750ad47SMarcel Moolenaar -D "DPDEPS" 6887750ad47SMarcel Moolenaar 6897750ad47SMarcel Moolenaar -d bumps debug level 6907750ad47SMarcel Moolenaar 6917750ad47SMarcel Moolenaar """ 6927750ad47SMarcel Moolenaar import getopt 6937750ad47SMarcel Moolenaar 6947750ad47SMarcel Moolenaar # import Psyco if we can 6957750ad47SMarcel Moolenaar # it can speed things up quite a bit 6967750ad47SMarcel Moolenaar have_psyco = 0 6977750ad47SMarcel Moolenaar try: 6987750ad47SMarcel Moolenaar import psyco 6997750ad47SMarcel Moolenaar psyco.full() 7007750ad47SMarcel Moolenaar have_psyco = 1 7017750ad47SMarcel Moolenaar except: 7027750ad47SMarcel Moolenaar pass 7037750ad47SMarcel Moolenaar 7047750ad47SMarcel Moolenaar conf = { 7057750ad47SMarcel Moolenaar 'SRCTOPS': [], 7067750ad47SMarcel Moolenaar 'OBJROOTS': [], 707ccfb9654SSimon J. Gerraty 'EXCLUDES': [], 7087750ad47SMarcel Moolenaar } 7097750ad47SMarcel Moolenaar 7107750ad47SMarcel Moolenaar try: 7117750ad47SMarcel Moolenaar machine = os.environ['MACHINE'] 7127750ad47SMarcel Moolenaar if machine: 7137750ad47SMarcel Moolenaar conf['MACHINE'] = machine 714bf062775SSimon J. Gerraty machine_arch = os.environ['MACHINE_ARCH'] 715bf062775SSimon J. Gerraty if machine_arch: 716bf062775SSimon J. Gerraty conf['MACHINE_ARCH'] = machine_arch 7177750ad47SMarcel Moolenaar srctop = os.environ['SB_SRC'] 7187750ad47SMarcel Moolenaar if srctop: 7197750ad47SMarcel Moolenaar conf['SRCTOPS'].append(srctop) 7207750ad47SMarcel Moolenaar objroot = os.environ['SB_OBJROOT'] 7217750ad47SMarcel Moolenaar if objroot: 7227750ad47SMarcel Moolenaar conf['OBJROOTS'].append(objroot) 7237750ad47SMarcel Moolenaar except: 7247750ad47SMarcel Moolenaar pass 7257750ad47SMarcel Moolenaar 7267750ad47SMarcel Moolenaar debug = 0 7277750ad47SMarcel Moolenaar output = True 7287750ad47SMarcel Moolenaar 729ccfb9654SSimon J. Gerraty opts, args = getopt.getopt(argv[1:], 'a:dS:C:O:R:m:D:H:qT:X:' + xopts) 7307750ad47SMarcel Moolenaar for o, a in opts: 731bf062775SSimon J. Gerraty if o == '-a': 732bf062775SSimon J. Gerraty conf['MACHINE_ARCH'] = a 733bf062775SSimon J. Gerraty elif o == '-d': 7347750ad47SMarcel Moolenaar debug += 1 7357750ad47SMarcel Moolenaar elif o == '-q': 7367750ad47SMarcel Moolenaar output = False 7377750ad47SMarcel Moolenaar elif o == '-H': 7387750ad47SMarcel Moolenaar conf['HOST_TARGET'] = a 7397750ad47SMarcel Moolenaar elif o == '-S': 7407750ad47SMarcel Moolenaar if a not in conf['SRCTOPS']: 7417750ad47SMarcel Moolenaar conf['SRCTOPS'].append(a) 7427750ad47SMarcel Moolenaar elif o == '-C': 7437750ad47SMarcel Moolenaar conf['CURDIR'] = a 7447750ad47SMarcel Moolenaar elif o == '-O': 7457750ad47SMarcel Moolenaar if a not in conf['OBJROOTS']: 7467750ad47SMarcel Moolenaar conf['OBJROOTS'].append(a) 7477750ad47SMarcel Moolenaar elif o == '-R': 7487750ad47SMarcel Moolenaar conf['RELDIR'] = a 7497750ad47SMarcel Moolenaar elif o == '-D': 7507750ad47SMarcel Moolenaar conf['DPDEPS'] = a 7517750ad47SMarcel Moolenaar elif o == '-m': 7527750ad47SMarcel Moolenaar conf['MACHINE'] = a 753bf062775SSimon J. Gerraty elif o == '-T': 754bf062775SSimon J. Gerraty conf['TARGET_SPEC'] = a 755ccfb9654SSimon J. Gerraty elif o == '-X': 756ccfb9654SSimon J. Gerraty if a not in conf['EXCLUDES']: 757ccfb9654SSimon J. Gerraty conf['EXCLUDES'].append(a) 7587750ad47SMarcel Moolenaar elif xoptf: 7597750ad47SMarcel Moolenaar xoptf(o, a, conf) 7607750ad47SMarcel Moolenaar 7617750ad47SMarcel Moolenaar conf['debug'] = debug 7627750ad47SMarcel Moolenaar 7637750ad47SMarcel Moolenaar # get any var=val assignments 7647750ad47SMarcel Moolenaar eaten = [] 7657750ad47SMarcel Moolenaar for a in args: 7667750ad47SMarcel Moolenaar if a.find('=') > 0: 7677750ad47SMarcel Moolenaar k,v = a.split('=') 7687750ad47SMarcel Moolenaar if k in ['SRCTOP','OBJROOT','SRCTOPS','OBJROOTS']: 7697750ad47SMarcel Moolenaar if k == 'SRCTOP': 7707750ad47SMarcel Moolenaar k = 'SRCTOPS' 7717750ad47SMarcel Moolenaar elif k == 'OBJROOT': 7727750ad47SMarcel Moolenaar k = 'OBJROOTS' 7737750ad47SMarcel Moolenaar if v not in conf[k]: 7747750ad47SMarcel Moolenaar conf[k].append(v) 7757750ad47SMarcel Moolenaar else: 7767750ad47SMarcel Moolenaar conf[k] = v 7777750ad47SMarcel Moolenaar eaten.append(a) 7787750ad47SMarcel Moolenaar continue 7797750ad47SMarcel Moolenaar break 7807750ad47SMarcel Moolenaar 7817750ad47SMarcel Moolenaar for a in eaten: 7827750ad47SMarcel Moolenaar args.remove(a) 7837750ad47SMarcel Moolenaar 7843b26e5a4SSimon J. Gerraty debug_out = conf.get('debug_out', sys.stderr) 7857750ad47SMarcel Moolenaar 7867750ad47SMarcel Moolenaar if debug: 78710ea6facSSimon J. Gerraty print("config:", file=debug_out) 78810ea6facSSimon J. Gerraty print("psyco=", have_psyco, file=debug_out) 78910ea6facSSimon J. Gerraty for k,v in list(conf.items()): 79010ea6facSSimon J. Gerraty print("%s=%s" % (k,v), file=debug_out) 7917750ad47SMarcel Moolenaar 792ccfb9654SSimon J. Gerraty m = None 7937750ad47SMarcel Moolenaar for a in args: 794d5ddb276SSimon J. Gerraty if a.endswith('.meta'): 795ccfb9654SSimon J. Gerraty if not os.path.exists(a): 796ccfb9654SSimon J. Gerraty continue 7977750ad47SMarcel Moolenaar m = klass(a, conf) 798d5ddb276SSimon J. Gerraty elif a.startswith('@'): 799d5ddb276SSimon J. Gerraty # there can actually multiple files per line 800d5ddb276SSimon J. Gerraty for line in open(a[1:]): 801d5ddb276SSimon J. Gerraty for f in line.strip().split(): 802ccfb9654SSimon J. Gerraty if not os.path.exists(f): 803ccfb9654SSimon J. Gerraty continue 804d5ddb276SSimon J. Gerraty m = klass(f, conf) 8057750ad47SMarcel Moolenaar 806ccfb9654SSimon J. Gerraty if output and m: 80710ea6facSSimon J. Gerraty print(m.dirdeps()) 8087750ad47SMarcel Moolenaar 80910ea6facSSimon J. Gerraty print(m.src_dirdeps('\nsrc:')) 8107750ad47SMarcel Moolenaar 8113b26e5a4SSimon J. Gerraty dpdeps = conf.get('DPDEPS') 8127750ad47SMarcel Moolenaar if dpdeps: 8133b26e5a4SSimon J. Gerraty m.file_depends(open(dpdeps, 'w')) 8147750ad47SMarcel Moolenaar 8157750ad47SMarcel Moolenaar return m 8167750ad47SMarcel Moolenaar 8177750ad47SMarcel Moolenaarif __name__ == '__main__': 8187750ad47SMarcel Moolenaar try: 8197750ad47SMarcel Moolenaar main(sys.argv) 8207750ad47SMarcel Moolenaar except: 8217750ad47SMarcel Moolenaar # yes, this goes to stdout 82210ea6facSSimon J. Gerraty print("ERROR: ", sys.exc_info()[1]) 8237750ad47SMarcel Moolenaar raise 8247750ad47SMarcel Moolenaar 825