summaryrefslogtreecommitdiffstats
path: root/bitbake
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2013-11-25 22:59:39 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2013-11-26 23:01:33 +0000
commita10301f6a90567c2d2eca9306a4b7b752f58a9c2 (patch)
tree41da459bd5e16ee0d8e9d502532b34c284e0fdd9 /bitbake
parentd0616923724c5d021a816ec778e836283a2ccfe2 (diff)
downloadpoky-a10301f6a90567c2d2eca9306a4b7b752f58a9c2.tar.gz
bitbake: data/codeparser: Improve handling of contains functions
One of the current frustrations with the sstate checksums is that code like base_contains('X', 'y',...) adds a full dependency on X and varies depend even on whitespace changes in X. This patch adds special handling of the contains functions to expand the first parameter and check for the flag specified by the second parameter (assuming its a string). The result is then appended to the value of the variable with a "Set" or "Unset" status. If the flag is added/removed, the stored variable value changes and hence the checksum changes. No dependency on X is added so it is free to change with regard to other flags or whitespace. This code is far from ideal, ideally we'd have properly typed variables however it fixes a major annoyance of the current checksums and is of enough value its worth adding in a stopgap solution. It shouldn't significantly restrict any propely typed variable implementation in future. (Bitbake rev: ed2d0a22a80299de0cfd377999950cf4b26c512e) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> Signed-off-by: Christopher Larson <chris_larson@mentor.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake')
-rw-r--r--bitbake/lib/bb/codeparser.py14
-rw-r--r--bitbake/lib/bb/data.py18
-rw-r--r--bitbake/lib/bb/data_smart.py4
3 files changed, 33 insertions, 3 deletions
diff --git a/bitbake/lib/bb/codeparser.py b/bitbake/lib/bb/codeparser.py
index 116481559a..6e34eff999 100644
--- a/bitbake/lib/bb/codeparser.py
+++ b/bitbake/lib/bb/codeparser.py
@@ -1,6 +1,7 @@
1import ast 1import ast
2import codegen 2import codegen
3import logging 3import logging
4import collections
4import os.path 5import os.path
5import bb.utils, bb.data 6import bb.utils, bb.data
6from itertools import chain 7from itertools import chain
@@ -35,7 +36,7 @@ def check_indent(codestr):
35 36
36class CodeParserCache(MultiProcessCache): 37class CodeParserCache(MultiProcessCache):
37 cache_file_name = "bb_codeparser.dat" 38 cache_file_name = "bb_codeparser.dat"
38 CACHE_VERSION = 3 39 CACHE_VERSION = 4
39 40
40 def __init__(self): 41 def __init__(self):
41 MultiProcessCache.__init__(self) 42 MultiProcessCache.__init__(self)
@@ -122,7 +123,11 @@ class PythonParser():
122 name = self.called_node_name(node.func) 123 name = self.called_node_name(node.func)
123 if name in self.getvars or name in self.containsfuncs: 124 if name in self.getvars or name in self.containsfuncs:
124 if isinstance(node.args[0], ast.Str): 125 if isinstance(node.args[0], ast.Str):
125 self.references.add(node.args[0].s) 126 varname = node.args[0].s
127 if name in self.containsfuncs and isinstance(node.args[1], ast.Str):
128 self.contains[varname].add(node.args[1].s)
129 else:
130 self.references.add(node.args[0].s)
126 else: 131 else:
127 self.warn(node.func, node.args[0]) 132 self.warn(node.func, node.args[0])
128 elif name in self.execfuncs: 133 elif name in self.execfuncs:
@@ -148,6 +153,7 @@ class PythonParser():
148 153
149 def __init__(self, name, log): 154 def __init__(self, name, log):
150 self.var_execs = set() 155 self.var_execs = set()
156 self.contains = collections.defaultdict(set)
151 self.execs = set() 157 self.execs = set()
152 self.references = set() 158 self.references = set()
153 self.log = BufferedLogger('BitBake.Data.%s' % name, logging.DEBUG, log) 159 self.log = BufferedLogger('BitBake.Data.%s' % name, logging.DEBUG, log)
@@ -161,14 +167,15 @@ class PythonParser():
161 if h in codeparsercache.pythoncache: 167 if h in codeparsercache.pythoncache:
162 self.references = codeparsercache.pythoncache[h]["refs"] 168 self.references = codeparsercache.pythoncache[h]["refs"]
163 self.execs = codeparsercache.pythoncache[h]["execs"] 169 self.execs = codeparsercache.pythoncache[h]["execs"]
170 self.contains = codeparsercache.pythoncache[h]["contains"]
164 return 171 return
165 172
166 if h in codeparsercache.pythoncacheextras: 173 if h in codeparsercache.pythoncacheextras:
167 self.references = codeparsercache.pythoncacheextras[h]["refs"] 174 self.references = codeparsercache.pythoncacheextras[h]["refs"]
168 self.execs = codeparsercache.pythoncacheextras[h]["execs"] 175 self.execs = codeparsercache.pythoncacheextras[h]["execs"]
176 self.contains = codeparsercache.pythoncacheextras[h]["contains"]
169 return 177 return
170 178
171
172 code = compile(check_indent(str(node)), "<string>", "exec", 179 code = compile(check_indent(str(node)), "<string>", "exec",
173 ast.PyCF_ONLY_AST) 180 ast.PyCF_ONLY_AST)
174 181
@@ -181,6 +188,7 @@ class PythonParser():
181 codeparsercache.pythoncacheextras[h] = {} 188 codeparsercache.pythoncacheextras[h] = {}
182 codeparsercache.pythoncacheextras[h]["refs"] = self.references 189 codeparsercache.pythoncacheextras[h]["refs"] = self.references
183 codeparsercache.pythoncacheextras[h]["execs"] = self.execs 190 codeparsercache.pythoncacheextras[h]["execs"] = self.execs
191 codeparsercache.pythoncacheextras[h]["contains"] = self.contains
184 192
185class ShellParser(): 193class ShellParser():
186 def __init__(self, name, log): 194 def __init__(self, name, log):
diff --git a/bitbake/lib/bb/data.py b/bitbake/lib/bb/data.py
index bdd1e79e24..3d2c6a4975 100644
--- a/bitbake/lib/bb/data.py
+++ b/bitbake/lib/bb/data.py
@@ -299,6 +299,21 @@ def build_dependencies(key, keys, shelldeps, varflagsexcl, d):
299 vardeps = varflags.get("vardeps") 299 vardeps = varflags.get("vardeps")
300 value = d.getVar(key, False) 300 value = d.getVar(key, False)
301 301
302 def handle_contains(value, contains, d):
303 newvalue = ""
304 for k in contains:
305 l = (d.getVar(k, True) or "").split()
306 for word in contains[k]:
307 if word in l:
308 newvalue += "\n%s{%s} = Set" % (k, word)
309 else:
310 newvalue += "\n%s{%s} = Unset" % (k, word)
311 if not newvalue:
312 return value
313 if not value:
314 return newvalue
315 return value + newvalue
316
302 if "vardepvalue" in varflags: 317 if "vardepvalue" in varflags:
303 value = varflags.get("vardepvalue") 318 value = varflags.get("vardepvalue")
304 elif varflags.get("func"): 319 elif varflags.get("func"):
@@ -309,6 +324,7 @@ def build_dependencies(key, keys, shelldeps, varflagsexcl, d):
309 logger.warn("Variable %s contains tabs, please remove these (%s)" % (key, d.getVar("FILE", True))) 324 logger.warn("Variable %s contains tabs, please remove these (%s)" % (key, d.getVar("FILE", True)))
310 parser.parse_python(parsedvar.value) 325 parser.parse_python(parsedvar.value)
311 deps = deps | parser.references 326 deps = deps | parser.references
327 value = handle_contains(value, parser.contains, d)
312 else: 328 else:
313 parsedvar = d.expandWithRefs(value, key) 329 parsedvar = d.expandWithRefs(value, key)
314 parser = bb.codeparser.ShellParser(key, logger) 330 parser = bb.codeparser.ShellParser(key, logger)
@@ -318,10 +334,12 @@ def build_dependencies(key, keys, shelldeps, varflagsexcl, d):
318 parser.log.flush() 334 parser.log.flush()
319 deps = deps | parsedvar.references 335 deps = deps | parsedvar.references
320 deps = deps | (keys & parser.execs) | (keys & parsedvar.execs) 336 deps = deps | (keys & parser.execs) | (keys & parsedvar.execs)
337 value = handle_contains(value, parsedvar.contains, d)
321 else: 338 else:
322 parser = d.expandWithRefs(value, key) 339 parser = d.expandWithRefs(value, key)
323 deps |= parser.references 340 deps |= parser.references
324 deps = deps | (keys & parser.execs) 341 deps = deps | (keys & parser.execs)
342 value = handle_contains(value, parser.contains, d)
325 343
326 # Add varflags, assuming an exclusion list is set 344 # Add varflags, assuming an exclusion list is set
327 if varflagsexcl: 345 if varflagsexcl:
diff --git a/bitbake/lib/bb/data_smart.py b/bitbake/lib/bb/data_smart.py
index a1cbaba62b..9a6f767116 100644
--- a/bitbake/lib/bb/data_smart.py
+++ b/bitbake/lib/bb/data_smart.py
@@ -35,6 +35,7 @@ import hashlib
35import bb, bb.codeparser 35import bb, bb.codeparser
36from bb import utils 36from bb import utils
37from bb.COW import COWDictBase 37from bb.COW import COWDictBase
38import collections
38 39
39logger = logging.getLogger("BitBake.Data") 40logger = logging.getLogger("BitBake.Data")
40 41
@@ -88,6 +89,7 @@ class VariableParse:
88 89
89 self.references = set() 90 self.references = set()
90 self.execs = set() 91 self.execs = set()
92 self.contains = collections.defaultdict(set)
91 93
92 def var_sub(self, match): 94 def var_sub(self, match):
93 key = match.group()[2:-1] 95 key = match.group()[2:-1]
@@ -120,6 +122,8 @@ class VariableParse:
120 self.references |= parser.references 122 self.references |= parser.references
121 self.execs |= parser.execs 123 self.execs |= parser.execs
122 124
125 for k in parser.contains:
126 self.contains[k].update(parser.contains[k])
123 value = utils.better_eval(codeobj, DataContext(self.d)) 127 value = utils.better_eval(codeobj, DataContext(self.d))
124 return str(value) 128 return str(value)
125 129