xref: /OK3568_Linux_fs/yocto/bitbake/lib/bb/parse/__init__.py (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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