use an empty OEMASK if none is set
[bitbake.git] / bin / oe / parse / OEHandler.py
1 #!/usr/bin/env python
2 # ex:ts=4:sw=4:sts=4:et
3 # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
4 """class for handling .oe files
5
6    Reads the file and obtains its metadata"""
7
8 import re, oe, os, sys
9 import oe.fetch, oe.build
10 from oe import debug, data, fetch, fatal
11
12 from oe.parse.ConfHandler import include, localpath, obtain, init
13 from oe.parse import ParseError
14
15 __func_start_regexp__    = re.compile( r"(((?P<py>python)|(?P<fr>fakeroot))\s*)*(?P<func>[\w\-\+]+)?\s*\(\s*\)\s*{$" )
16 __inherit_regexp__       = re.compile( r"inherit\s+(.+)" )
17 __export_func_regexp__   = re.compile( r"EXPORT_FUNCTIONS\s+(.+)" )
18 __addtask_regexp__       = re.compile("addtask\s+(?P<func>\w+)\s*((before\s*(?P<before>((.*(?=after))|(.*))))|(after\s*(?P<after>((.*(?=before))|(.*)))))*")
19 __addhandler_regexp__    = re.compile( r"addhandler\s+(.+)" )
20 __def_regexp__           = re.compile( r"def\s+(\w+).*:" )
21 __python_func_regexp__   = re.compile( r"\s+.*" )
22 __word__ = re.compile(r"\S+")
23
24 __infunc__ = ""
25 __inpython__ = False
26 __body__   = []
27 __oepath_found__ = 0
28 __classname__ = ""
29 classes = [ None, ]
30
31 def supports(fn, d):
32     localfn = localpath(fn, d)
33     return localfn[-3:] == ".oe" or localfn[-8:] == ".oeclass"
34
35 def inherit(files, d):
36     __inherit_cache = data.getVar('__inherit_cache', d) or ""
37     fn = ""
38     lineno = 0
39     for f in files:
40         file = data.expand(f, d)
41         if file[0] != "/" and file[-8:] != ".oeclass":
42             file = "classes/%s.oeclass" % file
43
44         if not file in __inherit_cache.split():
45             debug(2, "OE %s:%d: inheriting %s" % (fn, lineno, file))
46             __inherit_cache += " %s" % file
47             include(fn, file, d)
48     data.setVar('__inherit_cache', __inherit_cache, d)
49
50
51 def handle(fn, d = {}, include = 0):
52     global __func_start_regexp__, __inherit_regexp__, __export_func_regexp__, __addtask_regexp__, __addhandler_regexp__, __infunc__, __body__, __oepath_found__
53     __body__ = []
54     __oepath_found__ = 0
55     __infunc__ = ""
56     __classname__ = ""
57
58     if include == 0:
59         debug(2, "OE " + fn + ": handle(data)")
60     else:
61         debug(2, "OE " + fn + ": handle(data, include)")
62
63     (root, ext) = os.path.splitext(os.path.basename(fn))
64     init(d)
65
66     if ext == ".oeclass":
67         __classname__ = root
68         classes.append(__classname__)
69
70     if include != 0:
71         oldfile = data.getVar('FILE', d)
72     else:
73         oldfile = None
74
75     fn = obtain(fn, d)
76     oepath = ['.']
77     if not os.path.isabs(fn):
78         f = None
79         voepath = data.getVar("OEPATH", d)
80         if voepath:
81             oepath += voepath.split(":")
82         for p in oepath:
83             p = data.expand(p, d)
84             j = os.path.join(p, fn)
85             if os.access(j, os.R_OK):
86                 abs_fn = j
87                 f = open(j, 'r')
88                 break
89         if f is None:
90             raise IOError("file not found")
91     else:
92         f = open(fn,'r')
93         abs_fn = fn
94
95     if include:
96         oe.parse.mark_dependency(d, abs_fn)
97
98     if ext != ".oeclass":
99         data.setVar('FILE', fn, d)
100         i = (data.getVar("INHERIT", d, 1) or "").split()
101         if not "base" in i and __classname__ != "base":
102             i[0:0] = ["base"]
103         inherit(i, d)
104
105     lineno = 0
106     while 1:
107         lineno = lineno + 1
108         s = f.readline()
109         if not s: break
110         w = s.strip()
111         if not w: continue      # skip empty lines
112         s = s.rstrip()
113         while s[-1] == '\\':
114             lineno = lineno + 1
115             s2 = f.readline()[:-1].strip()
116             s = s[:-1] + s2
117         feeder(lineno, s, fn, d)
118     if ext == ".oeclass":
119         classes.remove(__classname__)
120     else:
121         if include == 0:
122             data.expandKeys(d)
123             data.update_data(d)
124             anonqueue = data.getVar("__anonqueue", d, 1) or []
125             for anon in anonqueue:
126                 data.setVar("__anonfunc", anon["content"], d)
127                 data.setVarFlags("__anonfunc", anon["flags"], d)
128                 from oe import build
129                 try:
130                     t = data.getVar('T', d)
131                     data.setVar('T', '${TMPDIR}/', d)
132                     build.exec_func("__anonfunc", d)
133                     data.delVar('T', d)
134                     if t:
135                         data.setVar('T', t, d)
136                 except Exception, e:
137                     oe.debug(1, "executing anonymous function: %s" % e)
138                     raise
139             data.delVar("__anonqueue", d)
140             data.delVar("__anonfunc", d)
141             set_additional_vars(fn, d, include)
142             data.update_data(d)
143
144             for var in d.keys():
145                 if data.getVarFlag(var, 'handler', d):
146                     oe.event.register(data.getVar(var, d))
147                     continue
148
149                 if not data.getVarFlag(var, 'task', d):
150                     continue
151
152                 deps = data.getVarFlag(var, 'deps', d) or []
153                 postdeps = data.getVarFlag(var, 'postdeps', d) or []
154                 oe.build.add_task(var, deps, d)
155                 for p in postdeps:
156                     pdeps = data.getVarFlag(p, 'deps', d) or []
157                     pdeps.append(var)
158                     data.setVarFlag(p, 'deps', pdeps, d)
159                     oe.build.add_task(p, pdeps, d)
160     if oldfile:
161         oe.data.setVar("FILE", oldfile, d)
162     return d
163
164 def feeder(lineno, s, fn, d):
165     global __func_start_regexp__, __inherit_regexp__, __export_func_regexp__, __addtask_regexp__, __addhandler_regexp__, __def_regexp__, __python_func_regexp__, __inpython__,__infunc__, __body__, __oepath_found__, classes, oe
166     if __infunc__:
167         if s == '}':
168             __body__.append('')
169             data.setVar(__infunc__, '\n'.join(__body__), d)
170             data.setVarFlag(__infunc__, "func", 1, d)
171             if __infunc__ == "__anonymous":
172                 anonqueue = oe.data.getVar("__anonqueue", d) or []
173                 anonitem = {}
174                 anonitem["content"] = oe.data.getVar("__anonymous", d)
175                 anonitem["flags"] = oe.data.getVarFlags("__anonymous", d)
176                 anonqueue.append(anonitem)
177                 oe.data.setVar("__anonqueue", anonqueue, d)
178                 oe.data.delVarFlags("__anonymous", d)
179                 oe.data.delVar("__anonymous", d)
180             __infunc__ = ""
181             __body__ = []
182         else:
183             __body__.append(s)
184         return
185
186     if __inpython__:
187         m = __python_func_regexp__.match(s)
188         if m:
189             __body__.append(s)
190             return
191         else:
192             text = '\n'.join(__body__)
193             comp = compile(text, "<oe>", "exec")
194             exec comp in __builtins__
195             __body__ = []
196             __inpython__ = False
197             funcs = data.getVar('__functions__', d) or ""
198             data.setVar('__functions__', "%s\n%s" % (funcs, text), d)
199 #           fall through
200
201     if s[0] == '#': return          # skip comments
202
203     m = __func_start_regexp__.match(s)
204     if m:
205         __infunc__ = m.group("func") or "__anonymous"
206         key = __infunc__
207         if data.getVar(key, d):
208 #           clean up old version of this piece of metadata, as its
209 #           flags could cause problems
210             data.setVarFlag(key, 'python', None, d)
211             data.setVarFlag(key, 'fakeroot', None, d)
212         if m.group("py") is not None:
213             data.setVarFlag(key, "python", "1", d)
214         else:
215             data.delVarFlag(key, "python", d)
216         if m.group("fr") is not None:
217             data.setVarFlag(key, "fakeroot", "1", d)
218         else:
219             data.delVarFlag(key, "fakeroot", d)
220         return
221
222     m = __def_regexp__.match(s)
223     if m:
224         __body__.append(s)
225         __inpython__ = True
226         return
227
228     m = __export_func_regexp__.match(s)
229     if m:
230         fns = m.group(1)
231         n = __word__.findall(fns)
232         for f in n:
233             allvars = []
234             allvars.append(f)
235             allvars.append(classes[-1] + "_" + f)
236
237             vars = [[ allvars[0], allvars[1] ]]
238             if len(classes) > 1 and classes[-2] is not None:
239                 allvars.append(classes[-2] + "_" + f)
240                 vars = []
241                 vars.append([allvars[2], allvars[1]])
242                 vars.append([allvars[0], allvars[2]])
243
244             for (var, calledvar) in vars:
245                 if data.getVar(var, d) and not data.getVarFlag(var, 'export_func', d):
246                     continue
247
248                 if data.getVar(var, d):
249                     data.setVarFlag(var, 'python', None, d)
250                     data.setVarFlag(var, 'func', None, d)
251
252                 for flag in [ "func", "python" ]:
253                     if data.getVarFlag(calledvar, flag, d):
254                         data.setVarFlag(var, flag, data.getVarFlag(calledvar, flag, d), d)
255                 for flag in [ "dirs" ]:
256                     if data.getVarFlag(var, flag, d):
257                         data.setVarFlag(calledvar, flag, data.getVarFlag(var, flag, d), d)
258
259                 if data.getVarFlag(calledvar, "python", d):
260                     data.setVar(var, "\toe.build.exec_func('" + calledvar + "', d)\n", d)
261                 else:
262                     data.setVar(var, "\t" + calledvar + "\n", d)
263                 data.setVarFlag(var, 'export_func', '1', d)
264
265         return
266
267     m = __addtask_regexp__.match(s)
268     if m:
269         func = m.group("func")
270         before = m.group("before")
271         after = m.group("after")
272         if func is None:
273             return
274         var = "do_" + func
275
276         data.setVarFlag(var, "task", 1, d)
277
278         if after is not None:
279 #           set up deps for function
280             data.setVarFlag(var, "deps", after.split(), d)
281         if before is not None:
282 #           set up things that depend on this func
283             data.setVarFlag(var, "postdeps", before.split(), d)
284         return
285
286     m = __addhandler_regexp__.match(s)
287     if m:
288         fns = m.group(1)
289         hs = __word__.findall(fns)
290         for h in hs:
291             data.setVarFlag(h, "handler", 1, d)
292         return
293
294     m = __inherit_regexp__.match(s)
295     if m:
296
297         files = m.group(1)
298         n = __word__.findall(files)
299         inherit(n, d)
300         return
301
302     from oe.parse import ConfHandler
303     return ConfHandler.feeder(lineno, s, fn, d)
304
305 __pkgsplit_cache__={}
306 def vars_from_file(mypkg, d):
307     if not mypkg:
308         return (None, None, None)
309     if mypkg in __pkgsplit_cache__:
310         return __pkgsplit_cache__[mypkg]
311
312     myfile = os.path.splitext(os.path.basename(mypkg))
313     parts = myfile[0].split('_')
314     __pkgsplit_cache__[mypkg] = parts
315     exp = 3 - len(parts)
316     tmplist = []
317     while exp != 0:
318         exp -= 1
319         tmplist.append(None)
320     parts.extend(tmplist)
321     return parts
322
323 def set_additional_vars(file, d, include):
324     """Deduce rest of variables, e.g. ${A} out of ${SRC_URI}"""
325
326     debug(2,"OE %s: set_additional_vars" % file)
327
328     src_uri = data.getVar('SRC_URI', d)
329     if not src_uri:
330         return
331     src_uri = data.expand(src_uri, d)
332
333     a = data.getVar('A', d)
334     if a:
335         a = data.expand(a, d).split()
336     else:
337         a = []
338
339     from oe import fetch
340     try:
341         fetch.init(src_uri.split())
342     except fetch.NoMethodError:
343         pass
344     except oe.MalformedUrl,e:
345         raise ParseError("Unable to generate local paths for SRC_URI due to malformed uri: %s" % e)
346
347     a += fetch.localpaths(d)
348     del fetch
349     data.setVar('A', " ".join(a), d)
350
351
352 # Add us to the handlers list
353 from oe.parse import handlers
354 handlers.append({'supports': supports, 'handle': handle, 'init': init})
355 del handlers