Refactor the mongo main() into a class in mk2bp_catalog.py
Test: m out/target/product/$(get_build_var TARGET_DEVICE)/mk2bp_remaining.html Change-Id: I7200f5f9a6735bb0da3928aa5dc74723d69752d3
This commit is contained in:
@@ -177,16 +177,6 @@ def is_google(dirname):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def make_annotation_link(annotations, analysis, modules):
|
|
||||||
if analysis:
|
|
||||||
return "<a href='javascript:update_details(%d)'>%s</a>" % (
|
|
||||||
annotations.Add(analysis, modules),
|
|
||||||
len(analysis)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
return "";
|
|
||||||
|
|
||||||
|
|
||||||
def is_clean(makefile):
|
def is_clean(makefile):
|
||||||
for analysis in makefile.analyses.values():
|
for analysis in makefile.analyses.values():
|
||||||
if analysis:
|
if analysis:
|
||||||
@@ -242,6 +232,18 @@ class SoongData(object):
|
|||||||
traverse(module)
|
traverse(module)
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
def contains_unblocked_modules(self, filename):
|
||||||
|
for m in self.reverse_makefiles[filename]:
|
||||||
|
if len(self.deps[m]) == 0:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def contains_blocked_modules(self, filename):
|
||||||
|
for m in self.reverse_makefiles[filename]:
|
||||||
|
if len(self.deps[m]) > 0:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def count_deps(depsdb, module, seen):
|
def count_deps(depsdb, module, seen):
|
||||||
"""Based on the depsdb, count the number of transitive dependencies.
|
"""Based on the depsdb, count the number of transitive dependencies.
|
||||||
|
|
||||||
@@ -256,18 +258,6 @@ def count_deps(depsdb, module, seen):
|
|||||||
count += 1 + count_deps(depsdb, dep, seen)
|
count += 1 + count_deps(depsdb, dep, seen)
|
||||||
return count
|
return count
|
||||||
|
|
||||||
def contains_unblocked_modules(soong, modules):
|
|
||||||
for m in modules:
|
|
||||||
if len(soong.deps[m]) == 0:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def contains_blocked_modules(soong, modules):
|
|
||||||
for m in modules:
|
|
||||||
if len(soong.deps[m]) > 0:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
OTHER_PARTITON = "_other"
|
OTHER_PARTITON = "_other"
|
||||||
HOST_PARTITON = "_host"
|
HOST_PARTITON = "_host"
|
||||||
|
|
||||||
@@ -292,21 +282,6 @@ def format_module_link(module):
|
|||||||
def format_module_list(modules):
|
def format_module_list(modules):
|
||||||
return "".join(["<div>%s</div>" % format_module_link(m) for m in modules])
|
return "".join(["<div>%s</div>" % format_module_link(m) for m in modules])
|
||||||
|
|
||||||
def traverse_ready_makefiles(soong, summary, makefiles):
|
|
||||||
def clean_and_only_blocked_by_clean(makefile):
|
|
||||||
if not is_clean(makefile):
|
|
||||||
return False
|
|
||||||
modules = soong.reverse_makefiles[makefile.filename]
|
|
||||||
for module in modules:
|
|
||||||
for dep in soong.transitive_deps(module):
|
|
||||||
for m in soong.makefiles.get(dep, []):
|
|
||||||
if not summary.IsClean(m):
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
return [Analysis(makefile.filename, []) for makefile in makefiles
|
|
||||||
if clean_and_only_blocked_by_clean(makefile)]
|
|
||||||
|
|
||||||
def print_analysis_header(link, title):
|
def print_analysis_header(link, title):
|
||||||
print("""
|
print("""
|
||||||
<a name="%(link)s"></a>
|
<a name="%(link)s"></a>
|
||||||
@@ -328,48 +303,6 @@ def print_analysis_header(link, title):
|
|||||||
print("""<th class="Count Warning">%s</th>""" % analyzer.title)
|
print("""<th class="Count Warning">%s</th>""" % analyzer.title)
|
||||||
print(" </tr>")
|
print(" </tr>")
|
||||||
|
|
||||||
|
|
||||||
def print_analysis_row(soong, summary, annotations, modules, rowtitle, rowclass, makefiles):
|
|
||||||
all_makefiles = [Analysis(makefile.filename, []) for makefile in makefiles]
|
|
||||||
clean_makefiles = [Analysis(makefile.filename, []) for makefile in makefiles
|
|
||||||
if is_clean(makefile)]
|
|
||||||
easy_makefiles = traverse_ready_makefiles(soong, summary, makefiles)
|
|
||||||
unblocked_clean_makefiles = [Analysis(makefile.filename, []) for makefile in makefiles
|
|
||||||
if (contains_unblocked_modules(soong, soong.reverse_makefiles[makefile.filename])
|
|
||||||
and is_clean(makefile))]
|
|
||||||
unblocked_makefiles = [Analysis(makefile.filename, []) for makefile in makefiles
|
|
||||||
if contains_unblocked_modules(soong,
|
|
||||||
soong.reverse_makefiles[makefile.filename])]
|
|
||||||
blocked_makefiles = [Analysis(makefile.filename, []) for makefile in makefiles
|
|
||||||
if contains_blocked_modules(soong, soong.reverse_makefiles[makefile.filename])]
|
|
||||||
|
|
||||||
print("""
|
|
||||||
<tr class="%(rowclass)s">
|
|
||||||
<td class="RowTitle">%(rowtitle)s</td>
|
|
||||||
<td class="Count">%(makefiles)s</td>
|
|
||||||
<td class="Count">%(easy)s</td>
|
|
||||||
<td class="Count">%(unblocked_clean)s</td>
|
|
||||||
<td class="Count">%(unblocked)s</td>
|
|
||||||
<td class="Count">%(blocked)s</td>
|
|
||||||
<td class="Count">%(clean)s</td>
|
|
||||||
""" % {
|
|
||||||
"rowclass": rowclass,
|
|
||||||
"rowtitle": rowtitle,
|
|
||||||
"makefiles": make_annotation_link(annotations, all_makefiles, modules),
|
|
||||||
"unblocked": make_annotation_link(annotations, unblocked_makefiles, modules),
|
|
||||||
"blocked": make_annotation_link(annotations, blocked_makefiles, modules),
|
|
||||||
"clean": make_annotation_link(annotations, clean_makefiles, modules),
|
|
||||||
"unblocked_clean": make_annotation_link(annotations, unblocked_clean_makefiles, modules),
|
|
||||||
"easy": make_annotation_link(annotations, easy_makefiles, modules),
|
|
||||||
})
|
|
||||||
|
|
||||||
for analyzer in ANALYZERS:
|
|
||||||
analyses = [m.analyses.get(analyzer) for m in makefiles if m.analyses.get(analyzer)]
|
|
||||||
print("""<td class="Count">%s</td>"""
|
|
||||||
% make_annotation_link(annotations, analyses, modules))
|
|
||||||
|
|
||||||
print(" </tr>")
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="Info about remaining Android.mk files.")
|
parser = argparse.ArgumentParser(description="Info about remaining Android.mk files.")
|
||||||
parser.add_argument("--device", type=str, required=True,
|
parser.add_argument("--device", type=str, required=True,
|
||||||
@@ -394,14 +327,11 @@ def main():
|
|||||||
args.out_dir = args.out_dir[:-1]
|
args.out_dir = args.out_dir[:-1]
|
||||||
|
|
||||||
TARGET_DEVICE = args.device
|
TARGET_DEVICE = args.device
|
||||||
|
global HOST_OUT_ROOT
|
||||||
HOST_OUT_ROOT = args.out_dir + "/host"
|
HOST_OUT_ROOT = args.out_dir + "/host"
|
||||||
|
global PRODUCT_OUT
|
||||||
PRODUCT_OUT = args.out_dir + "/target/product/%s" % TARGET_DEVICE
|
PRODUCT_OUT = args.out_dir + "/target/product/%s" % TARGET_DEVICE
|
||||||
|
|
||||||
if args.title:
|
|
||||||
page_title = args.title
|
|
||||||
else:
|
|
||||||
page_title = "Remaining Android.mk files"
|
|
||||||
|
|
||||||
# Read target information
|
# Read target information
|
||||||
# TODO: Pull from configurable location. This is also slightly different because it's
|
# TODO: Pull from configurable location. This is also slightly different because it's
|
||||||
# only a single build, where as the tree scanning we do below is all Android.mk files.
|
# only a single build, where as the tree scanning we do below is all Android.mk files.
|
||||||
@@ -409,10 +339,32 @@ def main():
|
|||||||
% PRODUCT_OUT, "r", errors="ignore") as csvfile:
|
% PRODUCT_OUT, "r", errors="ignore") as csvfile:
|
||||||
soong = SoongData(csv.reader(csvfile))
|
soong = SoongData(csv.reader(csvfile))
|
||||||
|
|
||||||
|
# Read the makefiles
|
||||||
|
all_makefiles = dict()
|
||||||
|
for filename, modules in soong.reverse_makefiles.items():
|
||||||
|
if filename.startswith(args.out_dir + "/"):
|
||||||
|
continue
|
||||||
|
all_makefiles[filename] = Makefile(filename)
|
||||||
|
|
||||||
|
HtmlProcessor(args=args, soong=soong, all_makefiles=all_makefiles).execute()
|
||||||
|
|
||||||
|
class HtmlProcessor(object):
|
||||||
|
def __init__(self, args, soong, all_makefiles):
|
||||||
|
self.args = args
|
||||||
|
self.soong = soong
|
||||||
|
self.all_makefiles = all_makefiles
|
||||||
|
self.annotations = Annotations()
|
||||||
|
|
||||||
|
def execute(self):
|
||||||
|
if self.args.title:
|
||||||
|
page_title = self.args.title
|
||||||
|
else:
|
||||||
|
page_title = "Remaining Android.mk files"
|
||||||
|
|
||||||
# Which modules are installed where
|
# Which modules are installed where
|
||||||
modules_by_partition = dict()
|
modules_by_partition = dict()
|
||||||
partitions = set()
|
partitions = set()
|
||||||
for installed, module in soong.installed.items():
|
for installed, module in self.soong.installed.items():
|
||||||
partition = get_partition_from_installed(HOST_OUT_ROOT, PRODUCT_OUT, installed)
|
partition = get_partition_from_installed(HOST_OUT_ROOT, PRODUCT_OUT, installed)
|
||||||
modules_by_partition.setdefault(partition, []).append(module)
|
modules_by_partition.setdefault(partition, []).append(module)
|
||||||
partitions.add(partition)
|
partitions.add(partition)
|
||||||
@@ -709,23 +661,22 @@ def main():
|
|||||||
</div>
|
</div>
|
||||||
""")
|
""")
|
||||||
|
|
||||||
annotations = Annotations()
|
|
||||||
overall_summary = Summary()
|
overall_summary = Summary()
|
||||||
|
|
||||||
# For each partition
|
# For each partition
|
||||||
makefiles_for_partitions = dict()
|
|
||||||
for partition in sorted(partitions):
|
for partition in sorted(partitions):
|
||||||
modules = modules_by_partition[partition]
|
modules = modules_by_partition[partition]
|
||||||
|
|
||||||
makefiles = set(itertools.chain.from_iterable(
|
makefiles = set(itertools.chain.from_iterable(
|
||||||
[soong.makefiles[module] for module in modules]))
|
[self.soong.makefiles[module] for module in modules]))
|
||||||
|
|
||||||
# Read makefiles
|
# Read makefiles
|
||||||
summary = Summary()
|
summary = Summary()
|
||||||
for filename in makefiles:
|
for filename in makefiles:
|
||||||
if not filename.startswith(args.out_dir + "/"):
|
makefile = self.all_makefiles.get(filename)
|
||||||
summary.Add(Makefile(filename))
|
if makefile:
|
||||||
overall_summary.Add(Makefile(filename))
|
summary.Add(makefile)
|
||||||
|
overall_summary.Add(makefile)
|
||||||
|
|
||||||
# Categorize directories by who is responsible
|
# Categorize directories by who is responsible
|
||||||
aosp_dirs = []
|
aosp_dirs = []
|
||||||
@@ -745,17 +696,18 @@ def main():
|
|||||||
(google_dirs, "GoogleDir"),
|
(google_dirs, "GoogleDir"),
|
||||||
(partner_dirs, "PartnerDir"),]:
|
(partner_dirs, "PartnerDir"),]:
|
||||||
for dirname in dirgroup:
|
for dirname in dirgroup:
|
||||||
print_analysis_row(soong, summary, annotations, modules,
|
self.print_analysis_row(summary, modules,
|
||||||
dirname, rowclass, summary.directories[dirname])
|
dirname, rowclass, summary.directories[dirname])
|
||||||
|
|
||||||
print_analysis_row(soong, summary, annotations, modules,
|
self.print_analysis_row(summary, modules,
|
||||||
"Total", "TotalRow",
|
"Total", "TotalRow",
|
||||||
set(itertools.chain.from_iterable(summary.directories.values())))
|
set(itertools.chain.from_iterable(summary.directories.values())))
|
||||||
print("""
|
print("""
|
||||||
</table>
|
</table>
|
||||||
""")
|
""")
|
||||||
|
|
||||||
module_details = [(count_deps(soong.deps, m, []), -count_deps(soong.reverse_deps, m, []), m)
|
module_details = [(count_deps(self.soong.deps, m, []),
|
||||||
|
-count_deps(self.soong.reverse_deps, m, []), m)
|
||||||
for m in modules]
|
for m in modules]
|
||||||
module_details.sort()
|
module_details.sort()
|
||||||
module_details = [m[2] for m in module_details]
|
module_details = [m[2] for m in module_details]
|
||||||
@@ -770,7 +722,7 @@ def main():
|
|||||||
altRow = True
|
altRow = True
|
||||||
for module in module_details:
|
for module in module_details:
|
||||||
analyses = set()
|
analyses = set()
|
||||||
for filename in soong.makefiles[module]:
|
for filename in self.soong.makefiles[module]:
|
||||||
makefile = summary.makefiles.get(filename)
|
makefile = summary.makefiles.get(filename)
|
||||||
if makefile:
|
if makefile:
|
||||||
for analyzer, analysis in makefile.analyses.items():
|
for analyzer, analysis in makefile.analyses.items():
|
||||||
@@ -782,17 +734,17 @@ def main():
|
|||||||
print(" <td><a name='module_%s'></a>%s</td>" % (module, module))
|
print(" <td><a name='module_%s'></a>%s</td>" % (module, module))
|
||||||
print(" <td class='AnalysisCol'>%s</td>" % " ".join(["<span class='Analysis'>%s</span>" % title
|
print(" <td class='AnalysisCol'>%s</td>" % " ".join(["<span class='Analysis'>%s</span>" % title
|
||||||
for title in analyses]))
|
for title in analyses]))
|
||||||
print(" <td>%s</td>" % count_deps(soong.deps, module, []))
|
print(" <td>%s</td>" % count_deps(self.soong.deps, module, []))
|
||||||
print(" <td>%s</td>" % format_module_list(soong.deps.get(module, [])))
|
print(" <td>%s</td>" % format_module_list(self.soong.deps.get(module, [])))
|
||||||
print(" <td>%s</td>" % count_deps(soong.reverse_deps, module, []))
|
print(" <td>%s</td>" % count_deps(self.soong.reverse_deps, module, []))
|
||||||
print(" <td>%s</td>" % format_module_list(soong.reverse_deps.get(module, [])))
|
print(" <td>%s</td>" % format_module_list(self.soong.reverse_deps.get(module, [])))
|
||||||
print("</tr>")
|
print("</tr>")
|
||||||
print("""</table>""")
|
print("""</table>""")
|
||||||
|
|
||||||
print_analysis_header("summary", "Overall Summary")
|
print_analysis_header("summary", "Overall Summary")
|
||||||
|
|
||||||
modules = [module for installed, module in soong.installed.items()]
|
modules = [module for installed, module in self.soong.installed.items()]
|
||||||
print_analysis_row(soong, overall_summary, annotations, modules,
|
self.print_analysis_row(overall_summary, modules,
|
||||||
"All Makefiles", "TotalRow",
|
"All Makefiles", "TotalRow",
|
||||||
set(itertools.chain.from_iterable(overall_summary.directories.values())))
|
set(itertools.chain.from_iterable(overall_summary.directories.values())))
|
||||||
print("""
|
print("""
|
||||||
@@ -924,16 +876,16 @@ def main():
|
|||||||
|
|
||||||
var ANALYSIS = [
|
var ANALYSIS = [
|
||||||
""" % {
|
""" % {
|
||||||
"codesearch": args.codesearch,
|
"codesearch": self.args.codesearch,
|
||||||
})
|
})
|
||||||
for entry, mods in annotations.entries:
|
for entry, mods in self.annotations.entries:
|
||||||
print(" [")
|
print(" [")
|
||||||
for analysis in entry:
|
for analysis in entry:
|
||||||
print(" new Analysis('%(filename)s', %(modules)s, [%(line_matches)s])," % {
|
print(" new Analysis('%(filename)s', %(modules)s, [%(line_matches)s])," % {
|
||||||
"filename": analysis.filename,
|
"filename": analysis.filename,
|
||||||
#"modules": json.dumps([m for m in mods if m in filename in soong.makefiles[m]]),
|
#"modules": json.dumps([m for m in mods if m in filename in self.soong.makefiles[m]]),
|
||||||
"modules": json.dumps(
|
"modules": json.dumps(
|
||||||
[m for m in soong.reverse_makefiles[analysis.filename] if m in mods]),
|
[m for m in self.soong.reverse_makefiles[analysis.filename] if m in mods]),
|
||||||
"line_matches": ", ".join([
|
"line_matches": ", ".join([
|
||||||
"new LineMatch(%d, %s)" % (lineno, json.dumps(text))
|
"new LineMatch(%d, %s)" % (lineno, json.dumps(text))
|
||||||
for lineno, text in analysis.line_matches]),
|
for lineno, text in analysis.line_matches]),
|
||||||
@@ -943,10 +895,10 @@ def main():
|
|||||||
];
|
];
|
||||||
var MODULE_DATA = {
|
var MODULE_DATA = {
|
||||||
""")
|
""")
|
||||||
for module in soong.modules:
|
for module in self.soong.modules:
|
||||||
print(" '%(name)s': new Module(%(deps)s)," % {
|
print(" '%(name)s': new Module(%(deps)s)," % {
|
||||||
"name": module,
|
"name": module,
|
||||||
"deps": json.dumps(soong.deps[module]),
|
"deps": json.dumps(self.soong.deps[module]),
|
||||||
})
|
})
|
||||||
print("""
|
print("""
|
||||||
};
|
};
|
||||||
@@ -968,6 +920,70 @@ def main():
|
|||||||
</html>
|
</html>
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
def traverse_ready_makefiles(self, summary, makefiles):
|
||||||
|
def clean_and_only_blocked_by_clean(makefile):
|
||||||
|
if not is_clean(makefile):
|
||||||
|
return False
|
||||||
|
modules = self.soong.reverse_makefiles[makefile.filename]
|
||||||
|
for module in modules:
|
||||||
|
for dep in self.soong.transitive_deps(module):
|
||||||
|
for m in self.soong.makefiles.get(dep, []):
|
||||||
|
if not summary.IsClean(m):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
return [Analysis(makefile.filename, []) for makefile in makefiles
|
||||||
|
if clean_and_only_blocked_by_clean(makefile)]
|
||||||
|
|
||||||
|
def print_analysis_row(self, summary, modules, rowtitle, rowclass, makefiles):
|
||||||
|
all_makefiles = [Analysis(makefile.filename, []) for makefile in makefiles]
|
||||||
|
clean_makefiles = [Analysis(makefile.filename, []) for makefile in makefiles
|
||||||
|
if is_clean(makefile)]
|
||||||
|
easy_makefiles = self.traverse_ready_makefiles(summary, makefiles)
|
||||||
|
unblocked_clean_makefiles = [Analysis(makefile.filename, []) for makefile in makefiles
|
||||||
|
if (self.soong.contains_unblocked_modules(makefile.filename)
|
||||||
|
and is_clean(makefile))]
|
||||||
|
unblocked_makefiles = [Analysis(makefile.filename, []) for makefile in makefiles
|
||||||
|
if self.soong.contains_unblocked_modules(makefile.filename)]
|
||||||
|
blocked_makefiles = [Analysis(makefile.filename, []) for makefile in makefiles
|
||||||
|
if self.soong.contains_blocked_modules(makefile.filename)]
|
||||||
|
|
||||||
|
print("""
|
||||||
|
<tr class="%(rowclass)s">
|
||||||
|
<td class="RowTitle">%(rowtitle)s</td>
|
||||||
|
<td class="Count">%(makefiles)s</td>
|
||||||
|
<td class="Count">%(easy)s</td>
|
||||||
|
<td class="Count">%(unblocked_clean)s</td>
|
||||||
|
<td class="Count">%(unblocked)s</td>
|
||||||
|
<td class="Count">%(blocked)s</td>
|
||||||
|
<td class="Count">%(clean)s</td>
|
||||||
|
""" % {
|
||||||
|
"rowclass": rowclass,
|
||||||
|
"rowtitle": rowtitle,
|
||||||
|
"makefiles": self.make_annotation_link(all_makefiles, modules),
|
||||||
|
"unblocked": self.make_annotation_link(unblocked_makefiles, modules),
|
||||||
|
"blocked": self.make_annotation_link(blocked_makefiles, modules),
|
||||||
|
"clean": self.make_annotation_link(clean_makefiles, modules),
|
||||||
|
"unblocked_clean": self.make_annotation_link(unblocked_clean_makefiles, modules),
|
||||||
|
"easy": self.make_annotation_link(easy_makefiles, modules),
|
||||||
|
})
|
||||||
|
|
||||||
|
for analyzer in ANALYZERS:
|
||||||
|
analyses = [m.analyses.get(analyzer) for m in makefiles if m.analyses.get(analyzer)]
|
||||||
|
print("""<td class="Count">%s</td>"""
|
||||||
|
% self.make_annotation_link(analyses, modules))
|
||||||
|
|
||||||
|
print(" </tr>")
|
||||||
|
|
||||||
|
def make_annotation_link(self, analysis, modules):
|
||||||
|
if analysis:
|
||||||
|
return "<a href='javascript:update_details(%d)'>%s</a>" % (
|
||||||
|
self.annotations.Add(analysis, modules),
|
||||||
|
len(analysis)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return "";
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user