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