diff options
| -rw-r--r-- | bitbake/lib/bb/codeparser.py | 66 | ||||
| -rw-r--r-- | bitbake/lib/bb/cooker.py | 2 |
2 files changed, 58 insertions, 10 deletions
diff --git a/bitbake/lib/bb/codeparser.py b/bitbake/lib/bb/codeparser.py index 88a26c82a7..faffe390d9 100644 --- a/bitbake/lib/bb/codeparser.py +++ b/bitbake/lib/bb/codeparser.py | |||
| @@ -4,6 +4,14 @@ from bb import msg, utils | |||
| 4 | import ast | 4 | import ast |
| 5 | import codegen | 5 | import codegen |
| 6 | 6 | ||
| 7 | PARSERCACHE_VERSION = 1 | ||
| 8 | |||
| 9 | try: | ||
| 10 | import cPickle as pickle | ||
| 11 | except ImportError: | ||
| 12 | import pickle | ||
| 13 | bb.msg.note(1, bb.msg.domain.Cache, "Importing cPickle failed. Falling back to a very slow implementation.") | ||
| 14 | |||
| 7 | def check_indent(codestr): | 15 | def check_indent(codestr): |
| 8 | """If the code is indented, add a top level piece of code to 'remove' the indentation""" | 16 | """If the code is indented, add a top level piece of code to 'remove' the indentation""" |
| 9 | 17 | ||
| @@ -13,6 +21,43 @@ def check_indent(codestr): | |||
| 13 | return codestr | 21 | return codestr |
| 14 | 22 | ||
| 15 | pythonparsecache = {} | 23 | pythonparsecache = {} |
| 24 | shellparsecache = {} | ||
| 25 | |||
| 26 | def parser_cachefile(d): | ||
| 27 | cachedir = bb.data.getVar("PERSISTENT_DIR", d, True) or bb.data.getVar("CACHE", d, True) | ||
| 28 | if cachedir in [None, '']: | ||
| 29 | return None | ||
| 30 | bb.utils.mkdirhier(cachedir) | ||
| 31 | cachefile = os.path.join(cachedir, "bb_codeparser.dat") | ||
| 32 | bb.msg.debug(1, bb.msg.domain.Cache, "Using cache in '%s' for codeparser cache" % cachefile) | ||
| 33 | return cachefile | ||
| 34 | |||
| 35 | def parser_cache_init(d): | ||
| 36 | |||
| 37 | cachefile = parser_cachefile(d) | ||
| 38 | if not cachefile: | ||
| 39 | return | ||
| 40 | |||
| 41 | try: | ||
| 42 | p = pickle.Unpickler(file(cachefile, "rb")) | ||
| 43 | data, version = p.load() | ||
| 44 | except: | ||
| 45 | return | ||
| 46 | |||
| 47 | if version != PARSERCACHE_VERSION: | ||
| 48 | return | ||
| 49 | |||
| 50 | bb.codeparser.pythonparsecache = data[0] | ||
| 51 | bb.codeparser.shellparsecache = data[1] | ||
| 52 | |||
| 53 | def parser_cache_save(d): | ||
| 54 | |||
| 55 | cachefile = parser_cachefile(d) | ||
| 56 | if not cachefile: | ||
| 57 | return | ||
| 58 | |||
| 59 | p = pickle.Pickler(file(cachefile, "wb"), -1) | ||
| 60 | p.dump([[bb.codeparser.pythonparsecache, bb.codeparser.shellparsecache], PARSERCACHE_VERSION]) | ||
| 16 | 61 | ||
| 17 | class PythonParser(): | 62 | class PythonParser(): |
| 18 | class ValueVisitor(): | 63 | class ValueVisitor(): |
| @@ -125,9 +170,11 @@ class PythonParser(): | |||
| 125 | 170 | ||
| 126 | def parse_python(self, node): | 171 | def parse_python(self, node): |
| 127 | 172 | ||
| 128 | if node in pythonparsecache: | 173 | h = hash(node) |
| 129 | self.references = pythonparsecache[node].references | 174 | |
| 130 | self.execs = pythonparsecache[node].execs | 175 | if h in pythonparsecache: |
| 176 | self.references = pythonparsecache[h].references | ||
| 177 | self.execs = pythonparsecache[h].execs | ||
| 131 | return | 178 | return |
| 132 | 179 | ||
| 133 | code = compile(check_indent(str(node)), "<string>", "exec", | 180 | code = compile(check_indent(str(node)), "<string>", "exec", |
| @@ -142,10 +189,7 @@ class PythonParser(): | |||
| 142 | self.references.update(visitor.var_execs) | 189 | self.references.update(visitor.var_execs) |
| 143 | self.execs = visitor.direct_func_calls | 190 | self.execs = visitor.direct_func_calls |
| 144 | 191 | ||
| 145 | pythonparsecache[node] = self | 192 | pythonparsecache[h] = self |
| 146 | |||
| 147 | |||
| 148 | shellparsecache = {} | ||
| 149 | 193 | ||
| 150 | class ShellParser(): | 194 | class ShellParser(): |
| 151 | def __init__(self): | 195 | def __init__(self): |
| @@ -158,8 +202,10 @@ class ShellParser(): | |||
| 158 | commands it executes. | 202 | commands it executes. |
| 159 | """ | 203 | """ |
| 160 | 204 | ||
| 161 | if value in pythonparsecache: | 205 | h = hash(value) |
| 162 | self.execs = shellparsecache[value].execs | 206 | |
| 207 | if h in shellparsecache: | ||
| 208 | self.execs = shellparsecache[h].execs | ||
| 163 | return | 209 | return |
| 164 | 210 | ||
| 165 | try: | 211 | try: |
| @@ -171,7 +217,7 @@ class ShellParser(): | |||
| 171 | self.process_tokens(token) | 217 | self.process_tokens(token) |
| 172 | self.execs = set(cmd for cmd in self.allexecs if cmd not in self.funcdefs) | 218 | self.execs = set(cmd for cmd in self.allexecs if cmd not in self.funcdefs) |
| 173 | 219 | ||
| 174 | shellparsecache[value] = self | 220 | shellparsecache[h] = self |
| 175 | 221 | ||
| 176 | return self.execs | 222 | return self.execs |
| 177 | 223 | ||
diff --git a/bitbake/lib/bb/cooker.py b/bitbake/lib/bb/cooker.py index dcdcb7d443..ea33693ddb 100644 --- a/bitbake/lib/bb/cooker.py +++ b/bitbake/lib/bb/cooker.py | |||
| @@ -546,6 +546,7 @@ class BBCooker: | |||
| 546 | 546 | ||
| 547 | if bb.data.getVar("BB_WORKERCONTEXT", self.configuration.data) is None: | 547 | if bb.data.getVar("BB_WORKERCONTEXT", self.configuration.data) is None: |
| 548 | bb.fetch.fetcher_init(self.configuration.data) | 548 | bb.fetch.fetcher_init(self.configuration.data) |
| 549 | bb.codeparser.parser_cache_init(self.configuration.data) | ||
| 549 | 550 | ||
| 550 | bb.event.fire(bb.event.ConfigParsed(), self.configuration.data) | 551 | bb.event.fire(bb.event.ConfigParsed(), self.configuration.data) |
| 551 | 552 | ||
| @@ -1011,6 +1012,7 @@ class CookerParser: | |||
| 1011 | 1012 | ||
| 1012 | if self.pointer >= self.total: | 1013 | if self.pointer >= self.total: |
| 1013 | cooker.bb_cache.sync() | 1014 | cooker.bb_cache.sync() |
| 1015 | bb.codeparser.parser_cache_save(cooker.configuration.data) | ||
| 1014 | if self.error > 0: | 1016 | if self.error > 0: |
| 1015 | raise ParsingErrorsFound | 1017 | raise ParsingErrorsFound |
| 1016 | return False | 1018 | return False |
