data.py 15 KB

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