15f1e34d9SAlexandre Perrin#!/usr/bin/env python 25f1e34d9SAlexandre Perrin 36a91b982SJohn Marinofrom __future__ import print_function 46a91b982SJohn Marino 55f1e34d9SAlexandre Perrin""" 65f1e34d9SAlexandre PerrinThis script parses each "meta" file and extracts the 75f1e34d9SAlexandre Perrininformation needed to deduce build and src dependencies. 85f1e34d9SAlexandre Perrin 95f1e34d9SAlexandre PerrinIt works much the same as the original shell script, but is 105f1e34d9SAlexandre Perrin*much* more efficient. 115f1e34d9SAlexandre Perrin 125f1e34d9SAlexandre PerrinThe parsing work is handled by the class MetaFile. 135f1e34d9SAlexandre PerrinWe only pay attention to a subset of the information in the 145f1e34d9SAlexandre Perrin"meta" files. Specifically: 155f1e34d9SAlexandre Perrin 165f1e34d9SAlexandre Perrin'CWD' to initialize our notion. 175f1e34d9SAlexandre Perrin 185f1e34d9SAlexandre Perrin'C' to track chdir(2) on a per process basis 195f1e34d9SAlexandre Perrin 205f1e34d9SAlexandre Perrin'R' files read are what we really care about. 215f1e34d9SAlexandre Perrin directories read, provide a clue to resolving 225f1e34d9SAlexandre Perrin subsequent relative paths. That is if we cannot find 235f1e34d9SAlexandre Perrin them relative to 'cwd', we check relative to the last 245f1e34d9SAlexandre Perrin dir read. 255f1e34d9SAlexandre Perrin 265f1e34d9SAlexandre Perrin'W' files opened for write or read-write, 275f1e34d9SAlexandre Perrin for filemon V3 and earlier. 285f1e34d9SAlexandre Perrin 295f1e34d9SAlexandre Perrin'E' files executed. 305f1e34d9SAlexandre Perrin 315f1e34d9SAlexandre Perrin'L' files linked 325f1e34d9SAlexandre Perrin 335f1e34d9SAlexandre Perrin'V' the filemon version, this record is used as a clue 345f1e34d9SAlexandre Perrin that we have reached the interesting bit. 355f1e34d9SAlexandre Perrin 365f1e34d9SAlexandre Perrin""" 375f1e34d9SAlexandre Perrin 385f1e34d9SAlexandre Perrin""" 395f1e34d9SAlexandre PerrinRCSid: 40*6eef5f0cSAntonio Huete Jimenez $Id: meta2deps.py,v 1.44 2022/01/29 02:42:01 sjg Exp $ 415f1e34d9SAlexandre Perrin 42a34d5fb1SAntonio Huete Jimenez Copyright (c) 2011-2020, Simon J. Gerraty 43ca58f742SDaniel Fojt Copyright (c) 2011-2017, Juniper Networks, Inc. 445f1e34d9SAlexandre Perrin All rights reserved. 455f1e34d9SAlexandre Perrin 465f1e34d9SAlexandre Perrin Redistribution and use in source and binary forms, with or without 475f1e34d9SAlexandre Perrin modification, are permitted provided that the following conditions 485f1e34d9SAlexandre Perrin are met: 495f1e34d9SAlexandre Perrin 1. Redistributions of source code must retain the above copyright 505f1e34d9SAlexandre Perrin notice, this list of conditions and the following disclaimer. 515f1e34d9SAlexandre Perrin 2. Redistributions in binary form must reproduce the above copyright 525f1e34d9SAlexandre Perrin notice, this list of conditions and the following disclaimer in the 535f1e34d9SAlexandre Perrin documentation and/or other materials provided with the distribution. 545f1e34d9SAlexandre Perrin 555f1e34d9SAlexandre Perrin THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 565f1e34d9SAlexandre Perrin "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 575f1e34d9SAlexandre Perrin LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 585f1e34d9SAlexandre Perrin A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 595f1e34d9SAlexandre Perrin OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 605f1e34d9SAlexandre Perrin SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 615f1e34d9SAlexandre Perrin LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 625f1e34d9SAlexandre Perrin DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 635f1e34d9SAlexandre Perrin THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 645f1e34d9SAlexandre Perrin (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 655f1e34d9SAlexandre Perrin OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 665f1e34d9SAlexandre Perrin 675f1e34d9SAlexandre Perrin""" 685f1e34d9SAlexandre Perrin 69*6eef5f0cSAntonio Huete Jimenezimport os 70*6eef5f0cSAntonio Huete Jimenezimport re 71*6eef5f0cSAntonio Huete Jimenezimport sys 72*6eef5f0cSAntonio Huete Jimenezimport stat 735f1e34d9SAlexandre Perrin 745f1e34d9SAlexandre Perrindef resolve(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr): 755f1e34d9SAlexandre Perrin """ 765f1e34d9SAlexandre Perrin Return an absolute path, resolving via cwd or last_dir if needed. 775f1e34d9SAlexandre Perrin """ 785f1e34d9SAlexandre Perrin if path.endswith('/.'): 795f1e34d9SAlexandre Perrin path = path[0:-2] 805f1e34d9SAlexandre Perrin if len(path) > 0 and path[0] == '/': 81ca58f742SDaniel Fojt if os.path.exists(path): 825f1e34d9SAlexandre Perrin return path 83ca58f742SDaniel Fojt if debug > 2: 84ca58f742SDaniel Fojt print("skipping non-existent:", path, file=debug_out) 85ca58f742SDaniel Fojt return None 865f1e34d9SAlexandre Perrin if path == '.': 875f1e34d9SAlexandre Perrin return cwd 885f1e34d9SAlexandre Perrin if path.startswith('./'): 895f1e34d9SAlexandre Perrin return cwd + path[1:] 905f1e34d9SAlexandre Perrin if last_dir == cwd: 915f1e34d9SAlexandre Perrin last_dir = None 925f1e34d9SAlexandre Perrin for d in [last_dir, cwd]: 935f1e34d9SAlexandre Perrin if not d: 945f1e34d9SAlexandre Perrin continue 95ca58f742SDaniel Fojt if path == '..': 96ca58f742SDaniel Fojt dw = d.split('/') 97ca58f742SDaniel Fojt p = '/'.join(dw[:-1]) 98ca58f742SDaniel Fojt if not p: 99ca58f742SDaniel Fojt p = '/' 100ca58f742SDaniel Fojt return p 1015f1e34d9SAlexandre Perrin p = '/'.join([d,path]) 1025f1e34d9SAlexandre Perrin if debug > 2: 1036a91b982SJohn Marino print("looking for:", p, end=' ', file=debug_out) 1045f1e34d9SAlexandre Perrin if not os.path.exists(p): 1055f1e34d9SAlexandre Perrin if debug > 2: 1066a91b982SJohn Marino print("nope", file=debug_out) 1075f1e34d9SAlexandre Perrin p = None 1085f1e34d9SAlexandre Perrin continue 1095f1e34d9SAlexandre Perrin if debug > 2: 1106a91b982SJohn Marino print("found:", p, file=debug_out) 1115f1e34d9SAlexandre Perrin return p 1125f1e34d9SAlexandre Perrin return None 1135f1e34d9SAlexandre Perrin 114ca58f742SDaniel Fojtdef cleanpath(path): 115ca58f742SDaniel Fojt """cleanup path without using realpath(3)""" 116ca58f742SDaniel Fojt if path.startswith('/'): 117ca58f742SDaniel Fojt r = '/' 118ca58f742SDaniel Fojt else: 119ca58f742SDaniel Fojt r = '' 120ca58f742SDaniel Fojt p = [] 121ca58f742SDaniel Fojt w = path.split('/') 122ca58f742SDaniel Fojt for d in w: 123ca58f742SDaniel Fojt if not d or d == '.': 124ca58f742SDaniel Fojt continue 125ca58f742SDaniel Fojt if d == '..': 126ca58f742SDaniel Fojt try: 127ca58f742SDaniel Fojt p.pop() 128ca58f742SDaniel Fojt continue 129ca58f742SDaniel Fojt except: 130ca58f742SDaniel Fojt break 131ca58f742SDaniel Fojt p.append(d) 132ca58f742SDaniel Fojt 133ca58f742SDaniel Fojt return r + '/'.join(p) 134ca58f742SDaniel Fojt 1355f1e34d9SAlexandre Perrindef abspath(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr): 1365f1e34d9SAlexandre Perrin """ 1375f1e34d9SAlexandre Perrin Return an absolute path, resolving via cwd or last_dir if needed. 138ca58f742SDaniel Fojt this gets called a lot, so we try to avoid calling realpath. 1395f1e34d9SAlexandre Perrin """ 1405f1e34d9SAlexandre Perrin rpath = resolve(path, cwd, last_dir, debug, debug_out) 1415f1e34d9SAlexandre Perrin if rpath: 1425f1e34d9SAlexandre Perrin path = rpath 143ca58f742SDaniel Fojt elif len(path) > 0 and path[0] == '/': 144ca58f742SDaniel Fojt return None 145f445c897SJohn Marino if (path.find('/') < 0 or 146f445c897SJohn Marino path.find('./') > 0 or 147ca58f742SDaniel Fojt path.endswith('/..')): 148ca58f742SDaniel Fojt path = cleanpath(path) 1495f1e34d9SAlexandre Perrin return path 1505f1e34d9SAlexandre Perrin 1515f1e34d9SAlexandre Perrindef sort_unique(list, cmp=None, key=None, reverse=False): 152*6eef5f0cSAntonio Huete Jimenez if sys.version_info[0] == 2: 1535f1e34d9SAlexandre Perrin list.sort(cmp, key, reverse) 154*6eef5f0cSAntonio Huete Jimenez else: 155*6eef5f0cSAntonio Huete Jimenez list.sort(reverse=reverse) 1565f1e34d9SAlexandre Perrin nl = [] 1575f1e34d9SAlexandre Perrin le = None 1585f1e34d9SAlexandre Perrin for e in list: 1595f1e34d9SAlexandre Perrin if e == le: 1605f1e34d9SAlexandre Perrin continue 161ca58f742SDaniel Fojt le = e 1625f1e34d9SAlexandre Perrin nl.append(e) 1635f1e34d9SAlexandre Perrin return nl 1645f1e34d9SAlexandre Perrin 1655f1e34d9SAlexandre Perrindef add_trims(x): 1665f1e34d9SAlexandre Perrin return ['/' + x + '/', 1675f1e34d9SAlexandre Perrin '/' + x, 1685f1e34d9SAlexandre Perrin x + '/', 1695f1e34d9SAlexandre Perrin x] 1705f1e34d9SAlexandre Perrin 171*6eef5f0cSAntonio Huete Jimenezdef target_spec_exts(target_spec): 172*6eef5f0cSAntonio Huete Jimenez """return a list of dirdep extensions that could match target_spec""" 173*6eef5f0cSAntonio Huete Jimenez 174*6eef5f0cSAntonio Huete Jimenez if target_spec.find(',') < 0: 175*6eef5f0cSAntonio Huete Jimenez return ['.'+target_spec] 176*6eef5f0cSAntonio Huete Jimenez w = target_spec.split(',') 177*6eef5f0cSAntonio Huete Jimenez n = len(w) 178*6eef5f0cSAntonio Huete Jimenez e = [] 179*6eef5f0cSAntonio Huete Jimenez while n > 0: 180*6eef5f0cSAntonio Huete Jimenez e.append('.'+','.join(w[0:n])) 181*6eef5f0cSAntonio Huete Jimenez n -= 1 182*6eef5f0cSAntonio Huete Jimenez return e 183*6eef5f0cSAntonio Huete Jimenez 1845f1e34d9SAlexandre Perrinclass MetaFile: 1855f1e34d9SAlexandre Perrin """class to parse meta files generated by bmake.""" 1865f1e34d9SAlexandre Perrin 1875f1e34d9SAlexandre Perrin conf = None 1885f1e34d9SAlexandre Perrin dirdep_re = None 1895f1e34d9SAlexandre Perrin host_target = None 1905f1e34d9SAlexandre Perrin srctops = [] 1915f1e34d9SAlexandre Perrin objroots = [] 192f445c897SJohn Marino excludes = [] 1935f1e34d9SAlexandre Perrin seen = {} 1945f1e34d9SAlexandre Perrin obj_deps = [] 1955f1e34d9SAlexandre Perrin src_deps = [] 1965f1e34d9SAlexandre Perrin file_deps = [] 1975f1e34d9SAlexandre Perrin 1985f1e34d9SAlexandre Perrin def __init__(self, name, conf={}): 1995f1e34d9SAlexandre Perrin """if name is set we will parse it now. 2005f1e34d9SAlexandre Perrin conf can have the follwing keys: 2015f1e34d9SAlexandre Perrin 2025f1e34d9SAlexandre Perrin SRCTOPS list of tops of the src tree(s). 2035f1e34d9SAlexandre Perrin 2045f1e34d9SAlexandre Perrin CURDIR the src directory 'bmake' was run from. 2055f1e34d9SAlexandre Perrin 2065f1e34d9SAlexandre Perrin RELDIR the relative path from SRCTOP to CURDIR 2075f1e34d9SAlexandre Perrin 2085f1e34d9SAlexandre Perrin MACHINE the machine we built for. 2095f1e34d9SAlexandre Perrin set to 'none' if we are not cross-building. 2105f1e34d9SAlexandre Perrin More specifically if machine cannot be deduced from objdirs. 2115f1e34d9SAlexandre Perrin 2125f1e34d9SAlexandre Perrin TARGET_SPEC 2135f1e34d9SAlexandre Perrin Sometimes MACHINE isn't enough. 2145f1e34d9SAlexandre Perrin 2155f1e34d9SAlexandre Perrin HOST_TARGET 2166a91b982SJohn Marino when we build for the pseudo machine 'host' 2175f1e34d9SAlexandre Perrin the object tree uses HOST_TARGET rather than MACHINE. 2185f1e34d9SAlexandre Perrin 2195f1e34d9SAlexandre Perrin OBJROOTS a list of the common prefix for all obj dirs it might 2205f1e34d9SAlexandre Perrin end in '/' or '-'. 2215f1e34d9SAlexandre Perrin 2225f1e34d9SAlexandre Perrin DPDEPS names an optional file to which per file dependencies 2235f1e34d9SAlexandre Perrin will be appended. 2245f1e34d9SAlexandre Perrin For example if 'some/path/foo.h' is read from SRCTOP 2255f1e34d9SAlexandre Perrin then 'DPDEPS_some/path/foo.h +=' "RELDIR" is output. 2265f1e34d9SAlexandre Perrin This can allow 'bmake' to learn all the dirs within 2275f1e34d9SAlexandre Perrin the tree that depend on 'foo.h' 2285f1e34d9SAlexandre Perrin 229f445c897SJohn Marino EXCLUDES 230f445c897SJohn Marino A list of paths to ignore. 231f445c897SJohn Marino ccache(1) can otherwise be trouble. 232f445c897SJohn Marino 2335f1e34d9SAlexandre Perrin debug desired debug level 2345f1e34d9SAlexandre Perrin 2355f1e34d9SAlexandre Perrin debug_out open file to send debug output to (sys.stderr) 2365f1e34d9SAlexandre Perrin 2375f1e34d9SAlexandre Perrin """ 2385f1e34d9SAlexandre Perrin 2395f1e34d9SAlexandre Perrin self.name = name 240*6eef5f0cSAntonio Huete Jimenez self.debug = conf.get('debug', 0) 241*6eef5f0cSAntonio Huete Jimenez self.debug_out = conf.get('debug_out', sys.stderr) 2425f1e34d9SAlexandre Perrin 243*6eef5f0cSAntonio Huete Jimenez self.machine = conf.get('MACHINE', '') 244*6eef5f0cSAntonio Huete Jimenez self.machine_arch = conf.get('MACHINE_ARCH', '') 245*6eef5f0cSAntonio Huete Jimenez self.target_spec = conf.get('TARGET_SPEC', self.machine) 246*6eef5f0cSAntonio Huete Jimenez self.exts = target_spec_exts(self.target_spec) 247*6eef5f0cSAntonio Huete Jimenez self.curdir = conf.get('CURDIR') 248*6eef5f0cSAntonio Huete Jimenez self.reldir = conf.get('RELDIR') 249*6eef5f0cSAntonio Huete Jimenez self.dpdeps = conf.get('DPDEPS') 250*6eef5f0cSAntonio Huete Jimenez self.pids = {} 2515f1e34d9SAlexandre Perrin self.line = 0 2525f1e34d9SAlexandre Perrin 2535f1e34d9SAlexandre Perrin if not self.conf: 2545f1e34d9SAlexandre Perrin # some of the steps below we want to do only once 2555f1e34d9SAlexandre Perrin self.conf = conf 256*6eef5f0cSAntonio Huete Jimenez self.host_target = conf.get('HOST_TARGET') 257*6eef5f0cSAntonio Huete Jimenez for srctop in conf.get('SRCTOPS', []): 2585f1e34d9SAlexandre Perrin if srctop[-1] != '/': 2595f1e34d9SAlexandre Perrin srctop += '/' 2605f1e34d9SAlexandre Perrin if not srctop in self.srctops: 2615f1e34d9SAlexandre Perrin self.srctops.append(srctop) 2625f1e34d9SAlexandre Perrin _srctop = os.path.realpath(srctop) 2635f1e34d9SAlexandre Perrin if _srctop[-1] != '/': 2645f1e34d9SAlexandre Perrin _srctop += '/' 2655f1e34d9SAlexandre Perrin if not _srctop in self.srctops: 2665f1e34d9SAlexandre Perrin self.srctops.append(_srctop) 2675f1e34d9SAlexandre Perrin 2685f1e34d9SAlexandre Perrin trim_list = add_trims(self.machine) 2695f1e34d9SAlexandre Perrin if self.machine == 'host': 2705f1e34d9SAlexandre Perrin trim_list += add_trims(self.host_target) 271*6eef5f0cSAntonio Huete Jimenez if self.target_spec != self.machine: 2725f1e34d9SAlexandre Perrin trim_list += add_trims(self.target_spec) 2735f1e34d9SAlexandre Perrin 274*6eef5f0cSAntonio Huete Jimenez for objroot in conf.get('OBJROOTS', []): 2755f1e34d9SAlexandre Perrin for e in trim_list: 2765f1e34d9SAlexandre Perrin if objroot.endswith(e): 2775f1e34d9SAlexandre Perrin # this is not what we want - fix it 2785f1e34d9SAlexandre Perrin objroot = objroot[0:-len(e)] 279ca58f742SDaniel Fojt 280ca58f742SDaniel Fojt if objroot[-1] != '/': 2815f1e34d9SAlexandre Perrin objroot += '/' 2825f1e34d9SAlexandre Perrin if not objroot in self.objroots: 2835f1e34d9SAlexandre Perrin self.objroots.append(objroot) 2845f1e34d9SAlexandre Perrin _objroot = os.path.realpath(objroot) 2855f1e34d9SAlexandre Perrin if objroot[-1] == '/': 2865f1e34d9SAlexandre Perrin _objroot += '/' 2875f1e34d9SAlexandre Perrin if not _objroot in self.objroots: 2885f1e34d9SAlexandre Perrin self.objroots.append(_objroot) 2895f1e34d9SAlexandre Perrin 2905f1e34d9SAlexandre Perrin # we want the longest match 2915f1e34d9SAlexandre Perrin self.srctops.sort(reverse=True) 2925f1e34d9SAlexandre Perrin self.objroots.sort(reverse=True) 2935f1e34d9SAlexandre Perrin 294*6eef5f0cSAntonio Huete Jimenez self.excludes = conf.get('EXCLUDES', []) 295f445c897SJohn Marino 2965f1e34d9SAlexandre Perrin if self.debug: 2976a91b982SJohn Marino print("host_target=", self.host_target, file=self.debug_out) 2986a91b982SJohn Marino print("srctops=", self.srctops, file=self.debug_out) 2996a91b982SJohn Marino print("objroots=", self.objroots, file=self.debug_out) 300f445c897SJohn Marino print("excludes=", self.excludes, file=self.debug_out) 301*6eef5f0cSAntonio Huete Jimenez print("ext_list=", self.exts, file=self.debug_out) 3025f1e34d9SAlexandre Perrin 3035f1e34d9SAlexandre Perrin self.dirdep_re = re.compile(r'([^/]+)/(.+)') 3045f1e34d9SAlexandre Perrin 3055f1e34d9SAlexandre Perrin if self.dpdeps and not self.reldir: 3065f1e34d9SAlexandre Perrin if self.debug: 3076a91b982SJohn Marino print("need reldir:", end=' ', file=self.debug_out) 3085f1e34d9SAlexandre Perrin if self.curdir: 3095f1e34d9SAlexandre Perrin srctop = self.find_top(self.curdir, self.srctops) 3105f1e34d9SAlexandre Perrin if srctop: 3115f1e34d9SAlexandre Perrin self.reldir = self.curdir.replace(srctop,'') 3125f1e34d9SAlexandre Perrin if self.debug: 3136a91b982SJohn Marino print(self.reldir, file=self.debug_out) 3145f1e34d9SAlexandre Perrin if not self.reldir: 3155f1e34d9SAlexandre Perrin self.dpdeps = None # we cannot do it? 3165f1e34d9SAlexandre Perrin 3175f1e34d9SAlexandre Perrin self.cwd = os.getcwd() # make sure this is initialized 318f445c897SJohn Marino self.last_dir = self.cwd 3195f1e34d9SAlexandre Perrin 3205f1e34d9SAlexandre Perrin if name: 3215f1e34d9SAlexandre Perrin self.try_parse() 3225f1e34d9SAlexandre Perrin 3235f1e34d9SAlexandre Perrin def reset(self): 3245f1e34d9SAlexandre Perrin """reset state if we are being passed meta files from multiple directories.""" 3255f1e34d9SAlexandre Perrin self.seen = {} 3265f1e34d9SAlexandre Perrin self.obj_deps = [] 3275f1e34d9SAlexandre Perrin self.src_deps = [] 3285f1e34d9SAlexandre Perrin self.file_deps = [] 3295f1e34d9SAlexandre Perrin 3305f1e34d9SAlexandre Perrin def dirdeps(self, sep='\n'): 3315f1e34d9SAlexandre Perrin """return DIRDEPS""" 3325f1e34d9SAlexandre Perrin return sep.strip() + sep.join(self.obj_deps) 3335f1e34d9SAlexandre Perrin 3345f1e34d9SAlexandre Perrin def src_dirdeps(self, sep='\n'): 3355f1e34d9SAlexandre Perrin """return SRC_DIRDEPS""" 3365f1e34d9SAlexandre Perrin return sep.strip() + sep.join(self.src_deps) 3375f1e34d9SAlexandre Perrin 3385f1e34d9SAlexandre Perrin def file_depends(self, out=None): 3395f1e34d9SAlexandre Perrin """Append DPDEPS_${file} += ${RELDIR} 3405f1e34d9SAlexandre Perrin for each file we saw, to the output file.""" 3415f1e34d9SAlexandre Perrin if not self.reldir: 3425f1e34d9SAlexandre Perrin return None 3435f1e34d9SAlexandre Perrin for f in sort_unique(self.file_deps): 3446a91b982SJohn Marino print('DPDEPS_%s += %s' % (f, self.reldir), file=out) 345ca58f742SDaniel Fojt # these entries provide for reverse DIRDEPS lookup 346ca58f742SDaniel Fojt for f in self.obj_deps: 347ca58f742SDaniel Fojt print('DEPDIRS_%s += %s' % (f, self.reldir), file=out) 3485f1e34d9SAlexandre Perrin 3495f1e34d9SAlexandre Perrin def seenit(self, dir): 3505f1e34d9SAlexandre Perrin """rememer that we have seen dir.""" 3515f1e34d9SAlexandre Perrin self.seen[dir] = 1 3525f1e34d9SAlexandre Perrin 3535f1e34d9SAlexandre Perrin def add(self, list, data, clue=''): 3545f1e34d9SAlexandre Perrin """add data to list if it isn't already there.""" 3555f1e34d9SAlexandre Perrin if data not in list: 3565f1e34d9SAlexandre Perrin list.append(data) 3575f1e34d9SAlexandre Perrin if self.debug: 3586a91b982SJohn Marino print("%s: %sAdd: %s" % (self.name, clue, data), file=self.debug_out) 3595f1e34d9SAlexandre Perrin 3605f1e34d9SAlexandre Perrin def find_top(self, path, list): 3616a91b982SJohn Marino """the logical tree may be split across multiple trees""" 3625f1e34d9SAlexandre Perrin for top in list: 3635f1e34d9SAlexandre Perrin if path.startswith(top): 3645f1e34d9SAlexandre Perrin if self.debug > 2: 3656a91b982SJohn Marino print("found in", top, file=self.debug_out) 3665f1e34d9SAlexandre Perrin return top 3675f1e34d9SAlexandre Perrin return None 3685f1e34d9SAlexandre Perrin 3695f1e34d9SAlexandre Perrin def find_obj(self, objroot, dir, path, input): 3705f1e34d9SAlexandre Perrin """return path within objroot, taking care of .dirdep files""" 3715f1e34d9SAlexandre Perrin ddep = None 3725f1e34d9SAlexandre Perrin for ddepf in [path + '.dirdep', dir + '/.dirdep']: 3735f1e34d9SAlexandre Perrin if not ddep and os.path.exists(ddepf): 3746a91b982SJohn Marino ddep = open(ddepf, 'r').readline().strip('# \n') 3755f1e34d9SAlexandre Perrin if self.debug > 1: 3766a91b982SJohn Marino print("found %s: %s\n" % (ddepf, ddep), file=self.debug_out) 377*6eef5f0cSAntonio Huete Jimenez for e in self.exts: 378*6eef5f0cSAntonio Huete Jimenez if ddep.endswith(e): 379*6eef5f0cSAntonio Huete Jimenez ddep = ddep[0:-len(e)] 380*6eef5f0cSAntonio Huete Jimenez break 3815f1e34d9SAlexandre Perrin 3825f1e34d9SAlexandre Perrin if not ddep: 3835f1e34d9SAlexandre Perrin # no .dirdeps, so remember that we've seen the raw input 3845f1e34d9SAlexandre Perrin self.seenit(input) 3855f1e34d9SAlexandre Perrin self.seenit(dir) 3865f1e34d9SAlexandre Perrin if self.machine == 'none': 3875f1e34d9SAlexandre Perrin if dir.startswith(objroot): 3885f1e34d9SAlexandre Perrin return dir.replace(objroot,'') 3895f1e34d9SAlexandre Perrin return None 3905f1e34d9SAlexandre Perrin m = self.dirdep_re.match(dir.replace(objroot,'')) 3915f1e34d9SAlexandre Perrin if m: 3925f1e34d9SAlexandre Perrin ddep = m.group(2) 3935f1e34d9SAlexandre Perrin dmachine = m.group(1) 3945f1e34d9SAlexandre Perrin if dmachine != self.machine: 3955f1e34d9SAlexandre Perrin if not (self.machine == 'host' and 3965f1e34d9SAlexandre Perrin dmachine == self.host_target): 3975f1e34d9SAlexandre Perrin if self.debug > 2: 3986a91b982SJohn Marino print("adding .%s to %s" % (dmachine, ddep), file=self.debug_out) 3995f1e34d9SAlexandre Perrin ddep += '.' + dmachine 4005f1e34d9SAlexandre Perrin 4015f1e34d9SAlexandre Perrin return ddep 4025f1e34d9SAlexandre Perrin 4035f1e34d9SAlexandre Perrin def try_parse(self, name=None, file=None): 4045f1e34d9SAlexandre Perrin """give file and line number causing exception""" 4055f1e34d9SAlexandre Perrin try: 4065f1e34d9SAlexandre Perrin self.parse(name, file) 4075f1e34d9SAlexandre Perrin except: 4085f1e34d9SAlexandre Perrin # give a useful clue 4096a91b982SJohn Marino print('{}:{}: '.format(self.name, self.line), end=' ', file=sys.stderr) 4105f1e34d9SAlexandre Perrin raise 4115f1e34d9SAlexandre Perrin 4125f1e34d9SAlexandre Perrin def parse(self, name=None, file=None): 4135f1e34d9SAlexandre Perrin """A meta file looks like: 4145f1e34d9SAlexandre Perrin 4155f1e34d9SAlexandre Perrin # Meta data file "path" 4165f1e34d9SAlexandre Perrin CMD "command-line" 4175f1e34d9SAlexandre Perrin CWD "cwd" 4185f1e34d9SAlexandre Perrin TARGET "target" 4195f1e34d9SAlexandre Perrin -- command output -- 4205f1e34d9SAlexandre Perrin -- filemon acquired metadata -- 4215f1e34d9SAlexandre Perrin # buildmon version 3 4225f1e34d9SAlexandre Perrin V 3 4235f1e34d9SAlexandre Perrin C "pid" "cwd" 4245f1e34d9SAlexandre Perrin E "pid" "path" 4255f1e34d9SAlexandre Perrin F "pid" "child" 4265f1e34d9SAlexandre Perrin R "pid" "path" 4275f1e34d9SAlexandre Perrin W "pid" "path" 4285f1e34d9SAlexandre Perrin X "pid" "status" 4295f1e34d9SAlexandre Perrin D "pid" "path" 4305f1e34d9SAlexandre Perrin L "pid" "src" "target" 4315f1e34d9SAlexandre Perrin M "pid" "old" "new" 4325f1e34d9SAlexandre Perrin S "pid" "path" 4335f1e34d9SAlexandre Perrin # Bye bye 4345f1e34d9SAlexandre Perrin 4355f1e34d9SAlexandre Perrin We go to some effort to avoid processing a dependency more than once. 4365f1e34d9SAlexandre Perrin Of the above record types only C,E,F,L,R,V and W are of interest. 4375f1e34d9SAlexandre Perrin """ 4385f1e34d9SAlexandre Perrin 4395f1e34d9SAlexandre Perrin version = 0 # unknown 4405f1e34d9SAlexandre Perrin if name: 4415f1e34d9SAlexandre Perrin self.name = name; 4425f1e34d9SAlexandre Perrin if file: 4435f1e34d9SAlexandre Perrin f = file 444f445c897SJohn Marino cwd = self.last_dir = self.cwd 4455f1e34d9SAlexandre Perrin else: 4466a91b982SJohn Marino f = open(self.name, 'r') 4475f1e34d9SAlexandre Perrin skip = True 4485f1e34d9SAlexandre Perrin pid_cwd = {} 4495f1e34d9SAlexandre Perrin pid_last_dir = {} 4505f1e34d9SAlexandre Perrin last_pid = 0 4515f1e34d9SAlexandre Perrin 4525f1e34d9SAlexandre Perrin self.line = 0 4535f1e34d9SAlexandre Perrin if self.curdir: 4545f1e34d9SAlexandre Perrin self.seenit(self.curdir) # we ignore this 4555f1e34d9SAlexandre Perrin 456*6eef5f0cSAntonio Huete Jimenez interesting = 'CEFLRVX' 4575f1e34d9SAlexandre Perrin for line in f: 4585f1e34d9SAlexandre Perrin self.line += 1 4595f1e34d9SAlexandre Perrin # ignore anything we don't care about 4605f1e34d9SAlexandre Perrin if not line[0] in interesting: 4615f1e34d9SAlexandre Perrin continue 4625f1e34d9SAlexandre Perrin if self.debug > 2: 4636a91b982SJohn Marino print("input:", line, end=' ', file=self.debug_out) 4645f1e34d9SAlexandre Perrin w = line.split() 4655f1e34d9SAlexandre Perrin 4665f1e34d9SAlexandre Perrin if skip: 4675f1e34d9SAlexandre Perrin if w[0] == 'V': 4685f1e34d9SAlexandre Perrin skip = False 4695f1e34d9SAlexandre Perrin version = int(w[1]) 4705f1e34d9SAlexandre Perrin """ 4715f1e34d9SAlexandre Perrin if version < 4: 4725f1e34d9SAlexandre Perrin # we cannot ignore 'W' records 4735f1e34d9SAlexandre Perrin # as they may be 'rw' 4745f1e34d9SAlexandre Perrin interesting += 'W' 4755f1e34d9SAlexandre Perrin """ 4765f1e34d9SAlexandre Perrin elif w[0] == 'CWD': 477f445c897SJohn Marino self.cwd = cwd = self.last_dir = w[1] 4785f1e34d9SAlexandre Perrin self.seenit(cwd) # ignore this 4795f1e34d9SAlexandre Perrin if self.debug: 4806a91b982SJohn Marino print("%s: CWD=%s" % (self.name, cwd), file=self.debug_out) 4815f1e34d9SAlexandre Perrin continue 4825f1e34d9SAlexandre Perrin 4835f1e34d9SAlexandre Perrin pid = int(w[1]) 4845f1e34d9SAlexandre Perrin if pid != last_pid: 4855f1e34d9SAlexandre Perrin if last_pid: 486f445c897SJohn Marino pid_last_dir[last_pid] = self.last_dir 487*6eef5f0cSAntonio Huete Jimenez cwd = pid_cwd.get(pid, self.cwd) 488*6eef5f0cSAntonio Huete Jimenez self.last_dir = pid_last_dir.get(pid, self.cwd) 4895f1e34d9SAlexandre Perrin last_pid = pid 4905f1e34d9SAlexandre Perrin 4915f1e34d9SAlexandre Perrin # process operations 4925f1e34d9SAlexandre Perrin if w[0] == 'F': 4935f1e34d9SAlexandre Perrin npid = int(w[2]) 4945f1e34d9SAlexandre Perrin pid_cwd[npid] = cwd 4955f1e34d9SAlexandre Perrin pid_last_dir[npid] = cwd 4965f1e34d9SAlexandre Perrin last_pid = npid 4975f1e34d9SAlexandre Perrin continue 4985f1e34d9SAlexandre Perrin elif w[0] == 'C': 4995f1e34d9SAlexandre Perrin cwd = abspath(w[2], cwd, None, self.debug, self.debug_out) 500ca58f742SDaniel Fojt if not cwd: 501ca58f742SDaniel Fojt cwd = w[2] 502ca58f742SDaniel Fojt if self.debug > 1: 503ca58f742SDaniel Fojt print("missing cwd=", cwd, file=self.debug_out) 5045f1e34d9SAlexandre Perrin if cwd.endswith('/.'): 5055f1e34d9SAlexandre Perrin cwd = cwd[0:-2] 506ca58f742SDaniel Fojt self.last_dir = pid_last_dir[pid] = cwd 507ca58f742SDaniel Fojt pid_cwd[pid] = cwd 5085f1e34d9SAlexandre Perrin if self.debug > 1: 5096a91b982SJohn Marino print("cwd=", cwd, file=self.debug_out) 5105f1e34d9SAlexandre Perrin continue 5115f1e34d9SAlexandre Perrin 512*6eef5f0cSAntonio Huete Jimenez if w[0] == 'X': 513*6eef5f0cSAntonio Huete Jimenez try: 514*6eef5f0cSAntonio Huete Jimenez del self.pids[pid] 515*6eef5f0cSAntonio Huete Jimenez except KeyError: 516*6eef5f0cSAntonio Huete Jimenez pass 517*6eef5f0cSAntonio Huete Jimenez continue 518*6eef5f0cSAntonio Huete Jimenez 5195f1e34d9SAlexandre Perrin if w[2] in self.seen: 5205f1e34d9SAlexandre Perrin if self.debug > 2: 5216a91b982SJohn Marino print("seen:", w[2], file=self.debug_out) 5225f1e34d9SAlexandre Perrin continue 5235f1e34d9SAlexandre Perrin # file operations 5245f1e34d9SAlexandre Perrin if w[0] in 'ML': 525f445c897SJohn Marino # these are special, tread src as read and 526f445c897SJohn Marino # target as write 527ca58f742SDaniel Fojt self.parse_path(w[2].strip("'"), cwd, 'R', w) 528ca58f742SDaniel Fojt self.parse_path(w[3].strip("'"), cwd, 'W', w) 529f445c897SJohn Marino continue 530f445c897SJohn Marino elif w[0] in 'ERWS': 5315f1e34d9SAlexandre Perrin path = w[2] 532*6eef5f0cSAntonio Huete Jimenez if w[0] == 'E': 533*6eef5f0cSAntonio Huete Jimenez self.pids[pid] = path 534*6eef5f0cSAntonio Huete Jimenez elif path == '.': 535a34d5fb1SAntonio Huete Jimenez continue 536f445c897SJohn Marino self.parse_path(path, cwd, w[0], w) 537f445c897SJohn Marino 538a34d5fb1SAntonio Huete Jimenez assert(version > 0) 539*6eef5f0cSAntonio Huete Jimenez setid_pids = [] 540*6eef5f0cSAntonio Huete Jimenez # self.pids should be empty! 541*6eef5f0cSAntonio Huete Jimenez for pid,path in self.pids.items(): 542*6eef5f0cSAntonio Huete Jimenez try: 543*6eef5f0cSAntonio Huete Jimenez # no guarantee that path is still valid 544*6eef5f0cSAntonio Huete Jimenez if os.stat(path).st_mode & (stat.S_ISUID|stat.S_ISGID): 545*6eef5f0cSAntonio Huete Jimenez # we do not expect anything after Exec 546*6eef5f0cSAntonio Huete Jimenez setid_pids.append(pid) 547*6eef5f0cSAntonio Huete Jimenez continue 548*6eef5f0cSAntonio Huete Jimenez except: 549*6eef5f0cSAntonio Huete Jimenez # we do not care why the above fails, 550*6eef5f0cSAntonio Huete Jimenez # we do not want to miss the ERROR below. 551*6eef5f0cSAntonio Huete Jimenez pass 552*6eef5f0cSAntonio Huete Jimenez print("ERROR: missing eXit for {} pid {}".format(path, pid)) 553*6eef5f0cSAntonio Huete Jimenez for pid in setid_pids: 554*6eef5f0cSAntonio Huete Jimenez del self.pids[pid] 555*6eef5f0cSAntonio Huete Jimenez assert(len(self.pids) == 0) 556f445c897SJohn Marino if not file: 557f445c897SJohn Marino f.close() 558f445c897SJohn Marino 559ca58f742SDaniel Fojt def is_src(self, base, dir, rdir): 560ca58f742SDaniel Fojt """is base in srctop""" 561ca58f742SDaniel Fojt for dir in [dir,rdir]: 562ca58f742SDaniel Fojt if not dir: 563ca58f742SDaniel Fojt continue 564ca58f742SDaniel Fojt path = '/'.join([dir,base]) 565ca58f742SDaniel Fojt srctop = self.find_top(path, self.srctops) 566ca58f742SDaniel Fojt if srctop: 567ca58f742SDaniel Fojt if self.dpdeps: 568ca58f742SDaniel Fojt self.add(self.file_deps, path.replace(srctop,''), 'file') 569ca58f742SDaniel Fojt self.add(self.src_deps, dir.replace(srctop,''), 'src') 570ca58f742SDaniel Fojt self.seenit(dir) 571ca58f742SDaniel Fojt return True 572ca58f742SDaniel Fojt return False 573ca58f742SDaniel Fojt 574f445c897SJohn Marino def parse_path(self, path, cwd, op=None, w=[]): 575f445c897SJohn Marino """look at a path for the op specified""" 576f445c897SJohn Marino 577f445c897SJohn Marino if not op: 578f445c897SJohn Marino op = w[0] 579f445c897SJohn Marino 5805f1e34d9SAlexandre Perrin # we are never interested in .dirdep files as dependencies 5815f1e34d9SAlexandre Perrin if path.endswith('.dirdep'): 582f445c897SJohn Marino return 583f445c897SJohn Marino for p in self.excludes: 584f445c897SJohn Marino if p and path.startswith(p): 585f445c897SJohn Marino if self.debug > 2: 586f445c897SJohn Marino print("exclude:", p, path, file=self.debug_out) 587f445c897SJohn Marino return 5885f1e34d9SAlexandre Perrin # we don't want to resolve the last component if it is 5895f1e34d9SAlexandre Perrin # a symlink 590f445c897SJohn Marino path = resolve(path, cwd, self.last_dir, self.debug, self.debug_out) 5915f1e34d9SAlexandre Perrin if not path: 592f445c897SJohn Marino return 5935f1e34d9SAlexandre Perrin dir,base = os.path.split(path) 5945f1e34d9SAlexandre Perrin if dir in self.seen: 5955f1e34d9SAlexandre Perrin if self.debug > 2: 5966a91b982SJohn Marino print("seen:", dir, file=self.debug_out) 597f445c897SJohn Marino return 5985f1e34d9SAlexandre Perrin # we can have a path in an objdir which is a link 5995f1e34d9SAlexandre Perrin # to the src dir, we may need to add dependencies for each 6005f1e34d9SAlexandre Perrin rdir = dir 601f445c897SJohn Marino dir = abspath(dir, cwd, self.last_dir, self.debug, self.debug_out) 602*6eef5f0cSAntonio Huete Jimenez if dir: 603ca58f742SDaniel Fojt rdir = os.path.realpath(dir) 604*6eef5f0cSAntonio Huete Jimenez else: 605*6eef5f0cSAntonio Huete Jimenez dir = rdir 606ca58f742SDaniel Fojt if rdir == dir: 6075f1e34d9SAlexandre Perrin rdir = None 6085f1e34d9SAlexandre Perrin # now put path back together 6095f1e34d9SAlexandre Perrin path = '/'.join([dir,base]) 6105f1e34d9SAlexandre Perrin if self.debug > 1: 6116a91b982SJohn Marino print("raw=%s rdir=%s dir=%s path=%s" % (w[2], rdir, dir, path), file=self.debug_out) 612f445c897SJohn Marino if op in 'RWS': 613f445c897SJohn Marino if path in [self.last_dir, cwd, self.cwd, self.curdir]: 6145f1e34d9SAlexandre Perrin if self.debug > 1: 6156a91b982SJohn Marino print("skipping:", path, file=self.debug_out) 616f445c897SJohn Marino return 6175f1e34d9SAlexandre Perrin if os.path.isdir(path): 618f445c897SJohn Marino if op in 'RW': 619f445c897SJohn Marino self.last_dir = path; 6205f1e34d9SAlexandre Perrin if self.debug > 1: 621f445c897SJohn Marino print("ldir=", self.last_dir, file=self.debug_out) 622f445c897SJohn Marino return 6235f1e34d9SAlexandre Perrin 624ca58f742SDaniel Fojt if op in 'ER': 6255f1e34d9SAlexandre Perrin # finally, we get down to it 6265f1e34d9SAlexandre Perrin if dir == self.cwd or dir == self.curdir: 627f445c897SJohn Marino return 628ca58f742SDaniel Fojt if self.is_src(base, dir, rdir): 6295f1e34d9SAlexandre Perrin self.seenit(w[2]) 630ca58f742SDaniel Fojt if not rdir: 631f445c897SJohn Marino return 6325f1e34d9SAlexandre Perrin 6335f1e34d9SAlexandre Perrin objroot = None 6345f1e34d9SAlexandre Perrin for dir in [dir,rdir]: 6355f1e34d9SAlexandre Perrin if not dir: 6365f1e34d9SAlexandre Perrin continue 6375f1e34d9SAlexandre Perrin objroot = self.find_top(dir, self.objroots) 6385f1e34d9SAlexandre Perrin if objroot: 6395f1e34d9SAlexandre Perrin break 6405f1e34d9SAlexandre Perrin if objroot: 6415f1e34d9SAlexandre Perrin ddep = self.find_obj(objroot, dir, path, w[2]) 6425f1e34d9SAlexandre Perrin if ddep: 6435f1e34d9SAlexandre Perrin self.add(self.obj_deps, ddep, 'obj') 644ca58f742SDaniel Fojt if self.dpdeps and objroot.endswith('/stage/'): 645ca58f742SDaniel Fojt sp = '/'.join(path.replace(objroot,'').split('/')[1:]) 646ca58f742SDaniel Fojt self.add(self.file_deps, sp, 'file') 6475f1e34d9SAlexandre Perrin else: 6485f1e34d9SAlexandre Perrin # don't waste time looking again 6495f1e34d9SAlexandre Perrin self.seenit(w[2]) 6505f1e34d9SAlexandre Perrin self.seenit(dir) 6515f1e34d9SAlexandre Perrin 6525f1e34d9SAlexandre Perrin 6535f1e34d9SAlexandre Perrindef main(argv, klass=MetaFile, xopts='', xoptf=None): 6545f1e34d9SAlexandre Perrin """Simple driver for class MetaFile. 6555f1e34d9SAlexandre Perrin 6565f1e34d9SAlexandre Perrin Usage: 6575f1e34d9SAlexandre Perrin script [options] [key=value ...] "meta" ... 6585f1e34d9SAlexandre Perrin 6595f1e34d9SAlexandre Perrin Options and key=value pairs contribute to the 6605f1e34d9SAlexandre Perrin dictionary passed to MetaFile. 6615f1e34d9SAlexandre Perrin 6625f1e34d9SAlexandre Perrin -S "SRCTOP" 6635f1e34d9SAlexandre Perrin add "SRCTOP" to the "SRCTOPS" list. 6645f1e34d9SAlexandre Perrin 6655f1e34d9SAlexandre Perrin -C "CURDIR" 6665f1e34d9SAlexandre Perrin 6675f1e34d9SAlexandre Perrin -O "OBJROOT" 6685f1e34d9SAlexandre Perrin add "OBJROOT" to the "OBJROOTS" list. 6695f1e34d9SAlexandre Perrin 6705f1e34d9SAlexandre Perrin -m "MACHINE" 6715f1e34d9SAlexandre Perrin 6725f1e34d9SAlexandre Perrin -a "MACHINE_ARCH" 6735f1e34d9SAlexandre Perrin 6745f1e34d9SAlexandre Perrin -H "HOST_TARGET" 6755f1e34d9SAlexandre Perrin 6765f1e34d9SAlexandre Perrin -D "DPDEPS" 6775f1e34d9SAlexandre Perrin 6785f1e34d9SAlexandre Perrin -d bumps debug level 6795f1e34d9SAlexandre Perrin 6805f1e34d9SAlexandre Perrin """ 6815f1e34d9SAlexandre Perrin import getopt 6825f1e34d9SAlexandre Perrin 6835f1e34d9SAlexandre Perrin # import Psyco if we can 6845f1e34d9SAlexandre Perrin # it can speed things up quite a bit 6855f1e34d9SAlexandre Perrin have_psyco = 0 6865f1e34d9SAlexandre Perrin try: 6875f1e34d9SAlexandre Perrin import psyco 6885f1e34d9SAlexandre Perrin psyco.full() 6895f1e34d9SAlexandre Perrin have_psyco = 1 6905f1e34d9SAlexandre Perrin except: 6915f1e34d9SAlexandre Perrin pass 6925f1e34d9SAlexandre Perrin 6935f1e34d9SAlexandre Perrin conf = { 6945f1e34d9SAlexandre Perrin 'SRCTOPS': [], 6955f1e34d9SAlexandre Perrin 'OBJROOTS': [], 696f445c897SJohn Marino 'EXCLUDES': [], 6975f1e34d9SAlexandre Perrin } 6985f1e34d9SAlexandre Perrin 6995f1e34d9SAlexandre Perrin try: 7005f1e34d9SAlexandre Perrin machine = os.environ['MACHINE'] 7015f1e34d9SAlexandre Perrin if machine: 7025f1e34d9SAlexandre Perrin conf['MACHINE'] = machine 7035f1e34d9SAlexandre Perrin machine_arch = os.environ['MACHINE_ARCH'] 7045f1e34d9SAlexandre Perrin if machine_arch: 7055f1e34d9SAlexandre Perrin conf['MACHINE_ARCH'] = machine_arch 7065f1e34d9SAlexandre Perrin srctop = os.environ['SB_SRC'] 7075f1e34d9SAlexandre Perrin if srctop: 7085f1e34d9SAlexandre Perrin conf['SRCTOPS'].append(srctop) 7095f1e34d9SAlexandre Perrin objroot = os.environ['SB_OBJROOT'] 7105f1e34d9SAlexandre Perrin if objroot: 7115f1e34d9SAlexandre Perrin conf['OBJROOTS'].append(objroot) 7125f1e34d9SAlexandre Perrin except: 7135f1e34d9SAlexandre Perrin pass 7145f1e34d9SAlexandre Perrin 7155f1e34d9SAlexandre Perrin debug = 0 7165f1e34d9SAlexandre Perrin output = True 7175f1e34d9SAlexandre Perrin 718f445c897SJohn Marino opts, args = getopt.getopt(argv[1:], 'a:dS:C:O:R:m:D:H:qT:X:' + xopts) 7195f1e34d9SAlexandre Perrin for o, a in opts: 7205f1e34d9SAlexandre Perrin if o == '-a': 7215f1e34d9SAlexandre Perrin conf['MACHINE_ARCH'] = a 7225f1e34d9SAlexandre Perrin elif o == '-d': 7235f1e34d9SAlexandre Perrin debug += 1 7245f1e34d9SAlexandre Perrin elif o == '-q': 7255f1e34d9SAlexandre Perrin output = False 7265f1e34d9SAlexandre Perrin elif o == '-H': 7275f1e34d9SAlexandre Perrin conf['HOST_TARGET'] = a 7285f1e34d9SAlexandre Perrin elif o == '-S': 7295f1e34d9SAlexandre Perrin if a not in conf['SRCTOPS']: 7305f1e34d9SAlexandre Perrin conf['SRCTOPS'].append(a) 7315f1e34d9SAlexandre Perrin elif o == '-C': 7325f1e34d9SAlexandre Perrin conf['CURDIR'] = a 7335f1e34d9SAlexandre Perrin elif o == '-O': 7345f1e34d9SAlexandre Perrin if a not in conf['OBJROOTS']: 7355f1e34d9SAlexandre Perrin conf['OBJROOTS'].append(a) 7365f1e34d9SAlexandre Perrin elif o == '-R': 7375f1e34d9SAlexandre Perrin conf['RELDIR'] = a 7385f1e34d9SAlexandre Perrin elif o == '-D': 7395f1e34d9SAlexandre Perrin conf['DPDEPS'] = a 7405f1e34d9SAlexandre Perrin elif o == '-m': 7415f1e34d9SAlexandre Perrin conf['MACHINE'] = a 7425f1e34d9SAlexandre Perrin elif o == '-T': 7435f1e34d9SAlexandre Perrin conf['TARGET_SPEC'] = a 744f445c897SJohn Marino elif o == '-X': 745f445c897SJohn Marino if a not in conf['EXCLUDES']: 746f445c897SJohn Marino conf['EXCLUDES'].append(a) 7475f1e34d9SAlexandre Perrin elif xoptf: 7485f1e34d9SAlexandre Perrin xoptf(o, a, conf) 7495f1e34d9SAlexandre Perrin 7505f1e34d9SAlexandre Perrin conf['debug'] = debug 7515f1e34d9SAlexandre Perrin 7525f1e34d9SAlexandre Perrin # get any var=val assignments 7535f1e34d9SAlexandre Perrin eaten = [] 7545f1e34d9SAlexandre Perrin for a in args: 7555f1e34d9SAlexandre Perrin if a.find('=') > 0: 7565f1e34d9SAlexandre Perrin k,v = a.split('=') 7575f1e34d9SAlexandre Perrin if k in ['SRCTOP','OBJROOT','SRCTOPS','OBJROOTS']: 7585f1e34d9SAlexandre Perrin if k == 'SRCTOP': 7595f1e34d9SAlexandre Perrin k = 'SRCTOPS' 7605f1e34d9SAlexandre Perrin elif k == 'OBJROOT': 7615f1e34d9SAlexandre Perrin k = 'OBJROOTS' 7625f1e34d9SAlexandre Perrin if v not in conf[k]: 7635f1e34d9SAlexandre Perrin conf[k].append(v) 7645f1e34d9SAlexandre Perrin else: 7655f1e34d9SAlexandre Perrin conf[k] = v 7665f1e34d9SAlexandre Perrin eaten.append(a) 7675f1e34d9SAlexandre Perrin continue 7685f1e34d9SAlexandre Perrin break 7695f1e34d9SAlexandre Perrin 7705f1e34d9SAlexandre Perrin for a in eaten: 7715f1e34d9SAlexandre Perrin args.remove(a) 7725f1e34d9SAlexandre Perrin 773*6eef5f0cSAntonio Huete Jimenez debug_out = conf.get('debug_out', sys.stderr) 7745f1e34d9SAlexandre Perrin 7755f1e34d9SAlexandre Perrin if debug: 7766a91b982SJohn Marino print("config:", file=debug_out) 7776a91b982SJohn Marino print("psyco=", have_psyco, file=debug_out) 7786a91b982SJohn Marino for k,v in list(conf.items()): 7796a91b982SJohn Marino print("%s=%s" % (k,v), file=debug_out) 7805f1e34d9SAlexandre Perrin 781f445c897SJohn Marino m = None 7825f1e34d9SAlexandre Perrin for a in args: 7835f1e34d9SAlexandre Perrin if a.endswith('.meta'): 784f445c897SJohn Marino if not os.path.exists(a): 785f445c897SJohn Marino continue 7865f1e34d9SAlexandre Perrin m = klass(a, conf) 7875f1e34d9SAlexandre Perrin elif a.startswith('@'): 7885f1e34d9SAlexandre Perrin # there can actually multiple files per line 7895f1e34d9SAlexandre Perrin for line in open(a[1:]): 7905f1e34d9SAlexandre Perrin for f in line.strip().split(): 791f445c897SJohn Marino if not os.path.exists(f): 792f445c897SJohn Marino continue 7935f1e34d9SAlexandre Perrin m = klass(f, conf) 7945f1e34d9SAlexandre Perrin 795f445c897SJohn Marino if output and m: 7966a91b982SJohn Marino print(m.dirdeps()) 7975f1e34d9SAlexandre Perrin 7986a91b982SJohn Marino print(m.src_dirdeps('\nsrc:')) 7995f1e34d9SAlexandre Perrin 800*6eef5f0cSAntonio Huete Jimenez dpdeps = conf.get('DPDEPS') 8015f1e34d9SAlexandre Perrin if dpdeps: 802*6eef5f0cSAntonio Huete Jimenez m.file_depends(open(dpdeps, 'w')) 8035f1e34d9SAlexandre Perrin 8045f1e34d9SAlexandre Perrin return m 8055f1e34d9SAlexandre Perrin 8065f1e34d9SAlexandre Perrinif __name__ == '__main__': 8075f1e34d9SAlexandre Perrin try: 8085f1e34d9SAlexandre Perrin main(sys.argv) 8095f1e34d9SAlexandre Perrin except: 8105f1e34d9SAlexandre Perrin # yes, this goes to stdout 8116a91b982SJohn Marino print("ERROR: ", sys.exc_info()[1]) 8125f1e34d9SAlexandre Perrin raise 8135f1e34d9SAlexandre Perrin 814