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