summaryrefslogtreecommitdiffstats
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 15:32:39 +0000
commited2d0a22a80299de0cfd377999950cf4b26c512e (patch)
treeda8355663be01732cb1c7d8819de2c3706424750
parent84f1dde717dac22435005b79d03ee0b80a3e8e62 (diff)
downloadbitbake-ed2d0a22a80299de0cfd377999950cf4b26c512e.tar.gz
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. 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>
-rw-r--r--lib/bb/codeparser.py14
-rw-r--r--lib/bb/data.py18
-rw-r--r--lib/bb/data_smart.py4
3 files changed, 33 insertions, 3 deletions
diff --git a/lib/bb/codeparser.py b/lib/bb/codeparser.py
index 116481559..6e34eff99 100644
--- a/lib/bb/codeparser.py
+++ b/lib/bb/codeparser.py
@@ -1,6 +1,7 @@
import ast
import codegen
import logging
+import collections
import os.path
import bb.utils, bb.data
from itertools import chain
@@ -35,7 +36,7 @@ def check_indent(codestr):
class CodeParserCache(MultiProcessCache):
cache_file_name = "bb_codeparser.dat"
- CACHE_VERSION = 3
+ CACHE_VERSION = 4
def __init__(self):
MultiProcessCache.__init__(self)
@@ -122,7 +123,11 @@ class PythonParser():
name = self.called_node_name(node.func)
if name in self.getvars or name in self.containsfuncs:
if isinstance(node.args[0], ast.Str):
- self.references.add(node.args[0].s)
+ varname = node.args[0].s
+ if name in self.containsfuncs and isinstance(node.args[1], ast.Str):
+ self.contains[varname].add(node.args[1].s)
+ else:
+ self.references.add(node.args[0].s)
else:
self.warn(node.func, node.args[0])
elif name in self.execfuncs:
@@ -148,6 +153,7 @@ class PythonParser():
def __init__(self, name, log):
self.var_execs = set()
+ self.contains = collections.defaultdict(set)
self.execs = set()
self.references = set()
self.log = BufferedLogger('BitBake.Data.%s' % name, logging.DEBUG, log)
@@ -161,14 +167,15 @@ class PythonParser():
if h in codeparsercache.pythoncache:
self.references = codeparsercache.pythoncache[h]["refs"]
self.execs = codeparsercache.pythoncache[h]["execs"]
+ self.contains = codeparsercache.pythoncache[h]["contains"]
return
if h in codeparsercache.pythoncacheextras:
self.references = codeparsercache.pythoncacheextras[h]["refs"]
self.execs = codeparsercache.pythoncacheextras[h]["execs"]
+ self.contains = codeparsercache.pythoncacheextras[h]["contains"]
return
-
code = compile(check_indent(str(node)), "<string>", "exec",
ast.PyCF_ONLY_AST)
@@ -181,6 +188,7 @@ class PythonParser():
codeparsercache.pythoncacheextras[h] = {}
codeparsercache.pythoncacheextras[h]["refs"] = self.references
codeparsercache.pythoncacheextras[h]["execs"] = self.execs
+ codeparsercache.pythoncacheextras[h]["contains"] = self.contains
class ShellParser():
def __init__(self, name, log):
diff --git a/lib/bb/data.py b/lib/bb/data.py
index bdd1e79e2..3d2c6a497 100644
--- a/lib/bb/data.py
+++ b/lib/bb/data.py
@@ -299,6 +299,21 @@ def build_dependencies(key, keys, shelldeps, varflagsexcl, d):
vardeps = varflags.get("vardeps")
value = d.getVar(key, False)
+ def handle_contains(value, contains, d):
+ newvalue = ""
+ for k in contains:
+ l = (d.getVar(k, True) or "").split()
+ for word in contains[k]:
+ if word in l:
+ newvalue += "\n%s{%s} = Set" % (k, word)
+ else:
+ newvalue += "\n%s{%s} = Unset" % (k, word)
+ if not newvalue:
+ return value
+ if not value:
+ return newvalue
+ return value + newvalue
+
if "vardepvalue" in varflags:
value = varflags.get("vardepvalue")
elif varflags.get("func"):
@@ -309,6 +324,7 @@ def build_dependencies(key, keys, shelldeps, varflagsexcl, d):
logger.warn("Variable %s contains tabs, please remove these (%s)" % (key, d.getVar("FILE", True)))
parser.parse_python(parsedvar.value)
deps = deps | parser.references
+ value = handle_contains(value, parser.contains, d)
else:
parsedvar = d.expandWithRefs(value, key)
parser = bb.codeparser.ShellParser(key, logger)
@@ -318,10 +334,12 @@ def build_dependencies(key, keys, shelldeps, varflagsexcl, d):
parser.log.flush()
deps = deps | parsedvar.references
deps = deps | (keys & parser.execs) | (keys & parsedvar.execs)
+ value = handle_contains(value, parsedvar.contains, d)
else:
parser = d.expandWithRefs(value, key)
deps |= parser.references
deps = deps | (keys & parser.execs)
+ value = handle_contains(value, parser.contains, d)
# Add varflags, assuming an exclusion list is set
if varflagsexcl:
diff --git a/lib/bb/data_smart.py b/lib/bb/data_smart.py
index a1cbaba62..9a6f76711 100644
--- a/lib/bb/data_smart.py
+++ b/lib/bb/data_smart.py
@@ -35,6 +35,7 @@ import hashlib
import bb, bb.codeparser
from bb import utils
from bb.COW import COWDictBase
+import collections
logger = logging.getLogger("BitBake.Data")
@@ -88,6 +89,7 @@ class VariableParse:
self.references = set()
self.execs = set()
+ self.contains = collections.defaultdict(set)
def var_sub(self, match):
key = match.group()[2:-1]
@@ -120,6 +122,8 @@ class VariableParse:
self.references |= parser.references
self.execs |= parser.execs
+ for k in parser.contains:
+ self.contains[k].update(parser.contains[k])
value = utils.better_eval(codeobj, DataContext(self.d))
return str(value)