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""" 39*f974ced3SSimon J. GerratySPDX-License-Identifier: BSD-2-Clause 40*f974ced3SSimon J. Gerraty 417750ad47SMarcel MoolenaarRCSid: 42*f974ced3SSimon J. Gerraty $Id: meta2deps.py,v 1.47 2024/02/17 17:26:57 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. 79*f974ced3SSimon J. Gerraty 80*f974ced3SSimon J. Gerraty Cleanup any leading ``./`` and trailing ``/.`` 817750ad47SMarcel Moolenaar """ 82*f974ced3SSimon 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('./'): 93*f974ced3SSimon J. Gerraty while path.startswith('./'): 94*f974ced3SSimon J. Gerraty path = path[1:] 95*f974ced3SSimon 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 153*f974ced3SSimon 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. 207*f974ced3SSimon 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 2974ed4429cSSimon J. Gerraty # we want the longest match 2984ed4429cSSimon J. Gerraty self.srctops.sort(reverse=True) 2994ed4429cSSimon J. Gerraty self.objroots.sort(reverse=True) 3004ed4429cSSimon J. Gerraty 3013b26e5a4SSimon J. Gerraty self.excludes = conf.get('EXCLUDES', []) 302ccfb9654SSimon J. Gerraty 3037750ad47SMarcel Moolenaar if self.debug: 30410ea6facSSimon J. Gerraty print("host_target=", self.host_target, file=self.debug_out) 30510ea6facSSimon J. Gerraty print("srctops=", self.srctops, file=self.debug_out) 30610ea6facSSimon J. Gerraty print("objroots=", self.objroots, file=self.debug_out) 307ccfb9654SSimon J. Gerraty print("excludes=", self.excludes, file=self.debug_out) 3083b26e5a4SSimon J. Gerraty print("ext_list=", self.exts, file=self.debug_out) 3097750ad47SMarcel Moolenaar 3107750ad47SMarcel Moolenaar self.dirdep_re = re.compile(r'([^/]+)/(.+)') 3117750ad47SMarcel Moolenaar 3127750ad47SMarcel Moolenaar if self.dpdeps and not self.reldir: 3137750ad47SMarcel Moolenaar if self.debug: 31410ea6facSSimon J. Gerraty print("need reldir:", end=' ', file=self.debug_out) 3157750ad47SMarcel Moolenaar if self.curdir: 3167750ad47SMarcel Moolenaar srctop = self.find_top(self.curdir, self.srctops) 3177750ad47SMarcel Moolenaar if srctop: 3187750ad47SMarcel Moolenaar self.reldir = self.curdir.replace(srctop,'') 3197750ad47SMarcel Moolenaar if self.debug: 32010ea6facSSimon J. Gerraty print(self.reldir, file=self.debug_out) 3217750ad47SMarcel Moolenaar if not self.reldir: 3227750ad47SMarcel Moolenaar self.dpdeps = None # we cannot do it? 3237750ad47SMarcel Moolenaar 324876336c8SSimon J. Gerraty self.cwd = os.getcwd() # make sure this is initialized 325ccfb9654SSimon J. Gerraty self.last_dir = self.cwd 326876336c8SSimon J. Gerraty 3277750ad47SMarcel Moolenaar if name: 328d5ddb276SSimon J. Gerraty self.try_parse() 3297750ad47SMarcel Moolenaar 3307750ad47SMarcel Moolenaar def reset(self): 3317750ad47SMarcel Moolenaar """reset state if we are being passed meta files from multiple directories.""" 3327750ad47SMarcel Moolenaar self.seen = {} 3337750ad47SMarcel Moolenaar self.obj_deps = [] 3347750ad47SMarcel Moolenaar self.src_deps = [] 3357750ad47SMarcel Moolenaar self.file_deps = [] 3367750ad47SMarcel Moolenaar 3377750ad47SMarcel Moolenaar def dirdeps(self, sep='\n'): 3387750ad47SMarcel Moolenaar """return DIRDEPS""" 3397750ad47SMarcel Moolenaar return sep.strip() + sep.join(self.obj_deps) 3407750ad47SMarcel Moolenaar 3417750ad47SMarcel Moolenaar def src_dirdeps(self, sep='\n'): 3427750ad47SMarcel Moolenaar """return SRC_DIRDEPS""" 3437750ad47SMarcel Moolenaar return sep.strip() + sep.join(self.src_deps) 3447750ad47SMarcel Moolenaar 3457750ad47SMarcel Moolenaar def file_depends(self, out=None): 3467750ad47SMarcel Moolenaar """Append DPDEPS_${file} += ${RELDIR} 3477750ad47SMarcel Moolenaar for each file we saw, to the output file.""" 3487750ad47SMarcel Moolenaar if not self.reldir: 3497750ad47SMarcel Moolenaar return None 3507750ad47SMarcel Moolenaar for f in sort_unique(self.file_deps): 35110ea6facSSimon J. Gerraty print('DPDEPS_%s += %s' % (f, self.reldir), file=out) 352b47b9f6bSSimon J. Gerraty # these entries provide for reverse DIRDEPS lookup 353b47b9f6bSSimon J. Gerraty for f in self.obj_deps: 354b47b9f6bSSimon J. Gerraty print('DEPDIRS_%s += %s' % (f, self.reldir), file=out) 3557750ad47SMarcel Moolenaar 3567750ad47SMarcel Moolenaar def seenit(self, dir): 3577750ad47SMarcel Moolenaar """rememer that we have seen dir.""" 3587750ad47SMarcel Moolenaar self.seen[dir] = 1 3597750ad47SMarcel Moolenaar 3607750ad47SMarcel Moolenaar def add(self, list, data, clue=''): 3617750ad47SMarcel Moolenaar """add data to list if it isn't already there.""" 3627750ad47SMarcel Moolenaar if data not in list: 3637750ad47SMarcel Moolenaar list.append(data) 3647750ad47SMarcel Moolenaar if self.debug: 36510ea6facSSimon J. Gerraty print("%s: %sAdd: %s" % (self.name, clue, data), file=self.debug_out) 3667750ad47SMarcel Moolenaar 3677750ad47SMarcel Moolenaar def find_top(self, path, list): 368ccfb9654SSimon J. Gerraty """the logical tree may be split across multiple trees""" 3697750ad47SMarcel Moolenaar for top in list: 3707750ad47SMarcel Moolenaar if path.startswith(top): 3717750ad47SMarcel Moolenaar if self.debug > 2: 37210ea6facSSimon J. Gerraty print("found in", top, file=self.debug_out) 3737750ad47SMarcel Moolenaar return top 3747750ad47SMarcel Moolenaar return None 3757750ad47SMarcel Moolenaar 3767750ad47SMarcel Moolenaar def find_obj(self, objroot, dir, path, input): 3777750ad47SMarcel Moolenaar """return path within objroot, taking care of .dirdep files""" 3787750ad47SMarcel Moolenaar ddep = None 3797750ad47SMarcel Moolenaar for ddepf in [path + '.dirdep', dir + '/.dirdep']: 3807750ad47SMarcel Moolenaar if not ddep and os.path.exists(ddepf): 38110ea6facSSimon J. Gerraty ddep = open(ddepf, 'r').readline().strip('# \n') 3827750ad47SMarcel Moolenaar if self.debug > 1: 38310ea6facSSimon J. Gerraty print("found %s: %s\n" % (ddepf, ddep), file=self.debug_out) 3843b26e5a4SSimon J. Gerraty for e in self.exts: 3853b26e5a4SSimon J. Gerraty if ddep.endswith(e): 3863b26e5a4SSimon J. Gerraty ddep = ddep[0:-len(e)] 3873b26e5a4SSimon J. Gerraty break 3887750ad47SMarcel Moolenaar 3897750ad47SMarcel Moolenaar if not ddep: 3907750ad47SMarcel Moolenaar # no .dirdeps, so remember that we've seen the raw input 3917750ad47SMarcel Moolenaar self.seenit(input) 3927750ad47SMarcel Moolenaar self.seenit(dir) 3937750ad47SMarcel Moolenaar if self.machine == 'none': 3947750ad47SMarcel Moolenaar if dir.startswith(objroot): 3957750ad47SMarcel Moolenaar return dir.replace(objroot,'') 3967750ad47SMarcel Moolenaar return None 3977750ad47SMarcel Moolenaar m = self.dirdep_re.match(dir.replace(objroot,'')) 3987750ad47SMarcel Moolenaar if m: 3997750ad47SMarcel Moolenaar ddep = m.group(2) 4007750ad47SMarcel Moolenaar dmachine = m.group(1) 4017750ad47SMarcel Moolenaar if dmachine != self.machine: 4027750ad47SMarcel Moolenaar if not (self.machine == 'host' and 4037750ad47SMarcel Moolenaar dmachine == self.host_target): 4047750ad47SMarcel Moolenaar if self.debug > 2: 40510ea6facSSimon J. Gerraty print("adding .%s to %s" % (dmachine, ddep), file=self.debug_out) 4067750ad47SMarcel Moolenaar ddep += '.' + dmachine 4077750ad47SMarcel Moolenaar 4087750ad47SMarcel Moolenaar return ddep 4097750ad47SMarcel Moolenaar 410d5ddb276SSimon J. Gerraty def try_parse(self, name=None, file=None): 411d5ddb276SSimon J. Gerraty """give file and line number causing exception""" 412d5ddb276SSimon J. Gerraty try: 413d5ddb276SSimon J. Gerraty self.parse(name, file) 414d5ddb276SSimon J. Gerraty except: 415d5ddb276SSimon J. Gerraty # give a useful clue 41610ea6facSSimon J. Gerraty print('{}:{}: '.format(self.name, self.line), end=' ', file=sys.stderr) 417d5ddb276SSimon J. Gerraty raise 418d5ddb276SSimon J. Gerraty 4197750ad47SMarcel Moolenaar def parse(self, name=None, file=None): 4207750ad47SMarcel Moolenaar """A meta file looks like: 4217750ad47SMarcel Moolenaar 4227750ad47SMarcel Moolenaar # Meta data file "path" 4237750ad47SMarcel Moolenaar CMD "command-line" 4247750ad47SMarcel Moolenaar CWD "cwd" 4257750ad47SMarcel Moolenaar TARGET "target" 4267750ad47SMarcel Moolenaar -- command output -- 4277750ad47SMarcel Moolenaar -- filemon acquired metadata -- 4287750ad47SMarcel Moolenaar # buildmon version 3 4297750ad47SMarcel Moolenaar V 3 4307750ad47SMarcel Moolenaar C "pid" "cwd" 4317750ad47SMarcel Moolenaar E "pid" "path" 4327750ad47SMarcel Moolenaar F "pid" "child" 4337750ad47SMarcel Moolenaar R "pid" "path" 4347750ad47SMarcel Moolenaar W "pid" "path" 4357750ad47SMarcel Moolenaar X "pid" "status" 4367750ad47SMarcel Moolenaar D "pid" "path" 4377750ad47SMarcel Moolenaar L "pid" "src" "target" 4387750ad47SMarcel Moolenaar M "pid" "old" "new" 4397750ad47SMarcel Moolenaar S "pid" "path" 4407750ad47SMarcel Moolenaar # Bye bye 4417750ad47SMarcel Moolenaar 4427750ad47SMarcel Moolenaar We go to some effort to avoid processing a dependency more than once. 4437750ad47SMarcel Moolenaar Of the above record types only C,E,F,L,R,V and W are of interest. 4447750ad47SMarcel Moolenaar """ 4457750ad47SMarcel Moolenaar 4467750ad47SMarcel Moolenaar version = 0 # unknown 4477750ad47SMarcel Moolenaar if name: 4487750ad47SMarcel Moolenaar self.name = name; 4497750ad47SMarcel Moolenaar if file: 4507750ad47SMarcel Moolenaar f = file 451ccfb9654SSimon J. Gerraty cwd = self.last_dir = self.cwd 4527750ad47SMarcel Moolenaar else: 45310ea6facSSimon J. Gerraty f = open(self.name, 'r') 4547750ad47SMarcel Moolenaar skip = True 4557750ad47SMarcel Moolenaar pid_cwd = {} 4567750ad47SMarcel Moolenaar pid_last_dir = {} 4577750ad47SMarcel Moolenaar last_pid = 0 458bf7aa99aSSimon J. Gerraty eof_token = False 4597750ad47SMarcel Moolenaar 460d5ddb276SSimon J. Gerraty self.line = 0 4617750ad47SMarcel Moolenaar if self.curdir: 4627750ad47SMarcel Moolenaar self.seenit(self.curdir) # we ignore this 4637750ad47SMarcel Moolenaar 464bf7aa99aSSimon J. Gerraty interesting = '#CEFLRVX' 4657750ad47SMarcel Moolenaar for line in f: 466d5ddb276SSimon J. Gerraty self.line += 1 4677750ad47SMarcel Moolenaar # ignore anything we don't care about 4687750ad47SMarcel Moolenaar if not line[0] in interesting: 4697750ad47SMarcel Moolenaar continue 4707750ad47SMarcel Moolenaar if self.debug > 2: 47110ea6facSSimon J. Gerraty print("input:", line, end=' ', file=self.debug_out) 4727750ad47SMarcel Moolenaar w = line.split() 4737750ad47SMarcel Moolenaar 4747750ad47SMarcel Moolenaar if skip: 4757750ad47SMarcel Moolenaar if w[0] == 'V': 4767750ad47SMarcel Moolenaar skip = False 4777750ad47SMarcel Moolenaar version = int(w[1]) 4787750ad47SMarcel Moolenaar """ 4797750ad47SMarcel Moolenaar if version < 4: 4807750ad47SMarcel Moolenaar # we cannot ignore 'W' records 4817750ad47SMarcel Moolenaar # as they may be 'rw' 4827750ad47SMarcel Moolenaar interesting += 'W' 4837750ad47SMarcel Moolenaar """ 4847750ad47SMarcel Moolenaar elif w[0] == 'CWD': 485ccfb9654SSimon J. Gerraty self.cwd = cwd = self.last_dir = w[1] 4867750ad47SMarcel Moolenaar self.seenit(cwd) # ignore this 4877750ad47SMarcel Moolenaar if self.debug: 48810ea6facSSimon J. Gerraty print("%s: CWD=%s" % (self.name, cwd), file=self.debug_out) 4897750ad47SMarcel Moolenaar continue 4907750ad47SMarcel Moolenaar 491bf7aa99aSSimon J. Gerraty if w[0] == '#': 492bf7aa99aSSimon J. Gerraty # check the file has not been truncated 493bf7aa99aSSimon J. Gerraty if line.find('Bye') > 0: 494bf7aa99aSSimon J. Gerraty eof_token = True 495bf7aa99aSSimon J. Gerraty continue 496bf7aa99aSSimon J. Gerraty 4977750ad47SMarcel Moolenaar pid = int(w[1]) 4987750ad47SMarcel Moolenaar if pid != last_pid: 4997750ad47SMarcel Moolenaar if last_pid: 500ccfb9654SSimon J. Gerraty pid_last_dir[last_pid] = self.last_dir 5013b26e5a4SSimon J. Gerraty cwd = pid_cwd.get(pid, self.cwd) 5023b26e5a4SSimon J. Gerraty self.last_dir = pid_last_dir.get(pid, self.cwd) 5037750ad47SMarcel Moolenaar last_pid = pid 5047750ad47SMarcel Moolenaar 5057750ad47SMarcel Moolenaar # process operations 5067750ad47SMarcel Moolenaar if w[0] == 'F': 5077750ad47SMarcel Moolenaar npid = int(w[2]) 5087750ad47SMarcel Moolenaar pid_cwd[npid] = cwd 5097750ad47SMarcel Moolenaar pid_last_dir[npid] = cwd 5107750ad47SMarcel Moolenaar last_pid = npid 5117750ad47SMarcel Moolenaar continue 5127750ad47SMarcel Moolenaar elif w[0] == 'C': 5137750ad47SMarcel Moolenaar cwd = abspath(w[2], cwd, None, self.debug, self.debug_out) 514960b77beSSimon J. Gerraty if not cwd: 515960b77beSSimon J. Gerraty cwd = w[2] 516960b77beSSimon J. Gerraty if self.debug > 1: 517960b77beSSimon J. Gerraty print("missing cwd=", cwd, file=self.debug_out) 5187750ad47SMarcel Moolenaar if cwd.endswith('/.'): 5197750ad47SMarcel Moolenaar cwd = cwd[0:-2] 520b47b9f6bSSimon J. Gerraty self.last_dir = pid_last_dir[pid] = cwd 521b47b9f6bSSimon J. Gerraty pid_cwd[pid] = cwd 5227750ad47SMarcel Moolenaar if self.debug > 1: 52310ea6facSSimon J. Gerraty print("cwd=", cwd, file=self.debug_out) 5247750ad47SMarcel Moolenaar continue 5257750ad47SMarcel Moolenaar 526bf7aa99aSSimon J. Gerraty if w[0] == 'X': 527bf7aa99aSSimon J. Gerraty try: 528bf7aa99aSSimon J. Gerraty del self.pids[pid] 529bf7aa99aSSimon J. Gerraty except KeyError: 530bf7aa99aSSimon J. Gerraty pass 531bf7aa99aSSimon J. Gerraty continue 532bf7aa99aSSimon J. Gerraty 5337750ad47SMarcel Moolenaar if w[2] in self.seen: 5347750ad47SMarcel Moolenaar if self.debug > 2: 53510ea6facSSimon J. Gerraty print("seen:", w[2], file=self.debug_out) 5367750ad47SMarcel Moolenaar continue 5377750ad47SMarcel Moolenaar # file operations 5387750ad47SMarcel Moolenaar if w[0] in 'ML': 539ccfb9654SSimon J. Gerraty # these are special, tread src as read and 540ccfb9654SSimon J. Gerraty # target as write 541960b77beSSimon J. Gerraty self.parse_path(w[2].strip("'"), cwd, 'R', w) 542960b77beSSimon J. Gerraty self.parse_path(w[3].strip("'"), cwd, 'W', w) 543ccfb9654SSimon J. Gerraty continue 544ccfb9654SSimon J. Gerraty elif w[0] in 'ERWS': 5457750ad47SMarcel Moolenaar path = w[2] 546bf7aa99aSSimon J. Gerraty if w[0] == 'E': 547bf7aa99aSSimon J. Gerraty self.pids[pid] = path 548bf7aa99aSSimon J. Gerraty elif path == '.': 549960b77beSSimon J. Gerraty continue 550ccfb9654SSimon J. Gerraty self.parse_path(path, cwd, w[0], w) 551ccfb9654SSimon J. Gerraty 552bf7aa99aSSimon J. Gerraty if version == 0: 553bf7aa99aSSimon J. Gerraty raise AssertionError('missing filemon data') 554bf7aa99aSSimon J. Gerraty if not eof_token: 555bf7aa99aSSimon J. Gerraty raise AssertionError('truncated filemon data') 556bf7aa99aSSimon J. Gerraty 557bf7aa99aSSimon J. Gerraty setid_pids = [] 558bf7aa99aSSimon J. Gerraty # self.pids should be empty! 559bf7aa99aSSimon J. Gerraty for pid,path in self.pids.items(): 560bf7aa99aSSimon J. Gerraty try: 561bf7aa99aSSimon J. Gerraty # no guarantee that path is still valid 562bf7aa99aSSimon J. Gerraty if os.stat(path).st_mode & (stat.S_ISUID|stat.S_ISGID): 563bf7aa99aSSimon J. Gerraty # we do not expect anything after Exec 564bf7aa99aSSimon J. Gerraty setid_pids.append(pid) 565bf7aa99aSSimon J. Gerraty continue 566bf7aa99aSSimon J. Gerraty except: 567bf7aa99aSSimon J. Gerraty # we do not care why the above fails, 568bf7aa99aSSimon J. Gerraty # we do not want to miss the ERROR below. 569bf7aa99aSSimon J. Gerraty pass 570bf7aa99aSSimon J. Gerraty print("ERROR: missing eXit for {} pid {}".format(path, pid)) 571bf7aa99aSSimon J. Gerraty for pid in setid_pids: 572bf7aa99aSSimon J. Gerraty del self.pids[pid] 573bf7aa99aSSimon J. Gerraty assert(len(self.pids) == 0) 574ccfb9654SSimon J. Gerraty if not file: 575ccfb9654SSimon J. Gerraty f.close() 576ccfb9654SSimon J. Gerraty 577c0339e7dSSimon J. Gerraty def is_src(self, base, dir, rdir): 578c0339e7dSSimon J. Gerraty """is base in srctop""" 579c0339e7dSSimon J. Gerraty for dir in [dir,rdir]: 580c0339e7dSSimon J. Gerraty if not dir: 581c0339e7dSSimon J. Gerraty continue 582c0339e7dSSimon J. Gerraty path = '/'.join([dir,base]) 583c0339e7dSSimon J. Gerraty srctop = self.find_top(path, self.srctops) 584c0339e7dSSimon J. Gerraty if srctop: 585c0339e7dSSimon J. Gerraty if self.dpdeps: 586c0339e7dSSimon J. Gerraty self.add(self.file_deps, path.replace(srctop,''), 'file') 587c0339e7dSSimon J. Gerraty self.add(self.src_deps, dir.replace(srctop,''), 'src') 588c0339e7dSSimon J. Gerraty self.seenit(dir) 589c0339e7dSSimon J. Gerraty return True 590c0339e7dSSimon J. Gerraty return False 591c0339e7dSSimon J. Gerraty 592ccfb9654SSimon J. Gerraty def parse_path(self, path, cwd, op=None, w=[]): 593ccfb9654SSimon J. Gerraty """look at a path for the op specified""" 594ccfb9654SSimon J. Gerraty 595ccfb9654SSimon J. Gerraty if not op: 596ccfb9654SSimon J. Gerraty op = w[0] 597ccfb9654SSimon J. Gerraty 598fbc1b149SSimon J. Gerraty # we are never interested in .dirdep files as dependencies 599fbc1b149SSimon J. Gerraty if path.endswith('.dirdep'): 600ccfb9654SSimon J. Gerraty return 601ccfb9654SSimon J. Gerraty for p in self.excludes: 602ccfb9654SSimon J. Gerraty if p and path.startswith(p): 603ccfb9654SSimon J. Gerraty if self.debug > 2: 604e1dfa657SBryan Drewery print("exclude:", p, path, file=self.debug_out) 605ccfb9654SSimon J. Gerraty return 6067750ad47SMarcel Moolenaar # we don't want to resolve the last component if it is 6077750ad47SMarcel Moolenaar # a symlink 608ccfb9654SSimon J. Gerraty path = resolve(path, cwd, self.last_dir, self.debug, self.debug_out) 6097750ad47SMarcel Moolenaar if not path: 610ccfb9654SSimon J. Gerraty return 6117750ad47SMarcel Moolenaar dir,base = os.path.split(path) 6127750ad47SMarcel Moolenaar if dir in self.seen: 6137750ad47SMarcel Moolenaar if self.debug > 2: 61410ea6facSSimon J. Gerraty print("seen:", dir, file=self.debug_out) 615ccfb9654SSimon J. Gerraty return 6167750ad47SMarcel Moolenaar # we can have a path in an objdir which is a link 6177750ad47SMarcel Moolenaar # to the src dir, we may need to add dependencies for each 6187750ad47SMarcel Moolenaar rdir = dir 619ccfb9654SSimon J. Gerraty dir = abspath(dir, cwd, self.last_dir, self.debug, self.debug_out) 6203b26e5a4SSimon J. Gerraty if dir: 6216d4f05fdSSimon J. Gerraty rdir = os.path.realpath(dir) 6223b26e5a4SSimon J. Gerraty else: 6233b26e5a4SSimon J. Gerraty dir = rdir 624c0339e7dSSimon J. Gerraty if rdir == dir: 625c0339e7dSSimon J. Gerraty rdir = None 6267750ad47SMarcel Moolenaar # now put path back together 6277750ad47SMarcel Moolenaar path = '/'.join([dir,base]) 6287750ad47SMarcel Moolenaar if self.debug > 1: 62910ea6facSSimon J. Gerraty print("raw=%s rdir=%s dir=%s path=%s" % (w[2], rdir, dir, path), file=self.debug_out) 630ccfb9654SSimon J. Gerraty if op in 'RWS': 631ccfb9654SSimon J. Gerraty if path in [self.last_dir, cwd, self.cwd, self.curdir]: 6327750ad47SMarcel Moolenaar if self.debug > 1: 63310ea6facSSimon J. Gerraty print("skipping:", path, file=self.debug_out) 634ccfb9654SSimon J. Gerraty return 6357750ad47SMarcel Moolenaar if os.path.isdir(path): 636ccfb9654SSimon J. Gerraty if op in 'RW': 637ccfb9654SSimon J. Gerraty self.last_dir = path; 6387750ad47SMarcel Moolenaar if self.debug > 1: 639ccfb9654SSimon J. Gerraty print("ldir=", self.last_dir, file=self.debug_out) 640ccfb9654SSimon J. Gerraty return 6417750ad47SMarcel Moolenaar 642960b77beSSimon J. Gerraty if op in 'ER': 6437750ad47SMarcel Moolenaar # finally, we get down to it 6447750ad47SMarcel Moolenaar if dir == self.cwd or dir == self.curdir: 645ccfb9654SSimon J. Gerraty return 646c0339e7dSSimon J. Gerraty if self.is_src(base, dir, rdir): 6477750ad47SMarcel Moolenaar self.seenit(w[2]) 648c0339e7dSSimon J. Gerraty if not rdir: 649ccfb9654SSimon J. Gerraty return 6507750ad47SMarcel Moolenaar 6517750ad47SMarcel Moolenaar objroot = None 6527750ad47SMarcel Moolenaar for dir in [dir,rdir]: 6537750ad47SMarcel Moolenaar if not dir: 6547750ad47SMarcel Moolenaar continue 6557750ad47SMarcel Moolenaar objroot = self.find_top(dir, self.objroots) 6567750ad47SMarcel Moolenaar if objroot: 6577750ad47SMarcel Moolenaar break 6587750ad47SMarcel Moolenaar if objroot: 6597750ad47SMarcel Moolenaar ddep = self.find_obj(objroot, dir, path, w[2]) 6607750ad47SMarcel Moolenaar if ddep: 6617750ad47SMarcel Moolenaar self.add(self.obj_deps, ddep, 'obj') 662b47b9f6bSSimon J. Gerraty if self.dpdeps and objroot.endswith('/stage/'): 663b47b9f6bSSimon J. Gerraty sp = '/'.join(path.replace(objroot,'').split('/')[1:]) 664b47b9f6bSSimon J. Gerraty self.add(self.file_deps, sp, 'file') 6657750ad47SMarcel Moolenaar else: 6667750ad47SMarcel Moolenaar # don't waste time looking again 6677750ad47SMarcel Moolenaar self.seenit(w[2]) 6687750ad47SMarcel Moolenaar self.seenit(dir) 6697750ad47SMarcel Moolenaar 6707750ad47SMarcel Moolenaar 6717750ad47SMarcel Moolenaardef main(argv, klass=MetaFile, xopts='', xoptf=None): 6727750ad47SMarcel Moolenaar """Simple driver for class MetaFile. 6737750ad47SMarcel Moolenaar 6747750ad47SMarcel Moolenaar Usage: 6757750ad47SMarcel Moolenaar script [options] [key=value ...] "meta" ... 6767750ad47SMarcel Moolenaar 6777750ad47SMarcel Moolenaar Options and key=value pairs contribute to the 6787750ad47SMarcel Moolenaar dictionary passed to MetaFile. 6797750ad47SMarcel Moolenaar 6807750ad47SMarcel Moolenaar -S "SRCTOP" 6817750ad47SMarcel Moolenaar add "SRCTOP" to the "SRCTOPS" list. 6827750ad47SMarcel Moolenaar 6837750ad47SMarcel Moolenaar -C "CURDIR" 6847750ad47SMarcel Moolenaar 6857750ad47SMarcel Moolenaar -O "OBJROOT" 6867750ad47SMarcel Moolenaar add "OBJROOT" to the "OBJROOTS" list. 6877750ad47SMarcel Moolenaar 6887750ad47SMarcel Moolenaar -m "MACHINE" 6897750ad47SMarcel Moolenaar 690bf062775SSimon J. Gerraty -a "MACHINE_ARCH" 691bf062775SSimon J. Gerraty 6927750ad47SMarcel Moolenaar -H "HOST_TARGET" 6937750ad47SMarcel Moolenaar 6947750ad47SMarcel Moolenaar -D "DPDEPS" 6957750ad47SMarcel Moolenaar 6967750ad47SMarcel Moolenaar -d bumps debug level 6977750ad47SMarcel Moolenaar 6987750ad47SMarcel Moolenaar """ 6997750ad47SMarcel Moolenaar import getopt 7007750ad47SMarcel Moolenaar 7017750ad47SMarcel Moolenaar # import Psyco if we can 7027750ad47SMarcel Moolenaar # it can speed things up quite a bit 7037750ad47SMarcel Moolenaar have_psyco = 0 7047750ad47SMarcel Moolenaar try: 7057750ad47SMarcel Moolenaar import psyco 7067750ad47SMarcel Moolenaar psyco.full() 7077750ad47SMarcel Moolenaar have_psyco = 1 7087750ad47SMarcel Moolenaar except: 7097750ad47SMarcel Moolenaar pass 7107750ad47SMarcel Moolenaar 7117750ad47SMarcel Moolenaar conf = { 7127750ad47SMarcel Moolenaar 'SRCTOPS': [], 7137750ad47SMarcel Moolenaar 'OBJROOTS': [], 714ccfb9654SSimon J. Gerraty 'EXCLUDES': [], 7157750ad47SMarcel Moolenaar } 7167750ad47SMarcel Moolenaar 7177750ad47SMarcel Moolenaar try: 7187750ad47SMarcel Moolenaar machine = os.environ['MACHINE'] 7197750ad47SMarcel Moolenaar if machine: 7207750ad47SMarcel Moolenaar conf['MACHINE'] = machine 721bf062775SSimon J. Gerraty machine_arch = os.environ['MACHINE_ARCH'] 722bf062775SSimon J. Gerraty if machine_arch: 723bf062775SSimon J. Gerraty conf['MACHINE_ARCH'] = machine_arch 7247750ad47SMarcel Moolenaar srctop = os.environ['SB_SRC'] 7257750ad47SMarcel Moolenaar if srctop: 7267750ad47SMarcel Moolenaar conf['SRCTOPS'].append(srctop) 7277750ad47SMarcel Moolenaar objroot = os.environ['SB_OBJROOT'] 7287750ad47SMarcel Moolenaar if objroot: 7297750ad47SMarcel Moolenaar conf['OBJROOTS'].append(objroot) 7307750ad47SMarcel Moolenaar except: 7317750ad47SMarcel Moolenaar pass 7327750ad47SMarcel Moolenaar 7337750ad47SMarcel Moolenaar debug = 0 7347750ad47SMarcel Moolenaar output = True 7357750ad47SMarcel Moolenaar 736ccfb9654SSimon J. Gerraty opts, args = getopt.getopt(argv[1:], 'a:dS:C:O:R:m:D:H:qT:X:' + xopts) 7377750ad47SMarcel Moolenaar for o, a in opts: 738bf062775SSimon J. Gerraty if o == '-a': 739bf062775SSimon J. Gerraty conf['MACHINE_ARCH'] = a 740bf062775SSimon J. Gerraty elif o == '-d': 7417750ad47SMarcel Moolenaar debug += 1 7427750ad47SMarcel Moolenaar elif o == '-q': 7437750ad47SMarcel Moolenaar output = False 7447750ad47SMarcel Moolenaar elif o == '-H': 7457750ad47SMarcel Moolenaar conf['HOST_TARGET'] = a 7467750ad47SMarcel Moolenaar elif o == '-S': 7477750ad47SMarcel Moolenaar if a not in conf['SRCTOPS']: 7487750ad47SMarcel Moolenaar conf['SRCTOPS'].append(a) 7497750ad47SMarcel Moolenaar elif o == '-C': 7507750ad47SMarcel Moolenaar conf['CURDIR'] = a 7517750ad47SMarcel Moolenaar elif o == '-O': 7527750ad47SMarcel Moolenaar if a not in conf['OBJROOTS']: 7537750ad47SMarcel Moolenaar conf['OBJROOTS'].append(a) 7547750ad47SMarcel Moolenaar elif o == '-R': 7557750ad47SMarcel Moolenaar conf['RELDIR'] = a 7567750ad47SMarcel Moolenaar elif o == '-D': 7577750ad47SMarcel Moolenaar conf['DPDEPS'] = a 7587750ad47SMarcel Moolenaar elif o == '-m': 7597750ad47SMarcel Moolenaar conf['MACHINE'] = a 760bf062775SSimon J. Gerraty elif o == '-T': 761bf062775SSimon J. Gerraty conf['TARGET_SPEC'] = a 762ccfb9654SSimon J. Gerraty elif o == '-X': 763ccfb9654SSimon J. Gerraty if a not in conf['EXCLUDES']: 764ccfb9654SSimon J. Gerraty conf['EXCLUDES'].append(a) 7657750ad47SMarcel Moolenaar elif xoptf: 7667750ad47SMarcel Moolenaar xoptf(o, a, conf) 7677750ad47SMarcel Moolenaar 7687750ad47SMarcel Moolenaar conf['debug'] = debug 7697750ad47SMarcel Moolenaar 7707750ad47SMarcel Moolenaar # get any var=val assignments 7717750ad47SMarcel Moolenaar eaten = [] 7727750ad47SMarcel Moolenaar for a in args: 7737750ad47SMarcel Moolenaar if a.find('=') > 0: 7747750ad47SMarcel Moolenaar k,v = a.split('=') 7757750ad47SMarcel Moolenaar if k in ['SRCTOP','OBJROOT','SRCTOPS','OBJROOTS']: 7767750ad47SMarcel Moolenaar if k == 'SRCTOP': 7777750ad47SMarcel Moolenaar k = 'SRCTOPS' 7787750ad47SMarcel Moolenaar elif k == 'OBJROOT': 7797750ad47SMarcel Moolenaar k = 'OBJROOTS' 7807750ad47SMarcel Moolenaar if v not in conf[k]: 7817750ad47SMarcel Moolenaar conf[k].append(v) 7827750ad47SMarcel Moolenaar else: 7837750ad47SMarcel Moolenaar conf[k] = v 7847750ad47SMarcel Moolenaar eaten.append(a) 7857750ad47SMarcel Moolenaar continue 7867750ad47SMarcel Moolenaar break 7877750ad47SMarcel Moolenaar 7887750ad47SMarcel Moolenaar for a in eaten: 7897750ad47SMarcel Moolenaar args.remove(a) 7907750ad47SMarcel Moolenaar 7913b26e5a4SSimon J. Gerraty debug_out = conf.get('debug_out', sys.stderr) 7927750ad47SMarcel Moolenaar 7937750ad47SMarcel Moolenaar if debug: 79410ea6facSSimon J. Gerraty print("config:", file=debug_out) 79510ea6facSSimon J. Gerraty print("psyco=", have_psyco, file=debug_out) 79610ea6facSSimon J. Gerraty for k,v in list(conf.items()): 79710ea6facSSimon J. Gerraty print("%s=%s" % (k,v), file=debug_out) 7987750ad47SMarcel Moolenaar 799ccfb9654SSimon J. Gerraty m = None 8007750ad47SMarcel Moolenaar for a in args: 801d5ddb276SSimon J. Gerraty if a.endswith('.meta'): 802ccfb9654SSimon J. Gerraty if not os.path.exists(a): 803ccfb9654SSimon J. Gerraty continue 8047750ad47SMarcel Moolenaar m = klass(a, conf) 805d5ddb276SSimon J. Gerraty elif a.startswith('@'): 806d5ddb276SSimon J. Gerraty # there can actually multiple files per line 807d5ddb276SSimon J. Gerraty for line in open(a[1:]): 808d5ddb276SSimon J. Gerraty for f in line.strip().split(): 809ccfb9654SSimon J. Gerraty if not os.path.exists(f): 810ccfb9654SSimon J. Gerraty continue 811d5ddb276SSimon J. Gerraty m = klass(f, conf) 8127750ad47SMarcel Moolenaar 813ccfb9654SSimon J. Gerraty if output and m: 81410ea6facSSimon J. Gerraty print(m.dirdeps()) 8157750ad47SMarcel Moolenaar 81610ea6facSSimon J. Gerraty print(m.src_dirdeps('\nsrc:')) 8177750ad47SMarcel Moolenaar 8183b26e5a4SSimon J. Gerraty dpdeps = conf.get('DPDEPS') 8197750ad47SMarcel Moolenaar if dpdeps: 8203b26e5a4SSimon J. Gerraty m.file_depends(open(dpdeps, 'w')) 8217750ad47SMarcel Moolenaar 8227750ad47SMarcel Moolenaar return m 8237750ad47SMarcel Moolenaar 8247750ad47SMarcel Moolenaarif __name__ == '__main__': 8257750ad47SMarcel Moolenaar try: 8267750ad47SMarcel Moolenaar main(sys.argv) 8277750ad47SMarcel Moolenaar except: 8287750ad47SMarcel Moolenaar # yes, this goes to stdout 82910ea6facSSimon J. Gerraty print("ERROR: ", sys.exc_info()[1]) 8307750ad47SMarcel Moolenaar raise 8317750ad47SMarcel Moolenaar 832