2 # ex:ts=4:sw=4:sts=4:et
3 # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
5 BitBake 'Data' implementations
7 Functions for interacting with the data structure used by the
10 Copyright (C) 2003, 2004 Chris Larson
11 Copyright (C) 2005 Holger Hans Peter Freyther
13 This program is free software; you can redistribute it and/or modify it under
14 the terms of the GNU General Public License as published by the Free Software
15 Foundation; either version 2 of the License, or (at your option) any later
18 This program is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License along with
23 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
24 Place, Suite 330, Boston, MA 02111-1307 USA.
26 Based on functions from the base bb module, Copyright 2003 Holger Schurig
29 import sys, os, re, time, types
30 if sys.argv[0][-5:] == "pydoc":
31 path = os.path.dirname(os.path.dirname(sys.argv[1]))
33 path = os.path.dirname(os.path.dirname(sys.argv[0]))
36 from bb import note, debug, data_dict
38 _dict_type = data_dict.DataDict
39 _dict_p_type = data_dict.DataDictPackage
45 def init_db(cache,name,clean,parent = None):
46 return _dict_p_type(cache,name,clean,parent)
48 def init_db_mtime(cache,cache_bbfile):
49 return _dict_p_type.mtime(cache,cache_bbfile)
53 def createCopy(source):
54 """Link the source set to the destination
55 If one does not find the value in the destination set,
56 search will go on to the source set to get the value.
57 Value from source are copy-on-write. i.e. any try to
58 modify one of them will end up putting the modified value
59 in the destination set.
61 return source.createCopy()
63 def initVar(var, d = _data_dict):
64 """Non-destructive var init for data structure"""
68 def setVar(var, value, d = _data_dict):
69 """Set a variable to a given value
72 >>> setVar('TEST', 'testcontents')
73 >>> print getVar('TEST')
79 def getVar(var, d = _data_dict, exp = 0):
80 """Gets the value of a variable
83 >>> setVar('TEST', 'testcontents')
84 >>> print getVar('TEST')
87 return d.getVar(var,exp)
89 def delVar(var, d = _data_dict):
90 """Removes a variable from the data set
93 >>> setVar('TEST', 'testcontents')
94 >>> print getVar('TEST')
97 >>> print getVar('TEST')
102 def setVarFlag(var, flag, flagvalue, d = _data_dict):
103 """Set a flag for a given variable to a given value
106 >>> setVarFlag('TEST', 'python', 1)
107 >>> print getVarFlag('TEST', 'python')
110 d.setVarFlag(var,flag,flagvalue)
112 def getVarFlag(var, flag, d = _data_dict):
113 """Gets given flag from given var
116 >>> setVarFlag('TEST', 'python', 1)
117 >>> print getVarFlag('TEST', 'python')
120 return d.getVarFlag(var,flag)
122 def delVarFlag(var, flag, d = _data_dict):
123 """Removes a given flag from the variable's flags
126 >>> setVarFlag('TEST', 'testflag', 1)
127 >>> print getVarFlag('TEST', 'testflag')
129 >>> delVarFlag('TEST', 'testflag')
130 >>> print getVarFlag('TEST', 'testflag')
134 d.delVarFlag(var,flag)
136 def setVarFlags(var, flags, d = _data_dict):
137 """Set the flags for a given variable
141 >>> myflags['test'] = 'blah'
142 >>> setVarFlags('TEST', myflags)
143 >>> print getVarFlag('TEST', 'test')
146 d.setVarFlags(var,flags)
148 def getVarFlags(var, d = _data_dict):
149 """Gets a variable's flags
152 >>> setVarFlag('TEST', 'test', 'blah')
153 >>> print getVarFlags('TEST')['test']
156 return d.getVarFlags(var)
158 def delVarFlags(var, d = _data_dict):
159 """Removes a variable's flags
163 >>> setVarFlag('TEST', 'testflag', 1, data)
164 >>> print getVarFlag('TEST', 'testflag', data)
166 >>> delVarFlags('TEST', data)
167 >>> print getVarFlags('TEST', data)
173 def keys(d = _data_dict):
174 """Return a list of keys in d
178 >>> setVar('TEST', 1, d)
179 >>> setVar('MOO' , 2, d)
180 >>> setVarFlag('TEST', 'test', 1, d)
186 def getData(d = _data_dict):
187 """Returns the data object used"""
190 def setData(newData, d = _data_dict):
191 """Sets the data object to the supplied value"""
194 __expand_var_regexp__ = re.compile(r"\${[^{}]+}")
195 __expand_python_regexp__ = re.compile(r"\${@.+?}")
197 def expand(s, d = _data_dict, varname = None):
198 """Variable expansion using the data store.
202 >>> setVar('A', 'sshd')
203 >>> print expand('/usr/bin/${A}')
207 >>> print expand('result: ${@37 * 72}')
211 key = match.group()[2:-1]
214 raise Exception("variable %s references itself!" % varname)
215 var = getVar(key, d, 1)
221 def python_sub(match):
223 code = match.group()[3:-1]
226 if type(s) == types.IntType: s = str(s)
229 if type(s) is not types.StringType: # sanity check
232 while s.find('$') != -1:
235 s = __expand_var_regexp__.sub(var_sub, s)
236 s = __expand_python_regexp__.sub(python_sub, s)
238 if type(s) is not types.StringType: # sanity check
240 bb.error('expansion of %s returned non-string %s' % (olds, s))
241 except KeyboardInterrupt:
244 note("%s:%s while evaluating:\n%s" % (sys.exc_info()[0], sys.exc_info()[1], s))
248 def expandKeys(alterdata = _data_dict, readdata = None):
252 for key in keys(alterdata):
253 ekey = expand(key, readdata)
256 val = getVar(key, alterdata)
260 # setVarFlags(ekey, copy.copy(getVarFlags(key, readdata)), alterdata)
261 setVar(ekey, val, alterdata)
263 for i in ('_append', '_prepend', '_delete'):
264 dest = getVarFlag(ekey, i, alterdata) or []
265 src = getVarFlag(key, i, readdata) or []
267 setVarFlag(ekey, i, dest, alterdata)
269 delVar(key, alterdata)
271 def expandData(alterdata = _data_dict, readdata = None):
272 """For each variable in alterdata, expand it, and update the var contents.
273 Replacements use data from readdata.
278 >>> setVar("dlmsg", "dl_dir is ${DL_DIR}", a)
279 >>> setVar("DL_DIR", "/path/to/whatever", b)
281 >>> print getVar("dlmsg", a)
282 dl_dir is /path/to/whatever
287 for key in keys(alterdata):
288 val = getVar(key, alterdata)
289 if type(val) is not types.StringType:
291 expanded = expand(val, readdata)
292 # print "key is %s, val is %s, expanded is %s" % (key, val, expanded)
294 setVar(key, expanded, alterdata)
298 def inheritFromOS(d = _data_dict):
299 """Inherit variables from the environment."""
300 # fakeroot needs to be able to set these
301 non_inherit_vars = [ "LD_LIBRARY_PATH", "LD_PRELOAD" ]
302 for s in os.environ.keys():
303 if not s in non_inherit_vars:
305 setVar(s, os.environ[s], d)
306 setVarFlag(s, 'matchesenv', '1', d)
312 def emit_var(var, o=sys.__stdout__, d = _data_dict, all=False):
313 """Emit a variable to be sourced by a shell."""
314 if getVarFlag(var, "python", d):
319 oval = getVar(var, d, 0)
320 val = getVar(var, d, 1)
321 except KeyboardInterrupt:
324 excname = str(sys.exc_info()[0])
325 if excname == "bb.build.FuncFailed":
327 o.write('# expansion of %s threw %s\n' % (var, excname))
331 o.write('# %s=%s\n' % (var, oval))
333 if type(val) is not types.StringType:
336 if getVarFlag(var, 'matchesenv', d):
339 if (var.find("-") != -1 or var.find(".") != -1 or var.find('{') != -1 or var.find('}') != -1 or var.find('+') != -1) and not all:
346 if getVarFlag(var, "func", d):
347 # NOTE: should probably check for unbalanced {} within the var
348 o.write("%s() {\n%s\n}\n" % (var, val))
350 if getVarFlag(var, "export", d):
355 # if we're going to output this within doublequotes,
356 # to a shell, we need to escape the quotes in the var
357 alter = re.sub('"', '\\"', val.strip())
358 o.write('%s="%s"\n' % (var, alter))
362 def emit_env(o=sys.__stdout__, d = _data_dict, all=False):
363 """Emits all items in the data store in a format such that it can be sourced by a shell."""
368 if getVarFlag(e, "func", d):
370 emit_var(e, o, d, all) and o.write('\n')
373 if not getVarFlag(e, "func", d):
375 emit_var(e, o, d) and o.write('\n')
377 def update_data(d = _data_dict):
378 """Modifies the environment vars according to local overrides and commands.
380 Appending to a variable:
381 >>> setVar('TEST', 'this is a')
382 >>> setVar('TEST_append', ' test')
383 >>> setVar('TEST_append', ' of the emergency broadcast system.')
385 >>> print getVar('TEST')
386 this is a test of the emergency broadcast system.
388 Prepending to a variable:
389 >>> setVar('TEST', 'virtual/libc')
390 >>> setVar('TEST_prepend', 'virtual/tmake ')
391 >>> setVar('TEST_prepend', 'virtual/patcher ')
393 >>> print getVar('TEST')
394 virtual/patcher virtual/tmake virtual/libc
397 >>> setVar('TEST_arm', 'target')
398 >>> setVar('TEST_ramses', 'machine')
399 >>> setVar('TEST_local', 'local')
400 >>> setVar('OVERRIDES', 'arm')
402 >>> setVar('TEST', 'original')
404 >>> print getVar('TEST')
407 >>> setVar('OVERRIDES', 'arm:ramses:local')
408 >>> setVar('TEST', 'original')
410 >>> print getVar('TEST')
414 debug(2, "update_data()")
416 # can't do delete env[...] while iterating over the dictionary, so remember them
418 overrides = (getVar('OVERRIDES', d, 1) or "").split(':') or []
420 def applyOverrides(var, d = _data_dict):
422 debug(1, "OVERRIDES not defined, nothing to do")
426 if var.endswith("_" + o):
433 sval = getVar(s, d) or ""
435 # Handle line appends:
436 for (a, o) in getVarFlag(s, '_append', d) or []:
437 # maybe the OVERRIDE was not yet added so keep the append
438 if (o and o in overrides) or not o:
439 delVarFlag(s, '_append', d)
441 if not o in overrides:
446 # Handle line prepends
447 for (a, o) in getVarFlag(s, '_prepend', d) or []:
448 # maybe the OVERRIDE was not yet added so keep the append
449 if (o and o in overrides) or not o:
450 delVarFlag(s, '_prepend', d)
452 if not o in overrides:
457 # Handle line deletions
459 nameval = getVar(name, d)
464 pattern = nameval.replace('\n','').strip()
465 for line in sval.split('\n'):
466 if line.find(pattern) == -1:
467 new = new + '\n' + line
471 # delete all environment vars no longer needed
475 def inherits_class(klass, d):
476 val = getVar('__inherit_cache', d) or ""
477 if os.path.join('classes', '%s.bbclass' % klass) in val.split():
482 """Start a doctest run on this module"""
485 doctest.testmod(data)
487 if __name__ == "__main__":