summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/parse/parse_py/BBHandler.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/parse/parse_py/BBHandler.py')
-rw-r--r--bitbake/lib/bb/parse/parse_py/BBHandler.py378
1 files changed, 378 insertions, 0 deletions
diff --git a/bitbake/lib/bb/parse/parse_py/BBHandler.py b/bitbake/lib/bb/parse/parse_py/BBHandler.py
new file mode 100644
index 0000000000..fac3e85b36
--- /dev/null
+++ b/bitbake/lib/bb/parse/parse_py/BBHandler.py
@@ -0,0 +1,378 @@
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 .bb files
5
6 Reads a .bb file and obtains its metadata
7
8 Copyright (C) 2003, 2004 Chris Larson
9 Copyright (C) 2003, 2004 Phil Blundell
10
11 This program is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free Software
13 Foundation; either version 2 of the License, or (at your option) any later
14 version.
15
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22 Place, Suite 330, Boston, MA 02111-1307 USA."""
23
24import re, bb, os, sys
25import bb.fetch, bb.build
26from bb import debug, data, fetch, fatal
27
28from ConfHandler import include, localpath, obtain, init
29from bb.parse import ParseError
30
31__func_start_regexp__ = re.compile( r"(((?P<py>python)|(?P<fr>fakeroot))\s*)*(?P<func>[\w\.\-\+\{\}\$]+)?\s*\(\s*\)\s*{$" )
32__inherit_regexp__ = re.compile( r"inherit\s+(.+)" )
33__export_func_regexp__ = re.compile( r"EXPORT_FUNCTIONS\s+(.+)" )
34__addtask_regexp__ = re.compile("addtask\s+(?P<func>\w+)\s*((before\s*(?P<before>((.*(?=after))|(.*))))|(after\s*(?P<after>((.*(?=before))|(.*)))))*")
35__addhandler_regexp__ = re.compile( r"addhandler\s+(.+)" )
36__def_regexp__ = re.compile( r"def\s+(\w+).*:" )
37__python_func_regexp__ = re.compile( r"(\s+.*)|(^$)" )
38__word__ = re.compile(r"\S+")
39
40__infunc__ = ""
41__inpython__ = False
42__body__ = []
43__bbpath_found__ = 0
44__classname__ = ""
45classes = [ None, ]
46
47def supports(fn, d):
48 localfn = localpath(fn, d)
49 return localfn[-3:] == ".bb" or localfn[-8:] == ".bbclass" or localfn[-4:] == ".inc"
50
51def inherit(files, d):
52 __inherit_cache = data.getVar('__inherit_cache', d) or ""
53 fn = ""
54 lineno = 0
55 for f in files:
56 file = data.expand(f, d)
57 if file[0] != "/" and file[-8:] != ".bbclass":
58 file = os.path.join('classes', '%s.bbclass' % file)
59
60 if not file in __inherit_cache.split():
61 debug(2, "BB %s:%d: inheriting %s" % (fn, lineno, file))
62 __inherit_cache += " %s" % file
63 include(fn, file, d)
64 data.setVar('__inherit_cache', __inherit_cache, d)
65
66
67def handle(fn, d, include = 0):
68 global __func_start_regexp__, __inherit_regexp__, __export_func_regexp__, __addtask_regexp__, __addhandler_regexp__, __infunc__, __body__, __bbpath_found__, __residue__
69 __body__ = []
70 __bbpath_found__ = 0
71 __infunc__ = ""
72 __classname__ = ""
73 __residue__ = []
74
75 if include == 0:
76 debug(2, "BB " + fn + ": handle(data)")
77 else:
78 debug(2, "BB " + fn + ": handle(data, include)")
79
80 (root, ext) = os.path.splitext(os.path.basename(fn))
81 init(d)
82
83 if ext == ".bbclass":
84 __classname__ = root
85 classes.append(__classname__)
86
87 if include != 0:
88 oldfile = data.getVar('FILE', d)
89 else:
90 oldfile = None
91
92 fn = obtain(fn, d)
93 bbpath = (data.getVar('BBPATH', d, 1) or '').split(':')
94 if not os.path.isabs(fn):
95 f = None
96 for p in bbpath:
97 p = data.expand(p, d)
98 j = os.path.join(p, fn)
99 if os.access(j, os.R_OK):
100 abs_fn = j
101 f = open(j, 'r')
102 break
103 if f is None:
104 raise IOError("file not found")
105 else:
106 f = open(fn,'r')
107 abs_fn = fn
108
109 if ext != ".bbclass":
110 bbpath.insert(0, os.path.dirname(abs_fn))
111 data.setVar('BBPATH', ":".join(bbpath), d)
112
113 if include:
114 bb.parse.mark_dependency(d, abs_fn)
115
116 if ext != ".bbclass":
117 data.setVar('FILE', fn, d)
118 i = (data.getVar("INHERIT", d, 1) or "").split()
119 if not "base" in i and __classname__ != "base":
120 i[0:0] = ["base"]
121 inherit(i, d)
122
123 lineno = 0
124 while 1:
125 lineno = lineno + 1
126 s = f.readline()
127 if not s: break
128 s = s.rstrip()
129 feeder(lineno, s, fn, d)
130 if __inpython__:
131 # add a blank line to close out any python definition
132 feeder(lineno + 1, "", fn, d)
133 if ext == ".bbclass":
134 classes.remove(__classname__)
135 else:
136 if include == 0:
137 data.expandKeys(d)
138 data.update_data(d)
139 anonqueue = data.getVar("__anonqueue", d, 1) or []
140 for anon in anonqueue:
141 data.setVar("__anonfunc", anon["content"], d)
142 data.setVarFlags("__anonfunc", anon["flags"], d)
143 from bb import build
144 try:
145 t = data.getVar('T', d)
146 data.setVar('T', '${TMPDIR}/', d)
147 build.exec_func("__anonfunc", d)
148 data.delVar('T', d)
149 if t:
150 data.setVar('T', t, d)
151 except Exception, e:
152 bb.debug(1, "executing anonymous function: %s" % e)
153 raise
154 data.delVar("__anonqueue", d)
155 data.delVar("__anonfunc", d)
156 set_additional_vars(fn, d, include)
157 data.update_data(d)
158
159 for var in data.keys(d):
160 if data.getVarFlag(var, 'handler', d):
161 bb.event.register(data.getVar(var, d))
162 continue
163
164 if not data.getVarFlag(var, 'task', d):
165 continue
166
167 deps = data.getVarFlag(var, 'deps', d) or []
168 postdeps = data.getVarFlag(var, 'postdeps', d) or []
169 bb.build.add_task(var, deps, d)
170 for p in postdeps:
171 pdeps = data.getVarFlag(p, 'deps', d) or []
172 pdeps.append(var)
173 data.setVarFlag(p, 'deps', pdeps, d)
174 bb.build.add_task(p, pdeps, d)
175 bbpath.pop(0)
176 if oldfile:
177 bb.data.setVar("FILE", oldfile, d)
178 return d
179
180def feeder(lineno, s, fn, d):
181 global __func_start_regexp__, __inherit_regexp__, __export_func_regexp__, __addtask_regexp__, __addhandler_regexp__, __def_regexp__, __python_func_regexp__, __inpython__,__infunc__, __body__, __bbpath_found__, classes, bb, __residue__
182 if __infunc__:
183 if s == '}':
184 __body__.append('')
185 data.setVar(__infunc__, '\n'.join(__body__), d)
186 data.setVarFlag(__infunc__, "func", 1, d)
187 if __infunc__ == "__anonymous":
188 anonqueue = bb.data.getVar("__anonqueue", d) or []
189 anonitem = {}
190 anonitem["content"] = bb.data.getVar("__anonymous", d)
191 anonitem["flags"] = bb.data.getVarFlags("__anonymous", d)
192 anonqueue.append(anonitem)
193 bb.data.setVar("__anonqueue", anonqueue, d)
194 bb.data.delVarFlags("__anonymous", d)
195 bb.data.delVar("__anonymous", d)
196 __infunc__ = ""
197 __body__ = []
198 else:
199 __body__.append(s)
200 return
201
202 if __inpython__:
203 m = __python_func_regexp__.match(s)
204 if m:
205 __body__.append(s)
206 return
207 else:
208 text = '\n'.join(__body__)
209 comp = compile(text, "<bb>", "exec")
210 exec comp in __builtins__
211 __body__ = []
212 __inpython__ = False
213 funcs = data.getVar('__functions__', d) or ""
214 data.setVar('__functions__', "%s\n%s" % (funcs, text), d)
215# fall through
216
217 if s == '' or s[0] == '#': return # skip comments and empty lines
218
219 if s[-1] == '\\':
220 __residue__.append(s[:-1])
221 return
222
223 s = "".join(__residue__) + s
224 __residue__ = []
225
226 m = __func_start_regexp__.match(s)
227 if m:
228 __infunc__ = m.group("func") or "__anonymous"
229 key = __infunc__
230 if data.getVar(key, d):
231# clean up old version of this piece of metadata, as its
232# flags could cause problems
233 data.setVarFlag(key, 'python', None, d)
234 data.setVarFlag(key, 'fakeroot', None, d)
235 if m.group("py") is not None:
236 data.setVarFlag(key, "python", "1", d)
237 else:
238 data.delVarFlag(key, "python", d)
239 if m.group("fr") is not None:
240 data.setVarFlag(key, "fakeroot", "1", d)
241 else:
242 data.delVarFlag(key, "fakeroot", d)
243 return
244
245 m = __def_regexp__.match(s)
246 if m:
247 __body__.append(s)
248 __inpython__ = True
249 return
250
251 m = __export_func_regexp__.match(s)
252 if m:
253 fns = m.group(1)
254 n = __word__.findall(fns)
255 for f in n:
256 allvars = []
257 allvars.append(f)
258 allvars.append(classes[-1] + "_" + f)
259
260 vars = [[ allvars[0], allvars[1] ]]
261 if len(classes) > 1 and classes[-2] is not None:
262 allvars.append(classes[-2] + "_" + f)
263 vars = []
264 vars.append([allvars[2], allvars[1]])
265 vars.append([allvars[0], allvars[2]])
266
267 for (var, calledvar) in vars:
268 if data.getVar(var, d) and not data.getVarFlag(var, 'export_func', d):
269 continue
270
271 if data.getVar(var, d):
272 data.setVarFlag(var, 'python', None, d)
273 data.setVarFlag(var, 'func', None, d)
274
275 for flag in [ "func", "python" ]:
276 if data.getVarFlag(calledvar, flag, d):
277 data.setVarFlag(var, flag, data.getVarFlag(calledvar, flag, d), d)
278 for flag in [ "dirs" ]:
279 if data.getVarFlag(var, flag, d):
280 data.setVarFlag(calledvar, flag, data.getVarFlag(var, flag, d), d)
281
282 if data.getVarFlag(calledvar, "python", d):
283 data.setVar(var, "\tbb.build.exec_func('" + calledvar + "', d)\n", d)
284 else:
285 data.setVar(var, "\t" + calledvar + "\n", d)
286 data.setVarFlag(var, 'export_func', '1', d)
287
288 return
289
290 m = __addtask_regexp__.match(s)
291 if m:
292 func = m.group("func")
293 before = m.group("before")
294 after = m.group("after")
295 if func is None:
296 return
297 var = "do_" + func
298
299 data.setVarFlag(var, "task", 1, d)
300
301 if after is not None:
302# set up deps for function
303 data.setVarFlag(var, "deps", after.split(), d)
304 if before is not None:
305# set up things that depend on this func
306 data.setVarFlag(var, "postdeps", before.split(), d)
307 return
308
309 m = __addhandler_regexp__.match(s)
310 if m:
311 fns = m.group(1)
312 hs = __word__.findall(fns)
313 for h in hs:
314 data.setVarFlag(h, "handler", 1, d)
315 return
316
317 m = __inherit_regexp__.match(s)
318 if m:
319
320 files = m.group(1)
321 n = __word__.findall(files)
322 inherit(n, d)
323 return
324
325 from bb.parse import ConfHandler
326 return ConfHandler.feeder(lineno, s, fn, d)
327
328__pkgsplit_cache__={}
329def vars_from_file(mypkg, d):
330 if not mypkg:
331 return (None, None, None)
332 if mypkg in __pkgsplit_cache__:
333 return __pkgsplit_cache__[mypkg]
334
335 myfile = os.path.splitext(os.path.basename(mypkg))
336 parts = myfile[0].split('_')
337 __pkgsplit_cache__[mypkg] = parts
338 exp = 3 - len(parts)
339 tmplist = []
340 while exp != 0:
341 exp -= 1
342 tmplist.append(None)
343 parts.extend(tmplist)
344 return parts
345
346def set_additional_vars(file, d, include):
347 """Deduce rest of variables, e.g. ${A} out of ${SRC_URI}"""
348
349 debug(2,"BB %s: set_additional_vars" % file)
350
351 src_uri = data.getVar('SRC_URI', d)
352 if not src_uri:
353 return
354 src_uri = data.expand(src_uri, d)
355
356 a = data.getVar('A', d)
357 if a:
358 a = data.expand(a, d).split()
359 else:
360 a = []
361
362 from bb import fetch
363 try:
364 fetch.init(src_uri.split(), d)
365 except fetch.NoMethodError:
366 pass
367 except bb.MalformedUrl,e:
368 raise ParseError("Unable to generate local paths for SRC_URI due to malformed uri: %s" % e)
369
370 a += fetch.localpaths(d)
371 del fetch
372 data.setVar('A', " ".join(a), d)
373
374
375# Add us to the handlers list
376from bb.parse import handlers
377handlers.append({'supports': supports, 'handle': handle, 'init': init})
378del handlers