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