summaryrefslogtreecommitdiffstats
path: root/bitbake-dev/lib/bb/data.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake-dev/lib/bb/data.py')
-rw-r--r--bitbake-dev/lib/bb/data.py570
1 files changed, 570 insertions, 0 deletions
diff --git a/bitbake-dev/lib/bb/data.py b/bitbake-dev/lib/bb/data.py
new file mode 100644
index 0000000000..54b2615afb
--- /dev/null
+++ b/bitbake-dev/lib/bb/data.py
@@ -0,0 +1,570 @@
1# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3"""
4BitBake 'Data' implementations
5
6Functions for interacting with the data structure used by the
7BitBake build tools.
8
9The expandData and update_data are the most expensive
10operations. At night the cookie monster came by and
11suggested 'give me cookies on setting the variables and
12things will work out'. Taking this suggestion into account
13applying the skills from the not yet passed 'Entwurf und
14Analyse von Algorithmen' lecture and the cookie
15monster seems to be right. We will track setVar more carefully
16to have faster update_data and expandKeys operations.
17
18This is a treade-off between speed and memory again but
19the speed is more critical here.
20"""
21
22# Copyright (C) 2003, 2004 Chris Larson
23# Copyright (C) 2005 Holger Hans Peter Freyther
24#
25# This program is free software; you can redistribute it and/or modify
26# it under the terms of the GNU General Public License version 2 as
27# published by the Free Software Foundation.
28#
29# This program is distributed in the hope that it will be useful,
30# but WITHOUT ANY WARRANTY; without even the implied warranty of
31# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32# GNU General Public License for more details.
33#
34# You should have received a copy of the GNU General Public License along
35# with this program; if not, write to the Free Software Foundation, Inc.,
36# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
37#
38#Based on functions from the base bb module, Copyright 2003 Holger Schurig
39
40import sys, os, re, time, types
41if sys.argv[0][-5:] == "pydoc":
42 path = os.path.dirname(os.path.dirname(sys.argv[1]))
43else:
44 path = os.path.dirname(os.path.dirname(sys.argv[0]))
45sys.path.insert(0,path)
46
47from bb import data_smart
48import bb
49
50_dict_type = data_smart.DataSmart
51
52def init():
53 return _dict_type()
54
55def init_db(parent = None):
56 if parent:
57 return parent.createCopy()
58 else:
59 return _dict_type()
60
61def createCopy(source):
62 """Link the source set to the destination
63 If one does not find the value in the destination set,
64 search will go on to the source set to get the value.
65 Value from source are copy-on-write. i.e. any try to
66 modify one of them will end up putting the modified value
67 in the destination set.
68 """
69 return source.createCopy()
70
71def initVar(var, d):
72 """Non-destructive var init for data structure"""
73 d.initVar(var)
74
75
76def setVar(var, value, d):
77 """Set a variable to a given value
78
79 Example:
80 >>> d = init()
81 >>> setVar('TEST', 'testcontents', d)
82 >>> print getVar('TEST', d)
83 testcontents
84 """
85 d.setVar(var,value)
86
87
88def getVar(var, d, exp = 0):
89 """Gets the value of a variable
90
91 Example:
92 >>> d = init()
93 >>> setVar('TEST', 'testcontents', d)
94 >>> print getVar('TEST', d)
95 testcontents
96 """
97 return d.getVar(var,exp)
98
99
100def renameVar(key, newkey, d):
101 """Renames a variable from key to newkey
102
103 Example:
104 >>> d = init()
105 >>> setVar('TEST', 'testcontents', d)
106 >>> renameVar('TEST', 'TEST2', d)
107 >>> print getVar('TEST2', d)
108 testcontents
109 """
110 d.renameVar(key, newkey)
111
112def delVar(var, d):
113 """Removes a variable from the data set
114
115 Example:
116 >>> d = init()
117 >>> setVar('TEST', 'testcontents', d)
118 >>> print getVar('TEST', d)
119 testcontents
120 >>> delVar('TEST', d)
121 >>> print getVar('TEST', d)
122 None
123 """
124 d.delVar(var)
125
126def setVarFlag(var, flag, flagvalue, d):
127 """Set a flag for a given variable to a given value
128
129 Example:
130 >>> d = init()
131 >>> setVarFlag('TEST', 'python', 1, d)
132 >>> print getVarFlag('TEST', 'python', d)
133 1
134 """
135 d.setVarFlag(var,flag,flagvalue)
136
137def getVarFlag(var, flag, d):
138 """Gets given flag from given var
139
140 Example:
141 >>> d = init()
142 >>> setVarFlag('TEST', 'python', 1, d)
143 >>> print getVarFlag('TEST', 'python', d)
144 1
145 """
146 return d.getVarFlag(var,flag)
147
148def delVarFlag(var, flag, d):
149 """Removes a given flag from the variable's flags
150
151 Example:
152 >>> d = init()
153 >>> setVarFlag('TEST', 'testflag', 1, d)
154 >>> print getVarFlag('TEST', 'testflag', d)
155 1
156 >>> delVarFlag('TEST', 'testflag', d)
157 >>> print getVarFlag('TEST', 'testflag', d)
158 None
159
160 """
161 d.delVarFlag(var,flag)
162
163def setVarFlags(var, flags, d):
164 """Set the flags for a given variable
165
166 Note:
167 setVarFlags will not clear previous
168 flags. Think of this method as
169 addVarFlags
170
171 Example:
172 >>> d = init()
173 >>> myflags = {}
174 >>> myflags['test'] = 'blah'
175 >>> setVarFlags('TEST', myflags, d)
176 >>> print getVarFlag('TEST', 'test', d)
177 blah
178 """
179 d.setVarFlags(var,flags)
180
181def getVarFlags(var, d):
182 """Gets a variable's flags
183
184 Example:
185 >>> d = init()
186 >>> setVarFlag('TEST', 'test', 'blah', d)
187 >>> print getVarFlags('TEST', d)['test']
188 blah
189 """
190 return d.getVarFlags(var)
191
192def delVarFlags(var, d):
193 """Removes a variable's flags
194
195 Example:
196 >>> data = init()
197 >>> setVarFlag('TEST', 'testflag', 1, data)
198 >>> print getVarFlag('TEST', 'testflag', data)
199 1
200 >>> delVarFlags('TEST', data)
201 >>> print getVarFlags('TEST', data)
202 None
203
204 """
205 d.delVarFlags(var)
206
207def keys(d):
208 """Return a list of keys in d
209
210 Example:
211 >>> d = init()
212 >>> setVar('TEST', 1, d)
213 >>> setVar('MOO' , 2, d)
214 >>> setVarFlag('TEST', 'test', 1, d)
215 >>> keys(d)
216 ['TEST', 'MOO']
217 """
218 return d.keys()
219
220def getData(d):
221 """Returns the data object used"""
222 return d
223
224def setData(newData, d):
225 """Sets the data object to the supplied value"""
226 d = newData
227
228
229##
230## Cookie Monsters' query functions
231##
232def _get_override_vars(d, override):
233 """
234 Internal!!!
235
236 Get the Names of Variables that have a specific
237 override. This function returns a iterable
238 Set or an empty list
239 """
240 return []
241
242def _get_var_flags_triple(d):
243 """
244 Internal!!!
245
246 """
247 return []
248
249__expand_var_regexp__ = re.compile(r"\${[^{}]+}")
250__expand_python_regexp__ = re.compile(r"\${@.+?}")
251
252def expand(s, d, varname = None):
253 """Variable expansion using the data store.
254
255 Example:
256 Standard expansion:
257 >>> d = init()
258 >>> setVar('A', 'sshd', d)
259 >>> print expand('/usr/bin/${A}', d)
260 /usr/bin/sshd
261
262 Python expansion:
263 >>> d = init()
264 >>> print expand('result: ${@37 * 72}', d)
265 result: 2664
266
267 Shell expansion:
268 >>> d = init()
269 >>> print expand('${TARGET_MOO}', d)
270 ${TARGET_MOO}
271 >>> setVar('TARGET_MOO', 'yupp', d)
272 >>> print expand('${TARGET_MOO}',d)
273 yupp
274 >>> setVar('SRC_URI', 'http://somebug.${TARGET_MOO}', d)
275 >>> delVar('TARGET_MOO', d)
276 >>> print expand('${SRC_URI}', d)
277 http://somebug.${TARGET_MOO}
278 """
279 return d.expand(s, varname)
280
281def expandKeys(alterdata, readdata = None):
282 if readdata == None:
283 readdata = alterdata
284
285 todolist = {}
286 for key in keys(alterdata):
287 if not '${' in key:
288 continue
289
290 ekey = expand(key, readdata)
291 if key == ekey:
292 continue
293 todolist[key] = ekey
294
295 # These two for loops are split for performance to maximise the
296 # usefulness of the expand cache
297
298 for key in todolist:
299 ekey = todolist[key]
300 renameVar(key, ekey, alterdata)
301
302def expandData(alterdata, readdata = None):
303 """For each variable in alterdata, expand it, and update the var contents.
304 Replacements use data from readdata.
305
306 Example:
307 >>> a=init()
308 >>> b=init()
309 >>> setVar("dlmsg", "dl_dir is ${DL_DIR}", a)
310 >>> setVar("DL_DIR", "/path/to/whatever", b)
311 >>> expandData(a, b)
312 >>> print getVar("dlmsg", a)
313 dl_dir is /path/to/whatever
314 """
315 if readdata == None:
316 readdata = alterdata
317
318 for key in keys(alterdata):
319 val = getVar(key, alterdata)
320 if type(val) is not types.StringType:
321 continue
322 expanded = expand(val, readdata)
323# print "key is %s, val is %s, expanded is %s" % (key, val, expanded)
324 if val != expanded:
325 setVar(key, expanded, alterdata)
326
327import os
328
329def inheritFromOS(d):
330 """Inherit variables from the environment."""
331# fakeroot needs to be able to set these
332 non_inherit_vars = [ "LD_LIBRARY_PATH", "LD_PRELOAD" ]
333 for s in os.environ.keys():
334 if not s in non_inherit_vars:
335 try:
336 setVar(s, os.environ[s], d)
337 setVarFlag(s, 'matchesenv', '1', d)
338 except TypeError:
339 pass
340
341import sys
342
343def emit_var(var, o=sys.__stdout__, d = init(), all=False):
344 """Emit a variable to be sourced by a shell."""
345 if getVarFlag(var, "python", d):
346 return 0
347
348 export = getVarFlag(var, "export", d)
349 unexport = getVarFlag(var, "unexport", d)
350 func = getVarFlag(var, "func", d)
351 if not all and not export and not unexport and not func:
352 return 0
353
354 try:
355 if all:
356 oval = getVar(var, d, 0)
357 val = getVar(var, d, 1)
358 except KeyboardInterrupt:
359 raise
360 except:
361 excname = str(sys.exc_info()[0])
362 if excname == "bb.build.FuncFailed":
363 raise
364 o.write('# expansion of %s threw %s\n' % (var, excname))
365 return 0
366
367 if all:
368 o.write('# %s=%s\n' % (var, oval))
369
370 if type(val) is not types.StringType:
371 return 0
372
373 if (var.find("-") != -1 or var.find(".") != -1 or var.find('{') != -1 or var.find('}') != -1 or var.find('+') != -1) and not all:
374 return 0
375
376 varExpanded = expand(var, d)
377
378 if unexport:
379 o.write('unset %s\n' % varExpanded)
380 return 1
381
382 if getVarFlag(var, 'matchesenv', d):
383 return 0
384
385 val.rstrip()
386 if not val:
387 return 0
388
389 if func:
390 # NOTE: should probably check for unbalanced {} within the var
391 o.write("%s() {\n%s\n}\n" % (varExpanded, val))
392 return 1
393
394 if export:
395 o.write('export ')
396
397 # if we're going to output this within doublequotes,
398 # to a shell, we need to escape the quotes in the var
399 alter = re.sub('"', '\\"', val.strip())
400 o.write('%s="%s"\n' % (varExpanded, alter))
401 return 1
402
403
404def emit_env(o=sys.__stdout__, d = init(), all=False):
405 """Emits all items in the data store in a format such that it can be sourced by a shell."""
406
407 env = keys(d)
408
409 for e in env:
410 if getVarFlag(e, "func", d):
411 continue
412 emit_var(e, o, d, all) and o.write('\n')
413
414 for e in env:
415 if not getVarFlag(e, "func", d):
416 continue
417 emit_var(e, o, d) and o.write('\n')
418
419def update_data(d):
420 """Modifies the environment vars according to local overrides and commands.
421 Examples:
422 Appending to a variable:
423 >>> d = init()
424 >>> setVar('TEST', 'this is a', d)
425 >>> setVar('TEST_append', ' test', d)
426 >>> setVar('TEST_append', ' of the emergency broadcast system.', d)
427 >>> update_data(d)
428 >>> print getVar('TEST', d)
429 this is a test of the emergency broadcast system.
430
431 Prepending to a variable:
432 >>> setVar('TEST', 'virtual/libc', d)
433 >>> setVar('TEST_prepend', 'virtual/tmake ', d)
434 >>> setVar('TEST_prepend', 'virtual/patcher ', d)
435 >>> update_data(d)
436 >>> print getVar('TEST', d)
437 virtual/patcher virtual/tmake virtual/libc
438
439 Overrides:
440 >>> setVar('TEST_arm', 'target', d)
441 >>> setVar('TEST_ramses', 'machine', d)
442 >>> setVar('TEST_local', 'local', d)
443 >>> setVar('OVERRIDES', 'arm', d)
444
445 >>> setVar('TEST', 'original', d)
446 >>> update_data(d)
447 >>> print getVar('TEST', d)
448 target
449
450 >>> setVar('OVERRIDES', 'arm:ramses:local', d)
451 >>> setVar('TEST', 'original', d)
452 >>> update_data(d)
453 >>> print getVar('TEST', d)
454 local
455
456 CopyMonster:
457 >>> e = d.createCopy()
458 >>> setVar('TEST_foo', 'foo', e)
459 >>> update_data(e)
460 >>> print getVar('TEST', e)
461 local
462
463 >>> setVar('OVERRIDES', 'arm:ramses:local:foo', e)
464 >>> update_data(e)
465 >>> print getVar('TEST', e)
466 foo
467
468 >>> f = d.createCopy()
469 >>> setVar('TEST_moo', 'something', f)
470 >>> setVar('OVERRIDES', 'moo:arm:ramses:local:foo', e)
471 >>> update_data(e)
472 >>> print getVar('TEST', e)
473 foo
474
475
476 >>> h = init()
477 >>> setVar('SRC_URI', 'file://append.foo;patch=1 ', h)
478 >>> g = h.createCopy()
479 >>> setVar('SRC_URI_append_arm', 'file://other.foo;patch=1', g)
480 >>> setVar('OVERRIDES', 'arm:moo', g)
481 >>> update_data(g)
482 >>> print getVar('SRC_URI', g)
483 file://append.foo;patch=1 file://other.foo;patch=1
484
485 """
486 bb.msg.debug(2, bb.msg.domain.Data, "update_data()")
487
488 # now ask the cookie monster for help
489 #print "Cookie Monster"
490 #print "Append/Prepend %s" % d._special_values
491 #print "Overrides %s" % d._seen_overrides
492
493 overrides = (getVar('OVERRIDES', d, 1) or "").split(':') or []
494
495 #
496 # Well let us see what breaks here. We used to iterate
497 # over each variable and apply the override and then
498 # do the line expanding.
499 # If we have bad luck - which we will have - the keys
500 # where in some order that is so important for this
501 # method which we don't have anymore.
502 # Anyway we will fix that and write test cases this
503 # time.
504
505 #
506 # First we apply all overrides
507 # Then we will handle _append and _prepend
508 #
509
510 for o in overrides:
511 # calculate '_'+override
512 l = len(o)+1
513
514 # see if one should even try
515 if not d._seen_overrides.has_key(o):
516 continue
517
518 vars = d._seen_overrides[o]
519 for var in vars:
520 name = var[:-l]
521 try:
522 d[name] = d[var]
523 except:
524 bb.msg.note(1, bb.msg.domain.Data, "Untracked delVar")
525
526 # now on to the appends and prepends
527 if d._special_values.has_key('_append'):
528 appends = d._special_values['_append'] or []
529 for append in appends:
530 for (a, o) in getVarFlag(append, '_append', d) or []:
531 # maybe the OVERRIDE was not yet added so keep the append
532 if (o and o in overrides) or not o:
533 delVarFlag(append, '_append', d)
534 if o and not o in overrides:
535 continue
536
537 sval = getVar(append,d) or ""
538 sval+=a
539 setVar(append, sval, d)
540
541
542 if d._special_values.has_key('_prepend'):
543 prepends = d._special_values['_prepend'] or []
544
545 for prepend in prepends:
546 for (a, o) in getVarFlag(prepend, '_prepend', d) or []:
547 # maybe the OVERRIDE was not yet added so keep the prepend
548 if (o and o in overrides) or not o:
549 delVarFlag(prepend, '_prepend', d)
550 if o and not o in overrides:
551 continue
552
553 sval = a + (getVar(prepend,d) or "")
554 setVar(prepend, sval, d)
555
556
557def inherits_class(klass, d):
558 val = getVar('__inherit_cache', d) or []
559 if os.path.join('classes', '%s.bbclass' % klass) in val:
560 return True
561 return False
562
563def _test():
564 """Start a doctest run on this module"""
565 import doctest
566 from bb import data
567 doctest.testmod(data)
568
569if __name__ == "__main__":
570 _test()