1*4882a593Smuzhiyun""" 2*4882a593SmuzhiyunBitBake Parsers 3*4882a593Smuzhiyun 4*4882a593SmuzhiyunFile parsers for the BitBake build tools. 5*4882a593Smuzhiyun 6*4882a593Smuzhiyun""" 7*4882a593Smuzhiyun 8*4882a593Smuzhiyun 9*4882a593Smuzhiyun# Copyright (C) 2003, 2004 Chris Larson 10*4882a593Smuzhiyun# Copyright (C) 2003, 2004 Phil Blundell 11*4882a593Smuzhiyun# 12*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only 13*4882a593Smuzhiyun# 14*4882a593Smuzhiyun# Based on functions from the base bb module, Copyright 2003 Holger Schurig 15*4882a593Smuzhiyun# 16*4882a593Smuzhiyun 17*4882a593Smuzhiyunhandlers = [] 18*4882a593Smuzhiyun 19*4882a593Smuzhiyunimport errno 20*4882a593Smuzhiyunimport logging 21*4882a593Smuzhiyunimport os 22*4882a593Smuzhiyunimport stat 23*4882a593Smuzhiyunimport bb 24*4882a593Smuzhiyunimport bb.utils 25*4882a593Smuzhiyunimport bb.siggen 26*4882a593Smuzhiyun 27*4882a593Smuzhiyunlogger = logging.getLogger("BitBake.Parsing") 28*4882a593Smuzhiyun 29*4882a593Smuzhiyunclass ParseError(Exception): 30*4882a593Smuzhiyun """Exception raised when parsing fails""" 31*4882a593Smuzhiyun def __init__(self, msg, filename, lineno=0): 32*4882a593Smuzhiyun self.msg = msg 33*4882a593Smuzhiyun self.filename = filename 34*4882a593Smuzhiyun self.lineno = lineno 35*4882a593Smuzhiyun Exception.__init__(self, msg, filename, lineno) 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun def __str__(self): 38*4882a593Smuzhiyun if self.lineno: 39*4882a593Smuzhiyun return "ParseError at %s:%d: %s" % (self.filename, self.lineno, self.msg) 40*4882a593Smuzhiyun else: 41*4882a593Smuzhiyun return "ParseError in %s: %s" % (self.filename, self.msg) 42*4882a593Smuzhiyun 43*4882a593Smuzhiyunclass SkipRecipe(Exception): 44*4882a593Smuzhiyun """Exception raised to skip this recipe""" 45*4882a593Smuzhiyun 46*4882a593Smuzhiyunclass SkipPackage(SkipRecipe): 47*4882a593Smuzhiyun """Exception raised to skip this recipe (use SkipRecipe in new code)""" 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun__mtime_cache = {} 50*4882a593Smuzhiyundef cached_mtime(f): 51*4882a593Smuzhiyun if f not in __mtime_cache: 52*4882a593Smuzhiyun __mtime_cache[f] = os.stat(f)[stat.ST_MTIME] 53*4882a593Smuzhiyun return __mtime_cache[f] 54*4882a593Smuzhiyun 55*4882a593Smuzhiyundef cached_mtime_noerror(f): 56*4882a593Smuzhiyun if f not in __mtime_cache: 57*4882a593Smuzhiyun try: 58*4882a593Smuzhiyun __mtime_cache[f] = os.stat(f)[stat.ST_MTIME] 59*4882a593Smuzhiyun except OSError: 60*4882a593Smuzhiyun return 0 61*4882a593Smuzhiyun return __mtime_cache[f] 62*4882a593Smuzhiyun 63*4882a593Smuzhiyundef update_mtime(f): 64*4882a593Smuzhiyun try: 65*4882a593Smuzhiyun __mtime_cache[f] = os.stat(f)[stat.ST_MTIME] 66*4882a593Smuzhiyun except OSError: 67*4882a593Smuzhiyun if f in __mtime_cache: 68*4882a593Smuzhiyun del __mtime_cache[f] 69*4882a593Smuzhiyun return 0 70*4882a593Smuzhiyun return __mtime_cache[f] 71*4882a593Smuzhiyun 72*4882a593Smuzhiyundef update_cache(f): 73*4882a593Smuzhiyun if f in __mtime_cache: 74*4882a593Smuzhiyun logger.debug("Updating mtime cache for %s" % f) 75*4882a593Smuzhiyun update_mtime(f) 76*4882a593Smuzhiyun 77*4882a593Smuzhiyundef clear_cache(): 78*4882a593Smuzhiyun global __mtime_cache 79*4882a593Smuzhiyun __mtime_cache = {} 80*4882a593Smuzhiyun 81*4882a593Smuzhiyundef mark_dependency(d, f): 82*4882a593Smuzhiyun if f.startswith('./'): 83*4882a593Smuzhiyun f = "%s/%s" % (os.getcwd(), f[2:]) 84*4882a593Smuzhiyun deps = (d.getVar('__depends', False) or []) 85*4882a593Smuzhiyun s = (f, cached_mtime_noerror(f)) 86*4882a593Smuzhiyun if s not in deps: 87*4882a593Smuzhiyun deps.append(s) 88*4882a593Smuzhiyun d.setVar('__depends', deps) 89*4882a593Smuzhiyun 90*4882a593Smuzhiyundef check_dependency(d, f): 91*4882a593Smuzhiyun s = (f, cached_mtime_noerror(f)) 92*4882a593Smuzhiyun deps = (d.getVar('__depends', False) or []) 93*4882a593Smuzhiyun return s in deps 94*4882a593Smuzhiyun 95*4882a593Smuzhiyundef supports(fn, data): 96*4882a593Smuzhiyun """Returns true if we have a handler for this file, false otherwise""" 97*4882a593Smuzhiyun for h in handlers: 98*4882a593Smuzhiyun if h['supports'](fn, data): 99*4882a593Smuzhiyun return 1 100*4882a593Smuzhiyun return 0 101*4882a593Smuzhiyun 102*4882a593Smuzhiyundef handle(fn, data, include = 0): 103*4882a593Smuzhiyun """Call the handler that is appropriate for this file""" 104*4882a593Smuzhiyun for h in handlers: 105*4882a593Smuzhiyun if h['supports'](fn, data): 106*4882a593Smuzhiyun with data.inchistory.include(fn): 107*4882a593Smuzhiyun return h['handle'](fn, data, include) 108*4882a593Smuzhiyun raise ParseError("not a BitBake file", fn) 109*4882a593Smuzhiyun 110*4882a593Smuzhiyundef init(fn, data): 111*4882a593Smuzhiyun for h in handlers: 112*4882a593Smuzhiyun if h['supports'](fn): 113*4882a593Smuzhiyun return h['init'](data) 114*4882a593Smuzhiyun 115*4882a593Smuzhiyundef init_parser(d): 116*4882a593Smuzhiyun if hasattr(bb.parse, "siggen"): 117*4882a593Smuzhiyun bb.parse.siggen.exit() 118*4882a593Smuzhiyun bb.parse.siggen = bb.siggen.init(d) 119*4882a593Smuzhiyun 120*4882a593Smuzhiyundef resolve_file(fn, d): 121*4882a593Smuzhiyun if not os.path.isabs(fn): 122*4882a593Smuzhiyun bbpath = d.getVar("BBPATH") 123*4882a593Smuzhiyun newfn, attempts = bb.utils.which(bbpath, fn, history=True) 124*4882a593Smuzhiyun for af in attempts: 125*4882a593Smuzhiyun mark_dependency(d, af) 126*4882a593Smuzhiyun if not newfn: 127*4882a593Smuzhiyun raise IOError(errno.ENOENT, "file %s not found in %s" % (fn, bbpath)) 128*4882a593Smuzhiyun fn = newfn 129*4882a593Smuzhiyun else: 130*4882a593Smuzhiyun mark_dependency(d, fn) 131*4882a593Smuzhiyun 132*4882a593Smuzhiyun if not os.path.isfile(fn): 133*4882a593Smuzhiyun raise IOError(errno.ENOENT, "file %s not found" % fn) 134*4882a593Smuzhiyun 135*4882a593Smuzhiyun return fn 136*4882a593Smuzhiyun 137*4882a593Smuzhiyun# Used by OpenEmbedded metadata 138*4882a593Smuzhiyun__pkgsplit_cache__={} 139*4882a593Smuzhiyundef vars_from_file(mypkg, d): 140*4882a593Smuzhiyun if not mypkg or not mypkg.endswith((".bb", ".bbappend")): 141*4882a593Smuzhiyun return (None, None, None) 142*4882a593Smuzhiyun if mypkg in __pkgsplit_cache__: 143*4882a593Smuzhiyun return __pkgsplit_cache__[mypkg] 144*4882a593Smuzhiyun 145*4882a593Smuzhiyun myfile = os.path.splitext(os.path.basename(mypkg)) 146*4882a593Smuzhiyun parts = myfile[0].split('_') 147*4882a593Smuzhiyun __pkgsplit_cache__[mypkg] = parts 148*4882a593Smuzhiyun if len(parts) > 3: 149*4882a593Smuzhiyun raise ParseError("Unable to generate default variables from filename (too many underscores)", mypkg) 150*4882a593Smuzhiyun exp = 3 - len(parts) 151*4882a593Smuzhiyun tmplist = [] 152*4882a593Smuzhiyun while exp != 0: 153*4882a593Smuzhiyun exp -= 1 154*4882a593Smuzhiyun tmplist.append(None) 155*4882a593Smuzhiyun parts.extend(tmplist) 156*4882a593Smuzhiyun return parts 157*4882a593Smuzhiyun 158*4882a593Smuzhiyundef get_file_depends(d): 159*4882a593Smuzhiyun '''Return the dependent files''' 160*4882a593Smuzhiyun dep_files = [] 161*4882a593Smuzhiyun depends = d.getVar('__base_depends', False) or [] 162*4882a593Smuzhiyun depends = depends + (d.getVar('__depends', False) or []) 163*4882a593Smuzhiyun for (fn, _) in depends: 164*4882a593Smuzhiyun dep_files.append(os.path.abspath(fn)) 165*4882a593Smuzhiyun return " ".join(dep_files) 166*4882a593Smuzhiyun 167*4882a593Smuzhiyunfrom bb.parse.parse_py import __version__, ConfHandler, BBHandler 168