data.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  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 renameVar(key, newkey, d):
  82. """Renames a variable from key to newkey
  83. Example:
  84. >>> d = init()
  85. >>> setVar('TEST', 'testcontents', d)
  86. >>> renameVar('TEST', 'TEST2', d)
  87. >>> print getVar('TEST2', d)
  88. testcontents
  89. """
  90. d.renameVar(key, newkey)
  91. def delVar(var, d):
  92. """Removes a variable from the data set
  93. Example:
  94. >>> d = init()
  95. >>> setVar('TEST', 'testcontents', d)
  96. >>> print getVar('TEST', d)
  97. testcontents
  98. >>> delVar('TEST', d)
  99. >>> print getVar('TEST', d)
  100. None
  101. """
  102. d.delVar(var)
  103. def setVarFlag(var, flag, flagvalue, d):
  104. """Set a flag for a given variable to a given value
  105. Example:
  106. >>> d = init()
  107. >>> setVarFlag('TEST', 'python', 1, d)
  108. >>> print getVarFlag('TEST', 'python', d)
  109. 1
  110. """
  111. d.setVarFlag(var,flag,flagvalue)
  112. def getVarFlag(var, flag, d):
  113. """Gets given flag from given var
  114. Example:
  115. >>> d = init()
  116. >>> setVarFlag('TEST', 'python', 1, d)
  117. >>> print getVarFlag('TEST', 'python', d)
  118. 1
  119. """
  120. return d.getVarFlag(var,flag)
  121. def delVarFlag(var, flag, d):
  122. """Removes a given flag from the variable's flags
  123. Example:
  124. >>> d = init()
  125. >>> setVarFlag('TEST', 'testflag', 1, d)
  126. >>> print getVarFlag('TEST', 'testflag', d)
  127. 1
  128. >>> delVarFlag('TEST', 'testflag', d)
  129. >>> print getVarFlag('TEST', 'testflag', d)
  130. None
  131. """
  132. d.delVarFlag(var,flag)
  133. def setVarFlags(var, flags, d):
  134. """Set the flags for a given variable
  135. Note:
  136. setVarFlags will not clear previous
  137. flags. Think of this method as
  138. addVarFlags
  139. Example:
  140. >>> d = init()
  141. >>> myflags = {}
  142. >>> myflags['test'] = 'blah'
  143. >>> setVarFlags('TEST', myflags, d)
  144. >>> print getVarFlag('TEST', 'test', d)
  145. blah
  146. """
  147. d.setVarFlags(var,flags)
  148. def getVarFlags(var, d):
  149. """Gets a variable's flags
  150. Example:
  151. >>> d = init()
  152. >>> setVarFlag('TEST', 'test', 'blah', d)
  153. >>> print getVarFlags('TEST', d)['test']
  154. blah
  155. """
  156. return d.getVarFlags(var)
  157. def delVarFlags(var, d):
  158. """Removes a variable's flags
  159. Example:
  160. >>> data = init()
  161. >>> setVarFlag('TEST', 'testflag', 1, data)
  162. >>> print getVarFlag('TEST', 'testflag', data)
  163. 1
  164. >>> delVarFlags('TEST', data)
  165. >>> print getVarFlags('TEST', data)
  166. None
  167. """
  168. d.delVarFlags(var)
  169. def keys(d):
  170. """Return a list of keys in d
  171. Example:
  172. >>> d = init()
  173. >>> setVar('TEST', 1, d)
  174. >>> setVar('MOO' , 2, d)
  175. >>> setVarFlag('TEST', 'test', 1, d)
  176. >>> keys(d)
  177. ['TEST', 'MOO']
  178. """
  179. return d.keys()
  180. def getData(d):
  181. """Returns the data object used"""
  182. return d
  183. def setData(newData, d):
  184. """Sets the data object to the supplied value"""
  185. d = newData
  186. ##
  187. ## Cookie Monsters' query functions
  188. ##
  189. def _get_override_vars(d, override):
  190. """
  191. Internal!!!
  192. Get the Names of Variables that have a specific
  193. override. This function returns a iterable
  194. Set or an empty list
  195. """
  196. return []
  197. def _get_var_flags_triple(d):
  198. """
  199. Internal!!!
  200. """
  201. return []
  202. __expand_var_regexp__ = re.compile(r"\${[^{}]+}")
  203. __expand_python_regexp__ = re.compile(r"\${@.+?}")
  204. def expand(s, d, varname = None):
  205. """Variable expansion using the data store.
  206. Example:
  207. Standard expansion:
  208. >>> d = init()
  209. >>> setVar('A', 'sshd', d)
  210. >>> print expand('/usr/bin/${A}', d)
  211. /usr/bin/sshd
  212. Python expansion:
  213. >>> d = init()
  214. >>> print expand('result: ${@37 * 72}', d)
  215. result: 2664
  216. Shell expansion:
  217. >>> d = init()
  218. >>> print expand('${TARGET_MOO}', d)
  219. ${TARGET_MOO}
  220. >>> setVar('TARGET_MOO', 'yupp', d)
  221. >>> print expand('${TARGET_MOO}',d)
  222. yupp
  223. >>> setVar('SRC_URI', 'http://somebug.${TARGET_MOO}', d)
  224. >>> delVar('TARGET_MOO', d)
  225. >>> print expand('${SRC_URI}', d)
  226. http://somebug.${TARGET_MOO}
  227. """
  228. return d.expand(s, varname)
  229. def expandKeys(alterdata, readdata = None):
  230. if readdata == None:
  231. readdata = alterdata
  232. for key in keys(alterdata):
  233. if not '${' in key:
  234. continue
  235. ekey = expand(key, readdata)
  236. if key == ekey:
  237. continue
  238. renameVar(key, ekey, alterdata)
  239. def expandData(alterdata, readdata = None):
  240. """For each variable in alterdata, expand it, and update the var contents.
  241. Replacements use data from readdata.
  242. Example:
  243. >>> a=init()
  244. >>> b=init()
  245. >>> setVar("dlmsg", "dl_dir is ${DL_DIR}", a)
  246. >>> setVar("DL_DIR", "/path/to/whatever", b)
  247. >>> expandData(a, b)
  248. >>> print getVar("dlmsg", a)
  249. dl_dir is /path/to/whatever
  250. """
  251. if readdata == None:
  252. readdata = alterdata
  253. for key in keys(alterdata):
  254. val = getVar(key, alterdata)
  255. if type(val) is not types.StringType:
  256. continue
  257. expanded = expand(val, readdata)
  258. # print "key is %s, val is %s, expanded is %s" % (key, val, expanded)
  259. if val != expanded:
  260. setVar(key, expanded, alterdata)
  261. import os
  262. def inheritFromOS(d):
  263. """Inherit variables from the environment."""
  264. # fakeroot needs to be able to set these
  265. non_inherit_vars = [ "LD_LIBRARY_PATH", "LD_PRELOAD" ]
  266. for s in os.environ.keys():
  267. if not s in non_inherit_vars:
  268. try:
  269. setVar(s, os.environ[s], d)
  270. setVarFlag(s, 'matchesenv', '1', d)
  271. except TypeError:
  272. pass
  273. import sys
  274. def emit_var(var, o=sys.__stdout__, d = init(), all=False):
  275. """Emit a variable to be sourced by a shell."""
  276. if getVarFlag(var, "python", d):
  277. return 0
  278. export = getVarFlag(var, "export", d)
  279. unexport = getVarFlag(var, "unexport", d)
  280. func = getVarFlag(var, "func", d)
  281. if not all and not export and not unexport and not func:
  282. return 0
  283. try:
  284. if all:
  285. oval = getVar(var, d, 0)
  286. val = getVar(var, d, 1)
  287. except KeyboardInterrupt:
  288. raise
  289. except:
  290. excname = str(sys.exc_info()[0])
  291. if excname == "bb.build.FuncFailed":
  292. raise
  293. o.write('# expansion of %s threw %s\n' % (var, excname))
  294. return 0
  295. if all:
  296. o.write('# %s=%s\n' % (var, oval))
  297. if type(val) is not types.StringType:
  298. return 0
  299. if getVarFlag(var, 'matchesenv', d):
  300. return 0
  301. if (var.find("-") != -1 or var.find(".") != -1 or var.find('{') != -1 or var.find('}') != -1 or var.find('+') != -1) and not all:
  302. return 0
  303. varExpanded = expand(var, d)
  304. if unexport:
  305. o.write('unset %s\n' % varExpanded)
  306. return 1
  307. val.rstrip()
  308. if not val:
  309. return 0
  310. if func:
  311. # NOTE: should probably check for unbalanced {} within the var
  312. o.write("%s() {\n%s\n}\n" % (varExpanded, val))
  313. return 1
  314. if export:
  315. o.write('export ')
  316. # if we're going to output this within doublequotes,
  317. # to a shell, we need to escape the quotes in the var
  318. alter = re.sub('"', '\\"', val.strip())
  319. o.write('%s="%s"\n' % (varExpanded, alter))
  320. return 1
  321. def emit_env(o=sys.__stdout__, d = init(), all=False):
  322. """Emits all items in the data store in a format such that it can be sourced by a shell."""
  323. env = keys(d)
  324. for e in env:
  325. if getVarFlag(e, "func", d):
  326. continue
  327. emit_var(e, o, d, all) and o.write('\n')
  328. for e in env:
  329. if not getVarFlag(e, "func", d):
  330. continue
  331. emit_var(e, o, d) and o.write('\n')
  332. def update_data(d):
  333. """Modifies the environment vars according to local overrides and commands.
  334. Examples:
  335. Appending to a variable:
  336. >>> d = init()
  337. >>> setVar('TEST', 'this is a', d)
  338. >>> setVar('TEST_append', ' test', d)
  339. >>> setVar('TEST_append', ' of the emergency broadcast system.', d)
  340. >>> update_data(d)
  341. >>> print getVar('TEST', d)
  342. this is a test of the emergency broadcast system.
  343. Prepending to a variable:
  344. >>> setVar('TEST', 'virtual/libc', d)
  345. >>> setVar('TEST_prepend', 'virtual/tmake ', d)
  346. >>> setVar('TEST_prepend', 'virtual/patcher ', d)
  347. >>> update_data(d)
  348. >>> print getVar('TEST', d)
  349. virtual/patcher virtual/tmake virtual/libc
  350. Overrides:
  351. >>> setVar('TEST_arm', 'target', d)
  352. >>> setVar('TEST_ramses', 'machine', d)
  353. >>> setVar('TEST_local', 'local', d)
  354. >>> setVar('OVERRIDES', 'arm', d)
  355. >>> setVar('TEST', 'original', d)
  356. >>> update_data(d)
  357. >>> print getVar('TEST', d)
  358. target
  359. >>> setVar('OVERRIDES', 'arm:ramses:local', d)
  360. >>> setVar('TEST', 'original', d)
  361. >>> update_data(d)
  362. >>> print getVar('TEST', d)
  363. local
  364. CopyMonster:
  365. >>> e = d.createCopy()
  366. >>> setVar('TEST_foo', 'foo', e)
  367. >>> update_data(e)
  368. >>> print getVar('TEST', e)
  369. local
  370. >>> setVar('OVERRIDES', 'arm:ramses:local:foo', e)
  371. >>> update_data(e)
  372. >>> print getVar('TEST', e)
  373. foo
  374. >>> f = d.createCopy()
  375. >>> setVar('TEST_moo', 'something', f)
  376. >>> setVar('OVERRIDES', 'moo:arm:ramses:local:foo', e)
  377. >>> update_data(e)
  378. >>> print getVar('TEST', e)
  379. foo
  380. >>> h = init()
  381. >>> setVar('SRC_URI', 'file://append.foo;patch=1 ', h)
  382. >>> g = h.createCopy()
  383. >>> setVar('SRC_URI_append_arm', 'file://other.foo;patch=1', g)
  384. >>> setVar('OVERRIDES', 'arm:moo', g)
  385. >>> update_data(g)
  386. >>> print getVar('SRC_URI', g)
  387. file://append.foo;patch=1 file://other.foo;patch=1
  388. """
  389. bb.msg.debug(2, bb.msg.domain.Data, "update_data()")
  390. # now ask the cookie monster for help
  391. #print "Cookie Monster"
  392. #print "Append/Prepend %s" % d._special_values
  393. #print "Overrides %s" % d._seen_overrides
  394. overrides = (getVar('OVERRIDES', d, 1) or "").split(':') or []
  395. #
  396. # Well let us see what breaks here. We used to iterate
  397. # over each variable and apply the override and then
  398. # do the line expanding.
  399. # If we have bad luck - which we will have - the keys
  400. # where in some order that is so important for this
  401. # method which we don't have anymore.
  402. # Anyway we will fix that and write test cases this
  403. # time.
  404. #
  405. # First we apply all overrides
  406. # Then we will handle _append and _prepend
  407. #
  408. for o in overrides:
  409. # calculate '_'+override
  410. l = len(o)+1
  411. # see if one should even try
  412. if not d._seen_overrides.has_key(o):
  413. continue
  414. vars = d._seen_overrides[o]
  415. for var in vars:
  416. name = var[:-l]
  417. try:
  418. d[name] = d[var]
  419. except:
  420. bb.msg.note(1, bb.msg.domain.Data, "Untracked delVar")
  421. # now on to the appends and prepends
  422. if d._special_values.has_key('_append'):
  423. appends = d._special_values['_append'] or []
  424. for append in appends:
  425. for (a, o) in getVarFlag(append, '_append', d) or []:
  426. # maybe the OVERRIDE was not yet added so keep the append
  427. if (o and o in overrides) or not o:
  428. delVarFlag(append, '_append', d)
  429. if o and not o in overrides:
  430. continue
  431. sval = getVar(append,d) or ""
  432. sval+=a
  433. setVar(append, sval, d)
  434. if d._special_values.has_key('_prepend'):
  435. prepends = d._special_values['_prepend'] or []
  436. for prepend in prepends:
  437. for (a, o) in getVarFlag(prepend, '_prepend', d) or []:
  438. # maybe the OVERRIDE was not yet added so keep the prepend
  439. if (o and o in overrides) or not o:
  440. delVarFlag(prepend, '_prepend', d)
  441. if o and not o in overrides:
  442. continue
  443. sval = a + (getVar(prepend,d) or "")
  444. setVar(prepend, sval, d)
  445. def inherits_class(klass, d):
  446. val = getVar('__inherit_cache', d) or []
  447. if os.path.join('classes', '%s.bbclass' % klass) in val:
  448. return True
  449. return False
  450. def _test():
  451. """Start a doctest run on this module"""
  452. import doctest
  453. from bb import data
  454. doctest.testmod(data)
  455. if __name__ == "__main__":
  456. _test()