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