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""" 39f974ced3SSimon J. GerratySPDX-License-Identifier: BSD-2-Clause 40f974ced3SSimon J. Gerraty 417750ad47SMarcel MoolenaarRCSid: 42*c8245cebSSimon J. Gerraty $Id: meta2deps.py,v 1.50 2024/09/27 00:08:36 sjg Exp $ 437750ad47SMarcel Moolenaar 44960b77beSSimon J. Gerraty Copyright (c) 2011-2020, Simon J. Gerraty 45960b77beSSimon J. Gerraty Copyright (c) 2011-2017, Juniper Networks, Inc. 464ed4429cSSimon J. Gerraty All rights reserved. 477750ad47SMarcel Moolenaar 487750ad47SMarcel Moolenaar Redistribution and use in source and binary forms, with or without 497750ad47SMarcel Moolenaar modification, are permitted provided that the following conditions 507750ad47SMarcel Moolenaar are met: 517750ad47SMarcel Moolenaar 1. Redistributions of source code must retain the above copyright 527750ad47SMarcel Moolenaar notice, this list of conditions and the following disclaimer. 537750ad47SMarcel Moolenaar 2. Redistributions in binary form must reproduce the above copyright 547750ad47SMarcel Moolenaar notice, this list of conditions and the following disclaimer in the 557750ad47SMarcel Moolenaar documentation and/or other materials provided with the distribution. 567750ad47SMarcel Moolenaar 577750ad47SMarcel Moolenaar THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 587750ad47SMarcel Moolenaar "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 597750ad47SMarcel Moolenaar LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 607750ad47SMarcel Moolenaar A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 617750ad47SMarcel Moolenaar OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 627750ad47SMarcel Moolenaar SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 637750ad47SMarcel Moolenaar LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 647750ad47SMarcel Moolenaar DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 657750ad47SMarcel Moolenaar THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 667750ad47SMarcel Moolenaar (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 677750ad47SMarcel Moolenaar OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 687750ad47SMarcel Moolenaar 697750ad47SMarcel Moolenaar""" 707750ad47SMarcel Moolenaar 71bf7aa99aSSimon J. Gerratyimport os 72bf7aa99aSSimon J. Gerratyimport re 73bf7aa99aSSimon J. Gerratyimport sys 74bf7aa99aSSimon J. Gerratyimport stat 757750ad47SMarcel Moolenaar 767750ad47SMarcel Moolenaardef resolve(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr): 777750ad47SMarcel Moolenaar """ 787750ad47SMarcel Moolenaar Return an absolute path, resolving via cwd or last_dir if needed. 79f974ced3SSimon J. Gerraty 80f974ced3SSimon J. Gerraty Cleanup any leading ``./`` and trailing ``/.`` 817750ad47SMarcel Moolenaar """ 82f974ced3SSimon J. Gerraty while path.endswith('/.'): 837750ad47SMarcel Moolenaar path = path[0:-2] 84d5ddb276SSimon J. Gerraty if len(path) > 0 and path[0] == '/': 85960b77beSSimon J. Gerraty if os.path.exists(path): 867750ad47SMarcel Moolenaar return path 87960b77beSSimon J. Gerraty if debug > 2: 88960b77beSSimon J. Gerraty print("skipping non-existent:", path, file=debug_out) 89960b77beSSimon J. Gerraty return None 907750ad47SMarcel Moolenaar if path == '.': 917750ad47SMarcel Moolenaar return cwd 927750ad47SMarcel Moolenaar if path.startswith('./'): 93f974ced3SSimon J. Gerraty while path.startswith('./'): 94f974ced3SSimon J. Gerraty path = path[1:] 95f974ced3SSimon J. Gerraty return cwd + path 967750ad47SMarcel Moolenaar if last_dir == cwd: 977750ad47SMarcel Moolenaar last_dir = None 987750ad47SMarcel Moolenaar for d in [last_dir, cwd]: 997750ad47SMarcel Moolenaar if not d: 1007750ad47SMarcel Moolenaar continue 101a6589ab7SSimon J. Gerraty if path == '..': 102a6589ab7SSimon J. Gerraty dw = d.split('/') 103a6589ab7SSimon J. Gerraty p = '/'.join(dw[:-1]) 104a6589ab7SSimon J. Gerraty if not p: 105a6589ab7SSimon J. Gerraty p = '/' 106a6589ab7SSimon J. Gerraty return p 1077750ad47SMarcel Moolenaar p = '/'.join([d,path]) 1087750ad47SMarcel Moolenaar if debug > 2: 10910ea6facSSimon J. Gerraty print("looking for:", p, end=' ', file=debug_out) 1107750ad47SMarcel Moolenaar if not os.path.exists(p): 1117750ad47SMarcel Moolenaar if debug > 2: 11210ea6facSSimon J. Gerraty print("nope", file=debug_out) 1137750ad47SMarcel Moolenaar p = None 1147750ad47SMarcel Moolenaar continue 1157750ad47SMarcel Moolenaar if debug > 2: 11610ea6facSSimon J. Gerraty print("found:", p, file=debug_out) 1177750ad47SMarcel Moolenaar return p 1187750ad47SMarcel Moolenaar return None 1197750ad47SMarcel Moolenaar 1206d4f05fdSSimon J. Gerratydef cleanpath(path): 1216d4f05fdSSimon J. Gerraty """cleanup path without using realpath(3)""" 1226d4f05fdSSimon J. Gerraty if path.startswith('/'): 1236d4f05fdSSimon J. Gerraty r = '/' 1246d4f05fdSSimon J. Gerraty else: 1256d4f05fdSSimon J. Gerraty r = '' 1266d4f05fdSSimon J. Gerraty p = [] 1276d4f05fdSSimon J. Gerraty w = path.split('/') 1286d4f05fdSSimon J. Gerraty for d in w: 1296d4f05fdSSimon J. Gerraty if not d or d == '.': 1306d4f05fdSSimon J. Gerraty continue 1316d4f05fdSSimon J. Gerraty if d == '..': 132a6589ab7SSimon J. Gerraty try: 1336d4f05fdSSimon J. Gerraty p.pop() 1346d4f05fdSSimon J. Gerraty continue 135a6589ab7SSimon J. Gerraty except: 136a6589ab7SSimon J. Gerraty break 1376d4f05fdSSimon J. Gerraty p.append(d) 1386d4f05fdSSimon J. Gerraty 1396d4f05fdSSimon J. Gerraty return r + '/'.join(p) 1406d4f05fdSSimon J. Gerraty 1417750ad47SMarcel Moolenaardef abspath(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr): 1427750ad47SMarcel Moolenaar """ 1437750ad47SMarcel Moolenaar Return an absolute path, resolving via cwd or last_dir if needed. 1446d4f05fdSSimon J. Gerraty this gets called a lot, so we try to avoid calling realpath. 1457750ad47SMarcel Moolenaar """ 146d5ddb276SSimon J. Gerraty rpath = resolve(path, cwd, last_dir, debug, debug_out) 147d5ddb276SSimon J. Gerraty if rpath: 148d5ddb276SSimon J. Gerraty path = rpath 149960b77beSSimon J. Gerraty elif len(path) > 0 and path[0] == '/': 150960b77beSSimon J. Gerraty return None 151ccfb9654SSimon J. Gerraty if (path.find('/') < 0 or 152ccfb9654SSimon J. Gerraty path.find('./') > 0 or 153f974ced3SSimon J. Gerraty path.find('/../') > 0 or 1546d4f05fdSSimon J. Gerraty path.endswith('/..')): 1556d4f05fdSSimon J. Gerraty path = cleanpath(path) 1567750ad47SMarcel Moolenaar return path 1577750ad47SMarcel Moolenaar 1587750ad47SMarcel Moolenaardef sort_unique(list, cmp=None, key=None, reverse=False): 1593b26e5a4SSimon J. Gerraty if sys.version_info[0] == 2: 1607750ad47SMarcel Moolenaar list.sort(cmp, key, reverse) 1613b26e5a4SSimon J. Gerraty else: 1623b26e5a4SSimon J. Gerraty list.sort(reverse=reverse) 1637750ad47SMarcel Moolenaar nl = [] 1647750ad47SMarcel Moolenaar le = None 1657750ad47SMarcel Moolenaar for e in list: 1667750ad47SMarcel Moolenaar if e == le: 1677750ad47SMarcel Moolenaar continue 1686d4f05fdSSimon J. Gerraty le = e 1697750ad47SMarcel Moolenaar nl.append(e) 1707750ad47SMarcel Moolenaar return nl 1717750ad47SMarcel Moolenaar 172bf062775SSimon J. Gerratydef add_trims(x): 173bf062775SSimon J. Gerraty return ['/' + x + '/', 174bf062775SSimon J. Gerraty '/' + x, 175bf062775SSimon J. Gerraty x + '/', 176bf062775SSimon J. Gerraty x] 177bf062775SSimon J. Gerraty 1783b26e5a4SSimon J. Gerratydef target_spec_exts(target_spec): 1793b26e5a4SSimon J. Gerraty """return a list of dirdep extensions that could match target_spec""" 1803b26e5a4SSimon J. Gerraty 1813b26e5a4SSimon J. Gerraty if target_spec.find(',') < 0: 1823b26e5a4SSimon J. Gerraty return ['.'+target_spec] 1833b26e5a4SSimon J. Gerraty w = target_spec.split(',') 1843b26e5a4SSimon J. Gerraty n = len(w) 1853b26e5a4SSimon J. Gerraty e = [] 1863b26e5a4SSimon J. Gerraty while n > 0: 1873b26e5a4SSimon J. Gerraty e.append('.'+','.join(w[0:n])) 1883b26e5a4SSimon J. Gerraty n -= 1 1893b26e5a4SSimon J. Gerraty return e 1903b26e5a4SSimon J. Gerraty 1917750ad47SMarcel Moolenaarclass MetaFile: 1927750ad47SMarcel Moolenaar """class to parse meta files generated by bmake.""" 1937750ad47SMarcel Moolenaar 1947750ad47SMarcel Moolenaar conf = None 1957750ad47SMarcel Moolenaar dirdep_re = None 1967750ad47SMarcel Moolenaar host_target = None 1977750ad47SMarcel Moolenaar srctops = [] 1987750ad47SMarcel Moolenaar objroots = [] 199ccfb9654SSimon J. Gerraty excludes = [] 2007750ad47SMarcel Moolenaar seen = {} 2017750ad47SMarcel Moolenaar obj_deps = [] 2027750ad47SMarcel Moolenaar src_deps = [] 2037750ad47SMarcel Moolenaar file_deps = [] 2047750ad47SMarcel Moolenaar 2057750ad47SMarcel Moolenaar def __init__(self, name, conf={}): 2067750ad47SMarcel Moolenaar """if name is set we will parse it now. 207f974ced3SSimon J. Gerraty conf can have the follwing keys: 2087750ad47SMarcel Moolenaar 2097750ad47SMarcel Moolenaar SRCTOPS list of tops of the src tree(s). 2107750ad47SMarcel Moolenaar 2117750ad47SMarcel Moolenaar CURDIR the src directory 'bmake' was run from. 2127750ad47SMarcel Moolenaar 2137750ad47SMarcel Moolenaar RELDIR the relative path from SRCTOP to CURDIR 2147750ad47SMarcel Moolenaar 2157750ad47SMarcel Moolenaar MACHINE the machine we built for. 2167750ad47SMarcel Moolenaar set to 'none' if we are not cross-building. 21751048477SSimon J. Gerraty More specifically if machine cannot be deduced from objdirs. 2187750ad47SMarcel Moolenaar 219bf062775SSimon J. Gerraty TARGET_SPEC 220bf062775SSimon J. Gerraty Sometimes MACHINE isn't enough. 221bf062775SSimon J. Gerraty 2227750ad47SMarcel Moolenaar HOST_TARGET 223ccfb9654SSimon J. Gerraty when we build for the pseudo machine 'host' 2247750ad47SMarcel Moolenaar the object tree uses HOST_TARGET rather than MACHINE. 2257750ad47SMarcel Moolenaar 2267750ad47SMarcel Moolenaar OBJROOTS a list of the common prefix for all obj dirs it might 2277750ad47SMarcel Moolenaar end in '/' or '-'. 2287750ad47SMarcel Moolenaar 2297750ad47SMarcel Moolenaar DPDEPS names an optional file to which per file dependencies 2307750ad47SMarcel Moolenaar will be appended. 2317750ad47SMarcel Moolenaar For example if 'some/path/foo.h' is read from SRCTOP 2327750ad47SMarcel Moolenaar then 'DPDEPS_some/path/foo.h +=' "RELDIR" is output. 2337750ad47SMarcel Moolenaar This can allow 'bmake' to learn all the dirs within 2347750ad47SMarcel Moolenaar the tree that depend on 'foo.h' 2357750ad47SMarcel Moolenaar 236ccfb9654SSimon J. Gerraty EXCLUDES 237ccfb9654SSimon J. Gerraty A list of paths to ignore. 238ccfb9654SSimon J. Gerraty ccache(1) can otherwise be trouble. 239ccfb9654SSimon J. Gerraty 2407750ad47SMarcel Moolenaar debug desired debug level 2417750ad47SMarcel Moolenaar 2427750ad47SMarcel Moolenaar debug_out open file to send debug output to (sys.stderr) 2437750ad47SMarcel Moolenaar 2447750ad47SMarcel Moolenaar """ 2457750ad47SMarcel Moolenaar 2467750ad47SMarcel Moolenaar self.name = name 2473b26e5a4SSimon J. Gerraty self.debug = conf.get('debug', 0) 2483b26e5a4SSimon J. Gerraty self.debug_out = conf.get('debug_out', sys.stderr) 2497750ad47SMarcel Moolenaar 2503b26e5a4SSimon J. Gerraty self.machine = conf.get('MACHINE', '') 2513b26e5a4SSimon J. Gerraty self.machine_arch = conf.get('MACHINE_ARCH', '') 2523b26e5a4SSimon J. Gerraty self.target_spec = conf.get('TARGET_SPEC', self.machine) 2533b26e5a4SSimon J. Gerraty self.exts = target_spec_exts(self.target_spec) 2543b26e5a4SSimon J. Gerraty self.curdir = conf.get('CURDIR') 2553b26e5a4SSimon J. Gerraty self.reldir = conf.get('RELDIR') 2563b26e5a4SSimon J. Gerraty self.dpdeps = conf.get('DPDEPS') 257bf7aa99aSSimon J. Gerraty self.pids = {} 258d5ddb276SSimon J. Gerraty self.line = 0 2594ed4429cSSimon J. Gerraty 2607750ad47SMarcel Moolenaar if not self.conf: 2617750ad47SMarcel Moolenaar # some of the steps below we want to do only once 2627750ad47SMarcel Moolenaar self.conf = conf 2633b26e5a4SSimon J. Gerraty self.host_target = conf.get('HOST_TARGET') 2643b26e5a4SSimon J. Gerraty for srctop in conf.get('SRCTOPS', []): 2657750ad47SMarcel Moolenaar if srctop[-1] != '/': 2667750ad47SMarcel Moolenaar srctop += '/' 2677750ad47SMarcel Moolenaar if not srctop in self.srctops: 2687750ad47SMarcel Moolenaar self.srctops.append(srctop) 269fbc1b149SSimon J. Gerraty _srctop = os.path.realpath(srctop) 270fbc1b149SSimon J. Gerraty if _srctop[-1] != '/': 271fbc1b149SSimon J. Gerraty _srctop += '/' 272fbc1b149SSimon J. Gerraty if not _srctop in self.srctops: 273fbc1b149SSimon J. Gerraty self.srctops.append(_srctop) 2747750ad47SMarcel Moolenaar 275bf062775SSimon J. Gerraty trim_list = add_trims(self.machine) 2768c95c434SSimon J. Gerraty if self.machine == 'host': 277bf062775SSimon J. Gerraty trim_list += add_trims(self.host_target) 2783b26e5a4SSimon J. Gerraty if self.target_spec != self.machine: 279bf062775SSimon J. Gerraty trim_list += add_trims(self.target_spec) 280876336c8SSimon J. Gerraty 2813b26e5a4SSimon J. Gerraty for objroot in conf.get('OBJROOTS', []): 2828c95c434SSimon J. Gerraty for e in trim_list: 2834ed4429cSSimon J. Gerraty if objroot.endswith(e): 2844ed4429cSSimon J. Gerraty # this is not what we want - fix it 2854ed4429cSSimon J. Gerraty objroot = objroot[0:-len(e)] 286b47b9f6bSSimon J. Gerraty 287b47b9f6bSSimon J. Gerraty if objroot[-1] != '/': 2884ed4429cSSimon J. Gerraty objroot += '/' 2897750ad47SMarcel Moolenaar if not objroot in self.objroots: 2907750ad47SMarcel Moolenaar self.objroots.append(objroot) 2917750ad47SMarcel Moolenaar _objroot = os.path.realpath(objroot) 2927750ad47SMarcel Moolenaar if objroot[-1] == '/': 2937750ad47SMarcel Moolenaar _objroot += '/' 2947750ad47SMarcel Moolenaar if not _objroot in self.objroots: 2957750ad47SMarcel Moolenaar self.objroots.append(_objroot) 2967750ad47SMarcel Moolenaar 297*c8245cebSSimon J. Gerraty self.sb = conf.get('SB', '') 2984ed4429cSSimon J. Gerraty # we want the longest match 2994ed4429cSSimon J. Gerraty self.srctops.sort(reverse=True) 3004ed4429cSSimon J. Gerraty self.objroots.sort(reverse=True) 3014ed4429cSSimon J. Gerraty 3023b26e5a4SSimon J. Gerraty self.excludes = conf.get('EXCLUDES', []) 303ccfb9654SSimon J. Gerraty 3047750ad47SMarcel Moolenaar if self.debug: 30510ea6facSSimon J. Gerraty print("host_target=", self.host_target, file=self.debug_out) 30610ea6facSSimon J. Gerraty print("srctops=", self.srctops, file=self.debug_out) 30710ea6facSSimon J. Gerraty print("objroots=", self.objroots, file=self.debug_out) 308ccfb9654SSimon J. Gerraty print("excludes=", self.excludes, file=self.debug_out) 3093b26e5a4SSimon J. Gerraty print("ext_list=", self.exts, file=self.debug_out) 3107750ad47SMarcel Moolenaar 3117750ad47SMarcel Moolenaar self.dirdep_re = re.compile(r'([^/]+)/(.+)') 3127750ad47SMarcel Moolenaar 3137750ad47SMarcel Moolenaar if self.dpdeps and not self.reldir: 3147750ad47SMarcel Moolenaar if self.debug: 31510ea6facSSimon J. Gerraty print("need reldir:", end=' ', file=self.debug_out) 3167750ad47SMarcel Moolenaar if self.curdir: 3177750ad47SMarcel Moolenaar srctop = self.find_top(self.curdir, self.srctops) 3187750ad47SMarcel Moolenaar if srctop: 3197750ad47SMarcel Moolenaar self.reldir = self.curdir.replace(srctop,'') 3207750ad47SMarcel Moolenaar if self.debug: 32110ea6facSSimon J. Gerraty print(self.reldir, file=self.debug_out) 3227750ad47SMarcel Moolenaar if not self.reldir: 3237750ad47SMarcel Moolenaar self.dpdeps = None # we cannot do it? 3247750ad47SMarcel Moolenaar 325876336c8SSimon J. Gerraty self.cwd = os.getcwd() # make sure this is initialized 326ccfb9654SSimon J. Gerraty self.last_dir = self.cwd 327876336c8SSimon J. Gerraty 3287750ad47SMarcel Moolenaar if name: 329d5ddb276SSimon J. Gerraty self.try_parse() 3307750ad47SMarcel Moolenaar 3317750ad47SMarcel Moolenaar def reset(self): 3327750ad47SMarcel Moolenaar """reset state if we are being passed meta files from multiple directories.""" 3337750ad47SMarcel Moolenaar self.seen = {} 3347750ad47SMarcel Moolenaar self.obj_deps = [] 3357750ad47SMarcel Moolenaar self.src_deps = [] 3367750ad47SMarcel Moolenaar self.file_deps = [] 3377750ad47SMarcel Moolenaar 3387750ad47SMarcel Moolenaar def dirdeps(self, sep='\n'): 3397750ad47SMarcel Moolenaar """return DIRDEPS""" 3407750ad47SMarcel Moolenaar return sep.strip() + sep.join(self.obj_deps) 3417750ad47SMarcel Moolenaar 3427750ad47SMarcel Moolenaar def src_dirdeps(self, sep='\n'): 3437750ad47SMarcel Moolenaar """return SRC_DIRDEPS""" 3447750ad47SMarcel Moolenaar return sep.strip() + sep.join(self.src_deps) 3457750ad47SMarcel Moolenaar 3467750ad47SMarcel Moolenaar def file_depends(self, out=None): 3477750ad47SMarcel Moolenaar """Append DPDEPS_${file} += ${RELDIR} 3487750ad47SMarcel Moolenaar for each file we saw, to the output file.""" 3497750ad47SMarcel Moolenaar if not self.reldir: 3507750ad47SMarcel Moolenaar return None 3517750ad47SMarcel Moolenaar for f in sort_unique(self.file_deps): 35210ea6facSSimon J. Gerraty print('DPDEPS_%s += %s' % (f, self.reldir), file=out) 353b47b9f6bSSimon J. Gerraty # these entries provide for reverse DIRDEPS lookup 354b47b9f6bSSimon J. Gerraty for f in self.obj_deps: 355b47b9f6bSSimon J. Gerraty print('DEPDIRS_%s += %s' % (f, self.reldir), file=out) 3567750ad47SMarcel Moolenaar 3577750ad47SMarcel Moolenaar def seenit(self, dir): 3587750ad47SMarcel Moolenaar """rememer that we have seen dir.""" 3597750ad47SMarcel Moolenaar self.seen[dir] = 1 3607750ad47SMarcel Moolenaar 3617750ad47SMarcel Moolenaar def add(self, list, data, clue=''): 3627750ad47SMarcel Moolenaar """add data to list if it isn't already there.""" 3637750ad47SMarcel Moolenaar if data not in list: 3647750ad47SMarcel Moolenaar list.append(data) 3657750ad47SMarcel Moolenaar if self.debug: 36610ea6facSSimon J. Gerraty print("%s: %sAdd: %s" % (self.name, clue, data), file=self.debug_out) 3677750ad47SMarcel Moolenaar 3687750ad47SMarcel Moolenaar def find_top(self, path, list): 369ccfb9654SSimon J. Gerraty """the logical tree may be split across multiple trees""" 3707750ad47SMarcel Moolenaar for top in list: 3717750ad47SMarcel Moolenaar if path.startswith(top): 3727750ad47SMarcel Moolenaar if self.debug > 2: 37310ea6facSSimon J. Gerraty print("found in", top, file=self.debug_out) 3747750ad47SMarcel Moolenaar return top 3757750ad47SMarcel Moolenaar return None 3767750ad47SMarcel Moolenaar 3777750ad47SMarcel Moolenaar def find_obj(self, objroot, dir, path, input): 3787750ad47SMarcel Moolenaar """return path within objroot, taking care of .dirdep files""" 3797750ad47SMarcel Moolenaar ddep = None 3807750ad47SMarcel Moolenaar for ddepf in [path + '.dirdep', dir + '/.dirdep']: 3817750ad47SMarcel Moolenaar if not ddep and os.path.exists(ddepf): 38210ea6facSSimon J. Gerraty ddep = open(ddepf, 'r').readline().strip('# \n') 3837750ad47SMarcel Moolenaar if self.debug > 1: 38410ea6facSSimon J. Gerraty print("found %s: %s\n" % (ddepf, ddep), file=self.debug_out) 3853b26e5a4SSimon J. Gerraty for e in self.exts: 3863b26e5a4SSimon J. Gerraty if ddep.endswith(e): 3873b26e5a4SSimon J. Gerraty ddep = ddep[0:-len(e)] 3883b26e5a4SSimon J. Gerraty break 3897750ad47SMarcel Moolenaar 3907750ad47SMarcel Moolenaar if not ddep: 3917750ad47SMarcel Moolenaar # no .dirdeps, so remember that we've seen the raw input 3927750ad47SMarcel Moolenaar self.seenit(input) 3937750ad47SMarcel Moolenaar self.seenit(dir) 3947750ad47SMarcel Moolenaar if self.machine == 'none': 3957750ad47SMarcel Moolenaar if dir.startswith(objroot): 3967750ad47SMarcel Moolenaar return dir.replace(objroot,'') 3977750ad47SMarcel Moolenaar return None 3987750ad47SMarcel Moolenaar m = self.dirdep_re.match(dir.replace(objroot,'')) 3997750ad47SMarcel Moolenaar if m: 4007750ad47SMarcel Moolenaar ddep = m.group(2) 4017750ad47SMarcel Moolenaar dmachine = m.group(1) 4027750ad47SMarcel Moolenaar if dmachine != self.machine: 4037750ad47SMarcel Moolenaar if not (self.machine == 'host' and 4047750ad47SMarcel Moolenaar dmachine == self.host_target): 4057750ad47SMarcel Moolenaar if self.debug > 2: 40610ea6facSSimon J. Gerraty print("adding .%s to %s" % (dmachine, ddep), file=self.debug_out) 4077750ad47SMarcel Moolenaar ddep += '.' + dmachine 4087750ad47SMarcel Moolenaar 4097750ad47SMarcel Moolenaar return ddep 4107750ad47SMarcel Moolenaar 411d5ddb276SSimon J. Gerraty def try_parse(self, name=None, file=None): 412d5ddb276SSimon J. Gerraty """give file and line number causing exception""" 413d5ddb276SSimon J. Gerraty try: 414d5ddb276SSimon J. Gerraty self.parse(name, file) 415d5ddb276SSimon J. Gerraty except: 416d5ddb276SSimon J. Gerraty # give a useful clue 41710ea6facSSimon J. Gerraty print('{}:{}: '.format(self.name, self.line), end=' ', file=sys.stderr) 418d5ddb276SSimon J. Gerraty raise 419d5ddb276SSimon J. Gerraty 4207750ad47SMarcel Moolenaar def parse(self, name=None, file=None): 4217750ad47SMarcel Moolenaar """A meta file looks like: 4227750ad47SMarcel Moolenaar 4237750ad47SMarcel Moolenaar # Meta data file "path" 4247750ad47SMarcel Moolenaar CMD "command-line" 4257750ad47SMarcel Moolenaar CWD "cwd" 4267750ad47SMarcel Moolenaar TARGET "target" 4277750ad47SMarcel Moolenaar -- command output -- 4287750ad47SMarcel Moolenaar -- filemon acquired metadata -- 4297750ad47SMarcel Moolenaar # buildmon version 3 4307750ad47SMarcel Moolenaar V 3 4317750ad47SMarcel Moolenaar C "pid" "cwd" 4327750ad47SMarcel Moolenaar E "pid" "path" 4337750ad47SMarcel Moolenaar F "pid" "child" 4347750ad47SMarcel Moolenaar R "pid" "path" 4357750ad47SMarcel Moolenaar W "pid" "path" 4367750ad47SMarcel Moolenaar X "pid" "status" 4377750ad47SMarcel Moolenaar D "pid" "path" 4387750ad47SMarcel Moolenaar L "pid" "src" "target" 4397750ad47SMarcel Moolenaar M "pid" "old" "new" 4407750ad47SMarcel Moolenaar S "pid" "path" 4417750ad47SMarcel Moolenaar # Bye bye 4427750ad47SMarcel Moolenaar 4437750ad47SMarcel Moolenaar We go to some effort to avoid processing a dependency more than once. 4447750ad47SMarcel Moolenaar Of the above record types only C,E,F,L,R,V and W are of interest. 4457750ad47SMarcel Moolenaar """ 4467750ad47SMarcel Moolenaar 4477750ad47SMarcel Moolenaar version = 0 # unknown 4487750ad47SMarcel Moolenaar if name: 4497750ad47SMarcel Moolenaar self.name = name; 4507750ad47SMarcel Moolenaar if file: 4517750ad47SMarcel Moolenaar f = file 452ccfb9654SSimon J. Gerraty cwd = self.last_dir = self.cwd 4537750ad47SMarcel Moolenaar else: 45410ea6facSSimon J. Gerraty f = open(self.name, 'r') 4557750ad47SMarcel Moolenaar skip = True 4567750ad47SMarcel Moolenaar pid_cwd = {} 4577750ad47SMarcel Moolenaar pid_last_dir = {} 4587750ad47SMarcel Moolenaar last_pid = 0 459bf7aa99aSSimon J. Gerraty eof_token = False 4607750ad47SMarcel Moolenaar 461d5ddb276SSimon J. Gerraty self.line = 0 4627750ad47SMarcel Moolenaar if self.curdir: 4637750ad47SMarcel Moolenaar self.seenit(self.curdir) # we ignore this 4647750ad47SMarcel Moolenaar 465*c8245cebSSimon J. Gerraty if self.sb and self.name.startswith(self.sb): 466*c8245cebSSimon J. Gerraty error_name = self.name.replace(self.sb+'/','') 467*c8245cebSSimon J. Gerraty else: 468*c8245cebSSimon J. Gerraty error_name = self.name 469bf7aa99aSSimon J. Gerraty interesting = '#CEFLRVX' 4707750ad47SMarcel Moolenaar for line in f: 471d5ddb276SSimon J. Gerraty self.line += 1 4727750ad47SMarcel Moolenaar # ignore anything we don't care about 4737750ad47SMarcel Moolenaar if not line[0] in interesting: 4747750ad47SMarcel Moolenaar continue 4757750ad47SMarcel Moolenaar if self.debug > 2: 47610ea6facSSimon J. Gerraty print("input:", line, end=' ', file=self.debug_out) 4777750ad47SMarcel Moolenaar w = line.split() 4787750ad47SMarcel Moolenaar 4797750ad47SMarcel Moolenaar if skip: 4807750ad47SMarcel Moolenaar if w[0] == 'V': 4817750ad47SMarcel Moolenaar skip = False 4827750ad47SMarcel Moolenaar version = int(w[1]) 4837750ad47SMarcel Moolenaar """ 4847750ad47SMarcel Moolenaar if version < 4: 4857750ad47SMarcel Moolenaar # we cannot ignore 'W' records 4867750ad47SMarcel Moolenaar # as they may be 'rw' 4877750ad47SMarcel Moolenaar interesting += 'W' 4887750ad47SMarcel Moolenaar """ 4897750ad47SMarcel Moolenaar elif w[0] == 'CWD': 490ccfb9654SSimon J. Gerraty self.cwd = cwd = self.last_dir = w[1] 4917750ad47SMarcel Moolenaar self.seenit(cwd) # ignore this 4927750ad47SMarcel Moolenaar if self.debug: 49310ea6facSSimon J. Gerraty print("%s: CWD=%s" % (self.name, cwd), file=self.debug_out) 4947750ad47SMarcel Moolenaar continue 4957750ad47SMarcel Moolenaar 496bf7aa99aSSimon J. Gerraty if w[0] == '#': 497bf7aa99aSSimon J. Gerraty # check the file has not been truncated 498bf7aa99aSSimon J. Gerraty if line.find('Bye') > 0: 499bf7aa99aSSimon J. Gerraty eof_token = True 500bf7aa99aSSimon J. Gerraty continue 501bf7aa99aSSimon J. Gerraty 5027750ad47SMarcel Moolenaar pid = int(w[1]) 5037750ad47SMarcel Moolenaar if pid != last_pid: 5047750ad47SMarcel Moolenaar if last_pid: 505ccfb9654SSimon J. Gerraty pid_last_dir[last_pid] = self.last_dir 5063b26e5a4SSimon J. Gerraty cwd = pid_cwd.get(pid, self.cwd) 5073b26e5a4SSimon J. Gerraty self.last_dir = pid_last_dir.get(pid, self.cwd) 5087750ad47SMarcel Moolenaar last_pid = pid 5097750ad47SMarcel Moolenaar 5107750ad47SMarcel Moolenaar # process operations 5117750ad47SMarcel Moolenaar if w[0] == 'F': 5127750ad47SMarcel Moolenaar npid = int(w[2]) 5137750ad47SMarcel Moolenaar pid_cwd[npid] = cwd 5147750ad47SMarcel Moolenaar pid_last_dir[npid] = cwd 5157750ad47SMarcel Moolenaar last_pid = npid 5167750ad47SMarcel Moolenaar continue 5177750ad47SMarcel Moolenaar elif w[0] == 'C': 5187750ad47SMarcel Moolenaar cwd = abspath(w[2], cwd, None, self.debug, self.debug_out) 519960b77beSSimon J. Gerraty if not cwd: 520960b77beSSimon J. Gerraty cwd = w[2] 521960b77beSSimon J. Gerraty if self.debug > 1: 522960b77beSSimon J. Gerraty print("missing cwd=", cwd, file=self.debug_out) 5237750ad47SMarcel Moolenaar if cwd.endswith('/.'): 5247750ad47SMarcel Moolenaar cwd = cwd[0:-2] 525b47b9f6bSSimon J. Gerraty self.last_dir = pid_last_dir[pid] = cwd 526b47b9f6bSSimon J. Gerraty pid_cwd[pid] = cwd 5277750ad47SMarcel Moolenaar if self.debug > 1: 52810ea6facSSimon J. Gerraty print("cwd=", cwd, file=self.debug_out) 5297750ad47SMarcel Moolenaar continue 5307750ad47SMarcel Moolenaar 531bf7aa99aSSimon J. Gerraty if w[0] == 'X': 532bf7aa99aSSimon J. Gerraty try: 533bf7aa99aSSimon J. Gerraty del self.pids[pid] 534bf7aa99aSSimon J. Gerraty except KeyError: 535bf7aa99aSSimon J. Gerraty pass 536bf7aa99aSSimon J. Gerraty continue 537bf7aa99aSSimon J. Gerraty 5387750ad47SMarcel Moolenaar if w[2] in self.seen: 5397750ad47SMarcel Moolenaar if self.debug > 2: 54010ea6facSSimon J. Gerraty print("seen:", w[2], file=self.debug_out) 5417750ad47SMarcel Moolenaar continue 5427750ad47SMarcel Moolenaar # file operations 5437750ad47SMarcel Moolenaar if w[0] in 'ML': 544ccfb9654SSimon J. Gerraty # these are special, tread src as read and 545ccfb9654SSimon J. Gerraty # target as write 546960b77beSSimon J. Gerraty self.parse_path(w[2].strip("'"), cwd, 'R', w) 547960b77beSSimon J. Gerraty self.parse_path(w[3].strip("'"), cwd, 'W', w) 548ccfb9654SSimon J. Gerraty continue 549ccfb9654SSimon J. Gerraty elif w[0] in 'ERWS': 5507750ad47SMarcel Moolenaar path = w[2] 551bf7aa99aSSimon J. Gerraty if w[0] == 'E': 552bf7aa99aSSimon J. Gerraty self.pids[pid] = path 553bf7aa99aSSimon J. Gerraty elif path == '.': 554960b77beSSimon J. Gerraty continue 555ccfb9654SSimon J. Gerraty self.parse_path(path, cwd, w[0], w) 556ccfb9654SSimon J. Gerraty 557bf7aa99aSSimon J. Gerraty if version == 0: 558*c8245cebSSimon J. Gerraty raise AssertionError('missing filemon data: {}'.format(error_name)) 559bf7aa99aSSimon J. Gerraty if not eof_token: 560*c8245cebSSimon J. Gerraty raise AssertionError('truncated filemon data: {}'.format(error_name)) 561bf7aa99aSSimon J. Gerraty 562bf7aa99aSSimon J. Gerraty setid_pids = [] 563bf7aa99aSSimon J. Gerraty # self.pids should be empty! 564bf7aa99aSSimon J. Gerraty for pid,path in self.pids.items(): 565bf7aa99aSSimon J. Gerraty try: 566bf7aa99aSSimon J. Gerraty # no guarantee that path is still valid 567bf7aa99aSSimon J. Gerraty if os.stat(path).st_mode & (stat.S_ISUID|stat.S_ISGID): 568bf7aa99aSSimon J. Gerraty # we do not expect anything after Exec 569bf7aa99aSSimon J. Gerraty setid_pids.append(pid) 570bf7aa99aSSimon J. Gerraty continue 571bf7aa99aSSimon J. Gerraty except: 572bf7aa99aSSimon J. Gerraty # we do not care why the above fails, 573bf7aa99aSSimon J. Gerraty # we do not want to miss the ERROR below. 574bf7aa99aSSimon J. Gerraty pass 575bf7aa99aSSimon J. Gerraty print("ERROR: missing eXit for {} pid {}".format(path, pid)) 576bf7aa99aSSimon J. Gerraty for pid in setid_pids: 577bf7aa99aSSimon J. Gerraty del self.pids[pid] 578*c8245cebSSimon J. Gerraty if len(self.pids) > 0: 579*c8245cebSSimon J. Gerraty raise AssertionError('bad filemon data - missing eXits: {}'.format(error_name)) 580ccfb9654SSimon J. Gerraty if not file: 581ccfb9654SSimon J. Gerraty f.close() 582ccfb9654SSimon J. Gerraty 583c0339e7dSSimon J. Gerraty def is_src(self, base, dir, rdir): 584c0339e7dSSimon J. Gerraty """is base in srctop""" 585c0339e7dSSimon J. Gerraty for dir in [dir,rdir]: 586c0339e7dSSimon J. Gerraty if not dir: 587c0339e7dSSimon J. Gerraty continue 588c0339e7dSSimon J. Gerraty path = '/'.join([dir,base]) 589c0339e7dSSimon J. Gerraty srctop = self.find_top(path, self.srctops) 590c0339e7dSSimon J. Gerraty if srctop: 591c0339e7dSSimon J. Gerraty if self.dpdeps: 592c0339e7dSSimon J. Gerraty self.add(self.file_deps, path.replace(srctop,''), 'file') 593c0339e7dSSimon J. Gerraty self.add(self.src_deps, dir.replace(srctop,''), 'src') 594c0339e7dSSimon J. Gerraty self.seenit(dir) 595c0339e7dSSimon J. Gerraty return True 596c0339e7dSSimon J. Gerraty return False 597c0339e7dSSimon J. Gerraty 598ccfb9654SSimon J. Gerraty def parse_path(self, path, cwd, op=None, w=[]): 599ccfb9654SSimon J. Gerraty """look at a path for the op specified""" 600ccfb9654SSimon J. Gerraty 601ccfb9654SSimon J. Gerraty if not op: 602ccfb9654SSimon J. Gerraty op = w[0] 603ccfb9654SSimon J. Gerraty 604fbc1b149SSimon J. Gerraty # we are never interested in .dirdep files as dependencies 605fbc1b149SSimon J. Gerraty if path.endswith('.dirdep'): 606ccfb9654SSimon J. Gerraty return 607ccfb9654SSimon J. Gerraty for p in self.excludes: 608ccfb9654SSimon J. Gerraty if p and path.startswith(p): 609ccfb9654SSimon J. Gerraty if self.debug > 2: 610e1dfa657SBryan Drewery print("exclude:", p, path, file=self.debug_out) 611ccfb9654SSimon J. Gerraty return 6127750ad47SMarcel Moolenaar # we don't want to resolve the last component if it is 6137750ad47SMarcel Moolenaar # a symlink 614ccfb9654SSimon J. Gerraty path = resolve(path, cwd, self.last_dir, self.debug, self.debug_out) 6157750ad47SMarcel Moolenaar if not path: 616ccfb9654SSimon J. Gerraty return 6177750ad47SMarcel Moolenaar dir,base = os.path.split(path) 6187750ad47SMarcel Moolenaar if dir in self.seen: 6197750ad47SMarcel Moolenaar if self.debug > 2: 62010ea6facSSimon J. Gerraty print("seen:", dir, file=self.debug_out) 621ccfb9654SSimon J. Gerraty return 6227750ad47SMarcel Moolenaar # we can have a path in an objdir which is a link 6237750ad47SMarcel Moolenaar # to the src dir, we may need to add dependencies for each 6247750ad47SMarcel Moolenaar rdir = dir 625ccfb9654SSimon J. Gerraty dir = abspath(dir, cwd, self.last_dir, self.debug, self.debug_out) 6263b26e5a4SSimon J. Gerraty if dir: 6276d4f05fdSSimon J. Gerraty rdir = os.path.realpath(dir) 6283b26e5a4SSimon J. Gerraty else: 6293b26e5a4SSimon J. Gerraty dir = rdir 630c0339e7dSSimon J. Gerraty if rdir == dir: 631c0339e7dSSimon J. Gerraty rdir = None 6327750ad47SMarcel Moolenaar # now put path back together 6337750ad47SMarcel Moolenaar path = '/'.join([dir,base]) 6347750ad47SMarcel Moolenaar if self.debug > 1: 63510ea6facSSimon J. Gerraty print("raw=%s rdir=%s dir=%s path=%s" % (w[2], rdir, dir, path), file=self.debug_out) 636ccfb9654SSimon J. Gerraty if op in 'RWS': 637ccfb9654SSimon J. Gerraty if path in [self.last_dir, cwd, self.cwd, self.curdir]: 6387750ad47SMarcel Moolenaar if self.debug > 1: 63910ea6facSSimon J. Gerraty print("skipping:", path, file=self.debug_out) 640ccfb9654SSimon J. Gerraty return 6417750ad47SMarcel Moolenaar if os.path.isdir(path): 642ccfb9654SSimon J. Gerraty if op in 'RW': 643ccfb9654SSimon J. Gerraty self.last_dir = path; 6447750ad47SMarcel Moolenaar if self.debug > 1: 645ccfb9654SSimon J. Gerraty print("ldir=", self.last_dir, file=self.debug_out) 646ccfb9654SSimon J. Gerraty return 6477750ad47SMarcel Moolenaar 648960b77beSSimon J. Gerraty if op in 'ER': 6497750ad47SMarcel Moolenaar # finally, we get down to it 6507750ad47SMarcel Moolenaar if dir == self.cwd or dir == self.curdir: 651ccfb9654SSimon J. Gerraty return 652c0339e7dSSimon J. Gerraty if self.is_src(base, dir, rdir): 6537750ad47SMarcel Moolenaar self.seenit(w[2]) 654c0339e7dSSimon J. Gerraty if not rdir: 655ccfb9654SSimon J. Gerraty return 6567750ad47SMarcel Moolenaar 6577750ad47SMarcel Moolenaar objroot = None 6587750ad47SMarcel Moolenaar for dir in [dir,rdir]: 6597750ad47SMarcel Moolenaar if not dir: 6607750ad47SMarcel Moolenaar continue 6617750ad47SMarcel Moolenaar objroot = self.find_top(dir, self.objroots) 6627750ad47SMarcel Moolenaar if objroot: 6637750ad47SMarcel Moolenaar break 6647750ad47SMarcel Moolenaar if objroot: 6657750ad47SMarcel Moolenaar ddep = self.find_obj(objroot, dir, path, w[2]) 6667750ad47SMarcel Moolenaar if ddep: 6677750ad47SMarcel Moolenaar self.add(self.obj_deps, ddep, 'obj') 668b47b9f6bSSimon J. Gerraty if self.dpdeps and objroot.endswith('/stage/'): 669b47b9f6bSSimon J. Gerraty sp = '/'.join(path.replace(objroot,'').split('/')[1:]) 670b47b9f6bSSimon J. Gerraty self.add(self.file_deps, sp, 'file') 6717750ad47SMarcel Moolenaar else: 6727750ad47SMarcel Moolenaar # don't waste time looking again 6737750ad47SMarcel Moolenaar self.seenit(w[2]) 6747750ad47SMarcel Moolenaar self.seenit(dir) 6757750ad47SMarcel Moolenaar 6767750ad47SMarcel Moolenaar 6777750ad47SMarcel Moolenaardef main(argv, klass=MetaFile, xopts='', xoptf=None): 6787750ad47SMarcel Moolenaar """Simple driver for class MetaFile. 6797750ad47SMarcel Moolenaar 6807750ad47SMarcel Moolenaar Usage: 6817750ad47SMarcel Moolenaar script [options] [key=value ...] "meta" ... 6827750ad47SMarcel Moolenaar 6837750ad47SMarcel Moolenaar Options and key=value pairs contribute to the 6847750ad47SMarcel Moolenaar dictionary passed to MetaFile. 6857750ad47SMarcel Moolenaar 6867750ad47SMarcel Moolenaar -S "SRCTOP" 6877750ad47SMarcel Moolenaar add "SRCTOP" to the "SRCTOPS" list. 6887750ad47SMarcel Moolenaar 6897750ad47SMarcel Moolenaar -C "CURDIR" 6907750ad47SMarcel Moolenaar 6917750ad47SMarcel Moolenaar -O "OBJROOT" 6927750ad47SMarcel Moolenaar add "OBJROOT" to the "OBJROOTS" list. 6937750ad47SMarcel Moolenaar 6947750ad47SMarcel Moolenaar -m "MACHINE" 6957750ad47SMarcel Moolenaar 696bf062775SSimon J. Gerraty -a "MACHINE_ARCH" 697bf062775SSimon J. Gerraty 6987750ad47SMarcel Moolenaar -H "HOST_TARGET" 6997750ad47SMarcel Moolenaar 7007750ad47SMarcel Moolenaar -D "DPDEPS" 7017750ad47SMarcel Moolenaar 7027750ad47SMarcel Moolenaar -d bumps debug level 7037750ad47SMarcel Moolenaar 7047750ad47SMarcel Moolenaar """ 7057750ad47SMarcel Moolenaar import getopt 7067750ad47SMarcel Moolenaar 7077750ad47SMarcel Moolenaar # import Psyco if we can 7087750ad47SMarcel Moolenaar # it can speed things up quite a bit 7097750ad47SMarcel Moolenaar have_psyco = 0 7107750ad47SMarcel Moolenaar try: 7117750ad47SMarcel Moolenaar import psyco 7127750ad47SMarcel Moolenaar psyco.full() 7137750ad47SMarcel Moolenaar have_psyco = 1 7147750ad47SMarcel Moolenaar except: 7157750ad47SMarcel Moolenaar pass 7167750ad47SMarcel Moolenaar 7177750ad47SMarcel Moolenaar conf = { 7187750ad47SMarcel Moolenaar 'SRCTOPS': [], 7197750ad47SMarcel Moolenaar 'OBJROOTS': [], 720ccfb9654SSimon J. Gerraty 'EXCLUDES': [], 7217750ad47SMarcel Moolenaar } 7227750ad47SMarcel Moolenaar 723*c8245cebSSimon J. Gerraty conf['SB'] = os.getenv('SB', '') 724*c8245cebSSimon J. Gerraty 7257750ad47SMarcel Moolenaar try: 7267750ad47SMarcel Moolenaar machine = os.environ['MACHINE'] 7277750ad47SMarcel Moolenaar if machine: 7287750ad47SMarcel Moolenaar conf['MACHINE'] = machine 729bf062775SSimon J. Gerraty machine_arch = os.environ['MACHINE_ARCH'] 730bf062775SSimon J. Gerraty if machine_arch: 731bf062775SSimon J. Gerraty conf['MACHINE_ARCH'] = machine_arch 7327750ad47SMarcel Moolenaar srctop = os.environ['SB_SRC'] 7337750ad47SMarcel Moolenaar if srctop: 7347750ad47SMarcel Moolenaar conf['SRCTOPS'].append(srctop) 7357750ad47SMarcel Moolenaar objroot = os.environ['SB_OBJROOT'] 7367750ad47SMarcel Moolenaar if objroot: 7377750ad47SMarcel Moolenaar conf['OBJROOTS'].append(objroot) 7387750ad47SMarcel Moolenaar except: 7397750ad47SMarcel Moolenaar pass 7407750ad47SMarcel Moolenaar 7417750ad47SMarcel Moolenaar debug = 0 7427750ad47SMarcel Moolenaar output = True 7437750ad47SMarcel Moolenaar 744ccfb9654SSimon J. Gerraty opts, args = getopt.getopt(argv[1:], 'a:dS:C:O:R:m:D:H:qT:X:' + xopts) 7457750ad47SMarcel Moolenaar for o, a in opts: 746bf062775SSimon J. Gerraty if o == '-a': 747bf062775SSimon J. Gerraty conf['MACHINE_ARCH'] = a 748bf062775SSimon J. Gerraty elif o == '-d': 7497750ad47SMarcel Moolenaar debug += 1 7507750ad47SMarcel Moolenaar elif o == '-q': 7517750ad47SMarcel Moolenaar output = False 7527750ad47SMarcel Moolenaar elif o == '-H': 7537750ad47SMarcel Moolenaar conf['HOST_TARGET'] = a 7547750ad47SMarcel Moolenaar elif o == '-S': 7557750ad47SMarcel Moolenaar if a not in conf['SRCTOPS']: 7567750ad47SMarcel Moolenaar conf['SRCTOPS'].append(a) 7577750ad47SMarcel Moolenaar elif o == '-C': 7587750ad47SMarcel Moolenaar conf['CURDIR'] = a 7597750ad47SMarcel Moolenaar elif o == '-O': 7607750ad47SMarcel Moolenaar if a not in conf['OBJROOTS']: 7617750ad47SMarcel Moolenaar conf['OBJROOTS'].append(a) 7627750ad47SMarcel Moolenaar elif o == '-R': 7637750ad47SMarcel Moolenaar conf['RELDIR'] = a 7647750ad47SMarcel Moolenaar elif o == '-D': 7657750ad47SMarcel Moolenaar conf['DPDEPS'] = a 7667750ad47SMarcel Moolenaar elif o == '-m': 7677750ad47SMarcel Moolenaar conf['MACHINE'] = a 768bf062775SSimon J. Gerraty elif o == '-T': 769bf062775SSimon J. Gerraty conf['TARGET_SPEC'] = a 770ccfb9654SSimon J. Gerraty elif o == '-X': 771ccfb9654SSimon J. Gerraty if a not in conf['EXCLUDES']: 772ccfb9654SSimon J. Gerraty conf['EXCLUDES'].append(a) 7737750ad47SMarcel Moolenaar elif xoptf: 7747750ad47SMarcel Moolenaar xoptf(o, a, conf) 7757750ad47SMarcel Moolenaar 7767750ad47SMarcel Moolenaar conf['debug'] = debug 7777750ad47SMarcel Moolenaar 7787750ad47SMarcel Moolenaar # get any var=val assignments 7797750ad47SMarcel Moolenaar eaten = [] 7807750ad47SMarcel Moolenaar for a in args: 7817750ad47SMarcel Moolenaar if a.find('=') > 0: 7827750ad47SMarcel Moolenaar k,v = a.split('=') 7837750ad47SMarcel Moolenaar if k in ['SRCTOP','OBJROOT','SRCTOPS','OBJROOTS']: 7847750ad47SMarcel Moolenaar if k == 'SRCTOP': 7857750ad47SMarcel Moolenaar k = 'SRCTOPS' 7867750ad47SMarcel Moolenaar elif k == 'OBJROOT': 7877750ad47SMarcel Moolenaar k = 'OBJROOTS' 7887750ad47SMarcel Moolenaar if v not in conf[k]: 7897750ad47SMarcel Moolenaar conf[k].append(v) 7907750ad47SMarcel Moolenaar else: 7917750ad47SMarcel Moolenaar conf[k] = v 7927750ad47SMarcel Moolenaar eaten.append(a) 7937750ad47SMarcel Moolenaar continue 7947750ad47SMarcel Moolenaar break 7957750ad47SMarcel Moolenaar 7967750ad47SMarcel Moolenaar for a in eaten: 7977750ad47SMarcel Moolenaar args.remove(a) 7987750ad47SMarcel Moolenaar 7993b26e5a4SSimon J. Gerraty debug_out = conf.get('debug_out', sys.stderr) 8007750ad47SMarcel Moolenaar 8017750ad47SMarcel Moolenaar if debug: 80210ea6facSSimon J. Gerraty print("config:", file=debug_out) 80310ea6facSSimon J. Gerraty print("psyco=", have_psyco, file=debug_out) 80410ea6facSSimon J. Gerraty for k,v in list(conf.items()): 80510ea6facSSimon J. Gerraty print("%s=%s" % (k,v), file=debug_out) 8067750ad47SMarcel Moolenaar 807ccfb9654SSimon J. Gerraty m = None 8087750ad47SMarcel Moolenaar for a in args: 809d5ddb276SSimon J. Gerraty if a.endswith('.meta'): 810ccfb9654SSimon J. Gerraty if not os.path.exists(a): 811ccfb9654SSimon J. Gerraty continue 8127750ad47SMarcel Moolenaar m = klass(a, conf) 813d5ddb276SSimon J. Gerraty elif a.startswith('@'): 814d5ddb276SSimon J. Gerraty # there can actually multiple files per line 815d5ddb276SSimon J. Gerraty for line in open(a[1:]): 816d5ddb276SSimon J. Gerraty for f in line.strip().split(): 817ccfb9654SSimon J. Gerraty if not os.path.exists(f): 818ccfb9654SSimon J. Gerraty continue 819d5ddb276SSimon J. Gerraty m = klass(f, conf) 8207750ad47SMarcel Moolenaar 821ccfb9654SSimon J. Gerraty if output and m: 82210ea6facSSimon J. Gerraty print(m.dirdeps()) 8237750ad47SMarcel Moolenaar 82410ea6facSSimon J. Gerraty print(m.src_dirdeps('\nsrc:')) 8257750ad47SMarcel Moolenaar 8263b26e5a4SSimon J. Gerraty dpdeps = conf.get('DPDEPS') 8277750ad47SMarcel Moolenaar if dpdeps: 8283b26e5a4SSimon J. Gerraty m.file_depends(open(dpdeps, 'w')) 8297750ad47SMarcel Moolenaar 8307750ad47SMarcel Moolenaar return m 8317750ad47SMarcel Moolenaar 8327750ad47SMarcel Moolenaarif __name__ == '__main__': 8337750ad47SMarcel Moolenaar try: 8347750ad47SMarcel Moolenaar main(sys.argv) 8357750ad47SMarcel Moolenaar except: 8367750ad47SMarcel Moolenaar # yes, this goes to stdout 83710ea6facSSimon J. Gerraty print("ERROR: ", sys.exc_info()[1]) 8387750ad47SMarcel Moolenaar raise 8397750ad47SMarcel Moolenaar 840