##### MakeTargets (.MF? -> Builders)def makeTargetsEmitter(target, source, env): for t in target: t.set_always_build() t.set_ignore_missing() return (target, source)def makeTargets(target, source, env, for_signature): if for_signature: return "" if hasattr(SCons.Job, 'parallel_lock'):# print 'acquire builder' SCons.Job.parallel_lock.acquire()# print 'acquired builder' try: cache_clear_needed = {} conglomerates = {} mft = source[0] for x in target: if env["VERBOSITY"]: print>>sys.stderr, 'INF: Building DAG for "%s"' % mft for y in x.children(): if env["SYNC_PERFORCE"] and y.has_builder() and y.has_src_builder() and (id(y.builder) == id(y.src_builder())): y.builder_set(None) if not y.has_builder(): skey = y.scanner_key().lower() if not skey: continue name = os.path.basename(str(y)).lower() # Find a builder that matches this suffix for k, v in env["BUILDERS"].items(): if v.get_suffix(env, [y]) == skey: if not hasattr(y.attributes, 'mfp_source'): raise BuilderException('Cannot build a DAG for "%s" because it was handled by an invalid scanner in "%s"' % (y, mft)) if y.attributes.mfp_source: source = env.File(y.attributes.mfp_source) else: source = None if not source: if not v.overrides.get("allow_no_source", None): raise BuilderException('%%SOURCE directive missing for "%s" to be able to apply the builder "%s" in "%s"' % (y, k, mft)) else: src_mutator = v.overrides.get("src_mutator", None) if src_mutator: source = src_mutator(y, source, env) if source.scanner_key() not in v.src_suffixes(env): raise BuilderException('The %%SOURCE suffix does not match for "%s" from "%s" in "%s": %s' % (source, y, mft, v.src_suffixes(env))) source.set_intermediate_path(y.dir) if v.overrides.get('conglomerate', 0): if k not in conglomerates: conglomerates[k] = (v, [], []) conglomerates[k][1].append(y) if source: conglomerates[k][2].append(source) continue if env["VERBOSITY"] > 2: print 'INF: Builder:', k, y, source, y.attributes.mfp_overrides try: rule = v(*(env, y, source), **y.attributes.mfp_overrides) markForCacheClear(cache_clear_needed, rule) except CrushException, b: print>>sys.stderr, 'ERR: Got an exception while creating build rules for "%s" in "%s"' % (y, mft) raise break for k, v in conglomerates.items(): if env["VERBOSITY"] > 2: print 'INF: ConglomerateBuilder:', k, v[0], map(str, v[1]), map(str, v[2]) try: rule = v[0](*(env, v[1], v[2])) markForCacheClear(cache_clear_needed, rule) except CrushException, b: print>>sys.stderr, 'ERR: Got an exception while creating build rules for "%s" in "%s"' % (' '.join(map(str, v[1])), mft) raise break # Sanity check if not env.GetOption('clean'): missing = 0 for x in target: for y in x.children(): if not y.has_builder() and not os.path.exists(str(y)): print>>sys.stderr, 'ERR: Do not know how to build the target "%s"' % y missing += 1 if missing: raise BuilderException('Do not know how to build %d targets needed by "%s"' % (missing, x.children()[0])) if not len(cache_clear_needed): if env["VERBOSITY"] > 1: print>>sys.stderr, 'INF: No targets for "%s" were auto-generated' % mft else: cleared = doCacheClear(cache_clear_needed, env) if env["VERBOSITY"] > 1: print>>sys.stderr, "INF: Cleared %d of %d DAG dependencies for %s" % (cleared, len(cache_clear_needed), mft) finally: if hasattr(SCons.Job, 'parallel_lock'):# print 'release builder' SCons.Job.parallel_lock.release() return ""env['BUILDERS']['MakeTargets'] = Builder( generator = makeTargets, emitter = makeTargetsEmitter, )##### Scons cache clear handlingdef markForCacheClear(dict, targets, depth=100): for x in asList(targets): if x in dict: continue dict[x]=None if depth==1: continue markForCacheClear(dict, x.all_children(), depth-1)def doCacheClear(dict, env): cleared = 0 for x in dict.keys(): if x.has_builder(): if env["VERBOSITY"] > 2: print>>sys.stderr, 'INF: Clearing', str(x) cleared += 1 x.clear() continue return cleared##### .MFT Scannerols3_re = re.compile( r'ENCAP\s+\'(?P<type>.*)\'\s+(?P<id>\d*)\s*\n' +r'NAME\s+"(?P<name>.*)"\s*\n' +r'MEM_TYPE\s+(?P<mem_type>0[xX][\da-fA-F]+|\d+)\s*\n' +r'(?:COMPRESSION\s+(?P<compression>\d)\s*\n)?' +r'LOAD_POS\s+(?P<load_pos>[\.\d]+)\s*\n'# +r'CONDITION\s+"(.*)"\s*\n'# +r'LOAD_ACTION\s+"(.*)"\s*\n'# +r'FREE_ACTION\s+"(.*)"\s*\n'# +r'TARG_ACTION\s+"(.*)"\s*\n'# +r'HIT_ACTION\s+"(.*)"\s*\n' +r'(?:%SOURCE\s+"(?P<source>.*)"\s*\n)?' +r'(?:%OVERRIDES\s+"(?P<overrides>.*)"\s*\n)?')ols3_re_encaps = re.compile(r'ENCAP')# We have far too many hacks in here to be able to use builtin SCons implicit depdency support.def mftScanner(target, env, arg): if not target.exists(): return [] depends = [] depends_dict = {} root = target.get_dir().get_dir() i = 0 for m in ols3_re.finditer(target.get_contents()): x = m.groupdict() fname = x['name'].lower() # Handle .zip paths idx = fname.find(".zip") if idx>=0: fname = fname[:idx+4] file = env.File(fname, root) if file in depends_dict: if file.scanner_key() <> ".zip": if target.current(): raise ScannerException('Manifest "%s" has a duplicate file "%s" with id %s' % (target, file, x['id'])) i += 1 continue if x['source']: source = x['source'].lower() else: source = None overrides = { 'ENTRY_TYPE':x['type'], 'ENCAP_ID':x['id'], } if x['overrides']: for y in x['overrides'].split(' '): z = y.split('=') if len(z) <> 2: if target.current(): raise ScannerException('Manifest "%s" has a malformed override for "%s"' % (target, file)) overrides[z[0]] = z[1] if not hasattr(file.attributes, 'mfp_overrides') or not getattr(file.attributes, 'was_current', False): file.attributes.mfp_source = source file.attributes.mfp_overrides = overrides file.attributes.was_current = target.current() elif target.current(): if not samefile(file.attributes.mfp_source, source): raise ScannerException('Source file mismatch ("%s" vs "%s") found for "%s" in "%s"' % (file.attributes.mfp_source, source, file, target)) if 'ENCAP_ID' not in file.attributes.mfp_overrides: del overrides['ENCAP_ID'] if 'ENCAP_ID' in file.attributes.mfp_overrides and (file.attributes.mfp_overrides['ENCAP_ID'] <> x['id']): # Do not store ENCAP_ID if we have conflicts del file.attributes.mfp_overrides['ENCAP_ID'] del overrides['ENCAP_ID'] if env['VERBOSITY'] > 2: print>>sys.stderr, 'INF: Encap ID mismatch found for "%s" in "%s"' % (file, target) if cmp(overrides, file.attributes.mfp_overrides) <> 0: print>>sys.stderr, 'INF: %s vs %s' % (overrides, file.attributes.mfp_overrides) raise ScannerException('Overrides mismatch found for "%s" in "%s"' % (file, target)) depends.append(file) depends_dict[file] = None i += 1 if i <> len(ols3_re_encaps.findall(target.get_contents())): if target.current(): raise ScannerException('The OLS3 regular expression parser is broken for "%s"' % target) else: print>>sys.stderr, 'WRN: The OLS3 regular expression parser is broken for "%s"' % target return [] if not i: print>>sys.stderr, 'WRN: The OLS3 manifest is empty for "%s"' % target return dependsmaster_env["SCANNERS"].append(Scanner(name = mftScanner.__name__, function = mftScanner, skeys = [".mft"]))