xref: /aosp_15_r20/build/make/tools/mk2bp_catalog.py (revision 9e94795a3d4ef5c1d47486f9a02bb378756cea8a)
1*9e94795aSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*9e94795aSAndroid Build Coastguard Worker
3*9e94795aSAndroid Build Coastguard Worker"""
4*9e94795aSAndroid Build Coastguard WorkerCommand to print info about makefiles remaining to be converted to soong.
5*9e94795aSAndroid Build Coastguard Worker
6*9e94795aSAndroid Build Coastguard WorkerSee usage / argument parsing below for commandline options.
7*9e94795aSAndroid Build Coastguard Worker"""
8*9e94795aSAndroid Build Coastguard Worker
9*9e94795aSAndroid Build Coastguard Workerimport argparse
10*9e94795aSAndroid Build Coastguard Workerimport csv
11*9e94795aSAndroid Build Coastguard Workerimport itertools
12*9e94795aSAndroid Build Coastguard Workerimport json
13*9e94795aSAndroid Build Coastguard Workerimport os
14*9e94795aSAndroid Build Coastguard Workerimport re
15*9e94795aSAndroid Build Coastguard Workerimport sys
16*9e94795aSAndroid Build Coastguard Worker
17*9e94795aSAndroid Build Coastguard WorkerDIRECTORY_PATTERNS = [x.split("/") for x in (
18*9e94795aSAndroid Build Coastguard Worker  "device/*",
19*9e94795aSAndroid Build Coastguard Worker  "frameworks/*",
20*9e94795aSAndroid Build Coastguard Worker  "hardware/*",
21*9e94795aSAndroid Build Coastguard Worker  "packages/*",
22*9e94795aSAndroid Build Coastguard Worker  "vendor/*",
23*9e94795aSAndroid Build Coastguard Worker  "*",
24*9e94795aSAndroid Build Coastguard Worker)]
25*9e94795aSAndroid Build Coastguard Worker
26*9e94795aSAndroid Build Coastguard Workerdef match_directory_group(pattern, filename):
27*9e94795aSAndroid Build Coastguard Worker  match = []
28*9e94795aSAndroid Build Coastguard Worker  filename = filename.split("/")
29*9e94795aSAndroid Build Coastguard Worker  if len(filename) < len(pattern):
30*9e94795aSAndroid Build Coastguard Worker    return None
31*9e94795aSAndroid Build Coastguard Worker  for i in range(len(pattern)):
32*9e94795aSAndroid Build Coastguard Worker    pattern_segment = pattern[i]
33*9e94795aSAndroid Build Coastguard Worker    filename_segment = filename[i]
34*9e94795aSAndroid Build Coastguard Worker    if pattern_segment == "*" or pattern_segment == filename_segment:
35*9e94795aSAndroid Build Coastguard Worker      match.append(filename_segment)
36*9e94795aSAndroid Build Coastguard Worker    else:
37*9e94795aSAndroid Build Coastguard Worker      return None
38*9e94795aSAndroid Build Coastguard Worker  if match:
39*9e94795aSAndroid Build Coastguard Worker    return os.path.sep.join(match)
40*9e94795aSAndroid Build Coastguard Worker  else:
41*9e94795aSAndroid Build Coastguard Worker    return None
42*9e94795aSAndroid Build Coastguard Worker
43*9e94795aSAndroid Build Coastguard Workerdef directory_group(filename):
44*9e94795aSAndroid Build Coastguard Worker  for pattern in DIRECTORY_PATTERNS:
45*9e94795aSAndroid Build Coastguard Worker    match = match_directory_group(pattern, filename)
46*9e94795aSAndroid Build Coastguard Worker    if match:
47*9e94795aSAndroid Build Coastguard Worker      return match
48*9e94795aSAndroid Build Coastguard Worker  return os.path.dirname(filename)
49*9e94795aSAndroid Build Coastguard Worker
50*9e94795aSAndroid Build Coastguard Workerclass Analysis(object):
51*9e94795aSAndroid Build Coastguard Worker  def __init__(self, filename, line_matches):
52*9e94795aSAndroid Build Coastguard Worker    self.filename = filename;
53*9e94795aSAndroid Build Coastguard Worker    self.line_matches = line_matches
54*9e94795aSAndroid Build Coastguard Worker
55*9e94795aSAndroid Build Coastguard Workerdef analyze_lines(filename, lines, func):
56*9e94795aSAndroid Build Coastguard Worker  line_matches = []
57*9e94795aSAndroid Build Coastguard Worker  for i in range(len(lines)):
58*9e94795aSAndroid Build Coastguard Worker    line = lines[i]
59*9e94795aSAndroid Build Coastguard Worker    stripped = line.strip()
60*9e94795aSAndroid Build Coastguard Worker    if stripped.startswith("#"):
61*9e94795aSAndroid Build Coastguard Worker      continue
62*9e94795aSAndroid Build Coastguard Worker    if func(stripped):
63*9e94795aSAndroid Build Coastguard Worker      line_matches.append((i+1, line))
64*9e94795aSAndroid Build Coastguard Worker  if line_matches:
65*9e94795aSAndroid Build Coastguard Worker    return Analysis(filename, line_matches);
66*9e94795aSAndroid Build Coastguard Worker
67*9e94795aSAndroid Build Coastguard Workerdef analyze_has_conditional(line):
68*9e94795aSAndroid Build Coastguard Worker  return (line.startswith("ifeq") or line.startswith("ifneq")
69*9e94795aSAndroid Build Coastguard Worker          or line.startswith("ifdef") or line.startswith("ifndef"))
70*9e94795aSAndroid Build Coastguard Worker
71*9e94795aSAndroid Build Coastguard WorkerNORMAL_INCLUDES = [re.compile(pattern) for pattern in (
72*9e94795aSAndroid Build Coastguard Worker  "include \$+\(CLEAR_VARS\)", # These are in defines which are tagged separately
73*9e94795aSAndroid Build Coastguard Worker  "include \$+\(BUILD_.*\)",
74*9e94795aSAndroid Build Coastguard Worker  "include \$\(call first-makefiles-under, *\$\(LOCAL_PATH\)\)",
75*9e94795aSAndroid Build Coastguard Worker  "include \$\(call all-subdir-makefiles\)",
76*9e94795aSAndroid Build Coastguard Worker  "include \$\(all-subdir-makefiles\)",
77*9e94795aSAndroid Build Coastguard Worker  "include \$\(call all-makefiles-under, *\$\(LOCAL_PATH\)\)",
78*9e94795aSAndroid Build Coastguard Worker  "include \$\(call all-makefiles-under, *\$\(call my-dir\).*\)",
79*9e94795aSAndroid Build Coastguard Worker  "include \$\(BUILD_SYSTEM\)/base_rules.mk", # called out separately
80*9e94795aSAndroid Build Coastguard Worker  "include \$\(call all-named-subdir-makefiles,.*\)",
81*9e94795aSAndroid Build Coastguard Worker  "include \$\(subdirs\)",
82*9e94795aSAndroid Build Coastguard Worker)]
83*9e94795aSAndroid Build Coastguard Workerdef analyze_has_wacky_include(line):
84*9e94795aSAndroid Build Coastguard Worker  if not (line.startswith("include") or line.startswith("-include")
85*9e94795aSAndroid Build Coastguard Worker          or line.startswith("sinclude")):
86*9e94795aSAndroid Build Coastguard Worker    return False
87*9e94795aSAndroid Build Coastguard Worker  for matcher in NORMAL_INCLUDES:
88*9e94795aSAndroid Build Coastguard Worker    if matcher.fullmatch(line):
89*9e94795aSAndroid Build Coastguard Worker      return False
90*9e94795aSAndroid Build Coastguard Worker  return True
91*9e94795aSAndroid Build Coastguard Worker
92*9e94795aSAndroid Build Coastguard WorkerBASE_RULES_RE = re.compile("include \$\(BUILD_SYSTEM\)/base_rules.mk")
93*9e94795aSAndroid Build Coastguard Worker
94*9e94795aSAndroid Build Coastguard Workerclass Analyzer(object):
95*9e94795aSAndroid Build Coastguard Worker  def __init__(self, title, func):
96*9e94795aSAndroid Build Coastguard Worker    self.title = title;
97*9e94795aSAndroid Build Coastguard Worker    self.func = func
98*9e94795aSAndroid Build Coastguard Worker
99*9e94795aSAndroid Build Coastguard Worker
100*9e94795aSAndroid Build Coastguard WorkerANALYZERS = (
101*9e94795aSAndroid Build Coastguard Worker  Analyzer("ifeq / ifneq", analyze_has_conditional),
102*9e94795aSAndroid Build Coastguard Worker  Analyzer("Wacky Includes", analyze_has_wacky_include),
103*9e94795aSAndroid Build Coastguard Worker  Analyzer("Calls base_rules", lambda line: BASE_RULES_RE.fullmatch(line)),
104*9e94795aSAndroid Build Coastguard Worker  Analyzer("Calls define", lambda line: line.startswith("define ")),
105*9e94795aSAndroid Build Coastguard Worker  Analyzer("Has ../", lambda line: "../" in line),
106*9e94795aSAndroid Build Coastguard Worker  Analyzer("dist-for-&#8203;goals", lambda line: "dist-for-goals" in line),
107*9e94795aSAndroid Build Coastguard Worker  Analyzer(".PHONY", lambda line: ".PHONY" in line),
108*9e94795aSAndroid Build Coastguard Worker  Analyzer("render-&#8203;script", lambda line: ".rscript" in line),
109*9e94795aSAndroid Build Coastguard Worker  Analyzer("vts src", lambda line: ".vts" in line),
110*9e94795aSAndroid Build Coastguard Worker  Analyzer("COPY_&#8203;HEADERS", lambda line: "LOCAL_COPY_HEADERS" in line),
111*9e94795aSAndroid Build Coastguard Worker)
112*9e94795aSAndroid Build Coastguard Worker
113*9e94795aSAndroid Build Coastguard Workerclass Summary(object):
114*9e94795aSAndroid Build Coastguard Worker  def __init__(self):
115*9e94795aSAndroid Build Coastguard Worker    self.makefiles = dict()
116*9e94795aSAndroid Build Coastguard Worker    self.directories = dict()
117*9e94795aSAndroid Build Coastguard Worker
118*9e94795aSAndroid Build Coastguard Worker  def Add(self, makefile):
119*9e94795aSAndroid Build Coastguard Worker    self.makefiles[makefile.filename] = makefile
120*9e94795aSAndroid Build Coastguard Worker    self.directories.setdefault(directory_group(makefile.filename), []).append(makefile)
121*9e94795aSAndroid Build Coastguard Worker
122*9e94795aSAndroid Build Coastguard Workerclass Makefile(object):
123*9e94795aSAndroid Build Coastguard Worker  def __init__(self, filename):
124*9e94795aSAndroid Build Coastguard Worker    self.filename = filename
125*9e94795aSAndroid Build Coastguard Worker
126*9e94795aSAndroid Build Coastguard Worker    # Analyze the file
127*9e94795aSAndroid Build Coastguard Worker    with open(filename, "r", errors="ignore") as f:
128*9e94795aSAndroid Build Coastguard Worker      try:
129*9e94795aSAndroid Build Coastguard Worker        lines = f.readlines()
130*9e94795aSAndroid Build Coastguard Worker      except UnicodeDecodeError as ex:
131*9e94795aSAndroid Build Coastguard Worker        sys.stderr.write("Filename: %s\n" % filename)
132*9e94795aSAndroid Build Coastguard Worker        raise ex
133*9e94795aSAndroid Build Coastguard Worker    lines = [line.strip() for line in lines]
134*9e94795aSAndroid Build Coastguard Worker
135*9e94795aSAndroid Build Coastguard Worker    self.analyses = dict([(analyzer, analyze_lines(filename, lines, analyzer.func)) for analyzer
136*9e94795aSAndroid Build Coastguard Worker        in ANALYZERS])
137*9e94795aSAndroid Build Coastguard Worker
138*9e94795aSAndroid Build Coastguard Workerdef find_android_mk():
139*9e94795aSAndroid Build Coastguard Worker  cwd = os.getcwd()
140*9e94795aSAndroid Build Coastguard Worker  for root, dirs, files in os.walk(cwd):
141*9e94795aSAndroid Build Coastguard Worker    for filename in files:
142*9e94795aSAndroid Build Coastguard Worker      if filename == "Android.mk":
143*9e94795aSAndroid Build Coastguard Worker        yield os.path.join(root, filename)[len(cwd) + 1:]
144*9e94795aSAndroid Build Coastguard Worker    for ignore in (".git", ".repo"):
145*9e94795aSAndroid Build Coastguard Worker      if ignore in dirs:
146*9e94795aSAndroid Build Coastguard Worker        dirs.remove(ignore)
147*9e94795aSAndroid Build Coastguard Worker
148*9e94795aSAndroid Build Coastguard Workerdef is_aosp(dirname):
149*9e94795aSAndroid Build Coastguard Worker  for d in ("device/sample", "hardware/interfaces", "hardware/libhardware",
150*9e94795aSAndroid Build Coastguard Worker          "hardware/ril"):
151*9e94795aSAndroid Build Coastguard Worker    if dirname.startswith(d):
152*9e94795aSAndroid Build Coastguard Worker      return True
153*9e94795aSAndroid Build Coastguard Worker  for d in ("device/", "hardware/", "vendor/"):
154*9e94795aSAndroid Build Coastguard Worker    if dirname.startswith(d):
155*9e94795aSAndroid Build Coastguard Worker      return False
156*9e94795aSAndroid Build Coastguard Worker  return True
157*9e94795aSAndroid Build Coastguard Worker
158*9e94795aSAndroid Build Coastguard Workerdef is_google(dirname):
159*9e94795aSAndroid Build Coastguard Worker  for d in ("device/google",
160*9e94795aSAndroid Build Coastguard Worker            "hardware/google",
161*9e94795aSAndroid Build Coastguard Worker            "test/sts",
162*9e94795aSAndroid Build Coastguard Worker            "vendor/auto",
163*9e94795aSAndroid Build Coastguard Worker            "vendor/google",
164*9e94795aSAndroid Build Coastguard Worker            "vendor/unbundled_google",
165*9e94795aSAndroid Build Coastguard Worker            "vendor/widevine",
166*9e94795aSAndroid Build Coastguard Worker            "vendor/xts"):
167*9e94795aSAndroid Build Coastguard Worker    if dirname.startswith(d):
168*9e94795aSAndroid Build Coastguard Worker      return True
169*9e94795aSAndroid Build Coastguard Worker  return False
170*9e94795aSAndroid Build Coastguard Worker
171*9e94795aSAndroid Build Coastguard Workerdef is_clean(makefile):
172*9e94795aSAndroid Build Coastguard Worker  for analysis in makefile.analyses.values():
173*9e94795aSAndroid Build Coastguard Worker    if analysis:
174*9e94795aSAndroid Build Coastguard Worker      return False
175*9e94795aSAndroid Build Coastguard Worker  return True
176*9e94795aSAndroid Build Coastguard Worker
177*9e94795aSAndroid Build Coastguard Workerdef clean_and_only_blocked_by_clean(soong, all_makefiles, makefile):
178*9e94795aSAndroid Build Coastguard Worker  if not is_clean(makefile):
179*9e94795aSAndroid Build Coastguard Worker    return False
180*9e94795aSAndroid Build Coastguard Worker  modules = soong.reverse_makefiles[makefile.filename]
181*9e94795aSAndroid Build Coastguard Worker  for module in modules:
182*9e94795aSAndroid Build Coastguard Worker    for dep in soong.transitive_deps(module):
183*9e94795aSAndroid Build Coastguard Worker      for filename in soong.makefiles.get(dep, []):
184*9e94795aSAndroid Build Coastguard Worker        m = all_makefiles.get(filename)
185*9e94795aSAndroid Build Coastguard Worker        if m and not is_clean(m):
186*9e94795aSAndroid Build Coastguard Worker          return False
187*9e94795aSAndroid Build Coastguard Worker  return True
188*9e94795aSAndroid Build Coastguard Worker
189*9e94795aSAndroid Build Coastguard Workerclass Annotations(object):
190*9e94795aSAndroid Build Coastguard Worker  def __init__(self):
191*9e94795aSAndroid Build Coastguard Worker    self.entries = []
192*9e94795aSAndroid Build Coastguard Worker    self.count = 0
193*9e94795aSAndroid Build Coastguard Worker
194*9e94795aSAndroid Build Coastguard Worker  def Add(self, makefiles, modules):
195*9e94795aSAndroid Build Coastguard Worker    self.entries.append((makefiles, modules))
196*9e94795aSAndroid Build Coastguard Worker    self.count += 1
197*9e94795aSAndroid Build Coastguard Worker    return self.count-1
198*9e94795aSAndroid Build Coastguard Worker
199*9e94795aSAndroid Build Coastguard Workerclass SoongData(object):
200*9e94795aSAndroid Build Coastguard Worker  def __init__(self, reader):
201*9e94795aSAndroid Build Coastguard Worker    """Read the input file and store the modules and dependency mappings.
202*9e94795aSAndroid Build Coastguard Worker    """
203*9e94795aSAndroid Build Coastguard Worker    self.problems = dict()
204*9e94795aSAndroid Build Coastguard Worker    self.deps = dict()
205*9e94795aSAndroid Build Coastguard Worker    self.reverse_deps = dict()
206*9e94795aSAndroid Build Coastguard Worker    self.module_types = dict()
207*9e94795aSAndroid Build Coastguard Worker    self.makefiles = dict()
208*9e94795aSAndroid Build Coastguard Worker    self.reverse_makefiles = dict()
209*9e94795aSAndroid Build Coastguard Worker    self.installed = dict()
210*9e94795aSAndroid Build Coastguard Worker    self.reverse_installed = dict()
211*9e94795aSAndroid Build Coastguard Worker    self.modules = set()
212*9e94795aSAndroid Build Coastguard Worker
213*9e94795aSAndroid Build Coastguard Worker    for (module, module_type, problem, dependencies, makefiles, installed) in reader:
214*9e94795aSAndroid Build Coastguard Worker      self.modules.add(module)
215*9e94795aSAndroid Build Coastguard Worker      makefiles = [f for f in makefiles.strip().split(' ') if f != ""]
216*9e94795aSAndroid Build Coastguard Worker      self.module_types[module] = module_type
217*9e94795aSAndroid Build Coastguard Worker      self.problems[module] = problem
218*9e94795aSAndroid Build Coastguard Worker      self.deps[module] = [d for d in dependencies.strip().split(' ') if d != ""]
219*9e94795aSAndroid Build Coastguard Worker      for dep in self.deps[module]:
220*9e94795aSAndroid Build Coastguard Worker        if not dep in self.reverse_deps:
221*9e94795aSAndroid Build Coastguard Worker          self.reverse_deps[dep] = []
222*9e94795aSAndroid Build Coastguard Worker        self.reverse_deps[dep].append(module)
223*9e94795aSAndroid Build Coastguard Worker      self.makefiles[module] = makefiles
224*9e94795aSAndroid Build Coastguard Worker      for f in makefiles:
225*9e94795aSAndroid Build Coastguard Worker        self.reverse_makefiles.setdefault(f, []).append(module)
226*9e94795aSAndroid Build Coastguard Worker      for f in installed.strip().split(' '):
227*9e94795aSAndroid Build Coastguard Worker        self.installed[f] = module
228*9e94795aSAndroid Build Coastguard Worker        self.reverse_installed.setdefault(module, []).append(f)
229*9e94795aSAndroid Build Coastguard Worker
230*9e94795aSAndroid Build Coastguard Worker  def transitive_deps(self, module):
231*9e94795aSAndroid Build Coastguard Worker    results = set()
232*9e94795aSAndroid Build Coastguard Worker    def traverse(module):
233*9e94795aSAndroid Build Coastguard Worker      for dep in self.deps.get(module, []):
234*9e94795aSAndroid Build Coastguard Worker        if not dep in results:
235*9e94795aSAndroid Build Coastguard Worker          results.add(dep)
236*9e94795aSAndroid Build Coastguard Worker          traverse(module)
237*9e94795aSAndroid Build Coastguard Worker    traverse(module)
238*9e94795aSAndroid Build Coastguard Worker    return results
239*9e94795aSAndroid Build Coastguard Worker
240*9e94795aSAndroid Build Coastguard Worker  def contains_unblocked_modules(self, filename):
241*9e94795aSAndroid Build Coastguard Worker    for m in self.reverse_makefiles[filename]:
242*9e94795aSAndroid Build Coastguard Worker      if len(self.deps[m]) == 0:
243*9e94795aSAndroid Build Coastguard Worker        return True
244*9e94795aSAndroid Build Coastguard Worker    return False
245*9e94795aSAndroid Build Coastguard Worker
246*9e94795aSAndroid Build Coastguard Worker  def contains_blocked_modules(self, filename):
247*9e94795aSAndroid Build Coastguard Worker    for m in self.reverse_makefiles[filename]:
248*9e94795aSAndroid Build Coastguard Worker      if len(self.deps[m]) > 0:
249*9e94795aSAndroid Build Coastguard Worker        return True
250*9e94795aSAndroid Build Coastguard Worker    return False
251*9e94795aSAndroid Build Coastguard Worker
252*9e94795aSAndroid Build Coastguard Workerdef count_deps(depsdb, module, seen):
253*9e94795aSAndroid Build Coastguard Worker  """Based on the depsdb, count the number of transitive dependencies.
254*9e94795aSAndroid Build Coastguard Worker
255*9e94795aSAndroid Build Coastguard Worker  You can pass in an reversed dependency graph to count the number of
256*9e94795aSAndroid Build Coastguard Worker  modules that depend on the module."""
257*9e94795aSAndroid Build Coastguard Worker  count = 0
258*9e94795aSAndroid Build Coastguard Worker  seen.append(module)
259*9e94795aSAndroid Build Coastguard Worker  if module in depsdb:
260*9e94795aSAndroid Build Coastguard Worker    for dep in depsdb[module]:
261*9e94795aSAndroid Build Coastguard Worker      if dep in seen:
262*9e94795aSAndroid Build Coastguard Worker        continue
263*9e94795aSAndroid Build Coastguard Worker      count += 1 + count_deps(depsdb, dep, seen)
264*9e94795aSAndroid Build Coastguard Worker  return count
265*9e94795aSAndroid Build Coastguard Worker
266*9e94795aSAndroid Build Coastguard WorkerOTHER_PARTITON = "_other"
267*9e94795aSAndroid Build Coastguard WorkerHOST_PARTITON = "_host"
268*9e94795aSAndroid Build Coastguard Worker
269*9e94795aSAndroid Build Coastguard Workerdef get_partition_from_installed(HOST_OUT_ROOT, PRODUCT_OUT, filename):
270*9e94795aSAndroid Build Coastguard Worker  host_prefix = HOST_OUT_ROOT + "/"
271*9e94795aSAndroid Build Coastguard Worker  device_prefix = PRODUCT_OUT + "/"
272*9e94795aSAndroid Build Coastguard Worker
273*9e94795aSAndroid Build Coastguard Worker  if filename.startswith(host_prefix):
274*9e94795aSAndroid Build Coastguard Worker    return HOST_PARTITON
275*9e94795aSAndroid Build Coastguard Worker
276*9e94795aSAndroid Build Coastguard Worker  elif filename.startswith(device_prefix):
277*9e94795aSAndroid Build Coastguard Worker    index = filename.find("/", len(device_prefix))
278*9e94795aSAndroid Build Coastguard Worker    if index < 0:
279*9e94795aSAndroid Build Coastguard Worker      return OTHER_PARTITON
280*9e94795aSAndroid Build Coastguard Worker    return filename[len(device_prefix):index]
281*9e94795aSAndroid Build Coastguard Worker
282*9e94795aSAndroid Build Coastguard Worker  return OTHER_PARTITON
283*9e94795aSAndroid Build Coastguard Worker
284*9e94795aSAndroid Build Coastguard Workerdef format_module_link(module):
285*9e94795aSAndroid Build Coastguard Worker  return "<a class='ModuleLink' href='#module_%s'>%s</a>" % (module, module)
286*9e94795aSAndroid Build Coastguard Worker
287*9e94795aSAndroid Build Coastguard Workerdef format_module_list(modules):
288*9e94795aSAndroid Build Coastguard Worker  return "".join(["<div>%s</div>" % format_module_link(m) for m in modules])
289*9e94795aSAndroid Build Coastguard Worker
290*9e94795aSAndroid Build Coastguard Workerdef print_analysis_header(link, title):
291*9e94795aSAndroid Build Coastguard Worker  print("""
292*9e94795aSAndroid Build Coastguard Worker    <a name="%(link)s"></a>
293*9e94795aSAndroid Build Coastguard Worker    <h2>%(title)s</h2>
294*9e94795aSAndroid Build Coastguard Worker    <table>
295*9e94795aSAndroid Build Coastguard Worker      <tr>
296*9e94795aSAndroid Build Coastguard Worker        <th class="RowTitle">Directory</th>
297*9e94795aSAndroid Build Coastguard Worker        <th class="Count">Total</th>
298*9e94795aSAndroid Build Coastguard Worker        <th class="Count Clean">Easy</th>
299*9e94795aSAndroid Build Coastguard Worker        <th class="Count Clean">Unblocked Clean</th>
300*9e94795aSAndroid Build Coastguard Worker        <th class="Count Unblocked">Unblocked</th>
301*9e94795aSAndroid Build Coastguard Worker        <th class="Count Blocked">Blocked</th>
302*9e94795aSAndroid Build Coastguard Worker        <th class="Count Clean">Clean</th>
303*9e94795aSAndroid Build Coastguard Worker  """ % {
304*9e94795aSAndroid Build Coastguard Worker    "link": link,
305*9e94795aSAndroid Build Coastguard Worker    "title": title
306*9e94795aSAndroid Build Coastguard Worker  })
307*9e94795aSAndroid Build Coastguard Worker  for analyzer in ANALYZERS:
308*9e94795aSAndroid Build Coastguard Worker    print("""<th class="Count Warning">%s</th>""" % analyzer.title)
309*9e94795aSAndroid Build Coastguard Worker  print("      </tr>")
310*9e94795aSAndroid Build Coastguard Worker
311*9e94795aSAndroid Build Coastguard Worker# get all modules in $(PRODUCT_PACKAGE) and the corresponding deps
312*9e94795aSAndroid Build Coastguard Workerdef get_module_product_packages_plus_deps(initial_modules, result, soong_data):
313*9e94795aSAndroid Build Coastguard Worker  for module in initial_modules:
314*9e94795aSAndroid Build Coastguard Worker    if module in result:
315*9e94795aSAndroid Build Coastguard Worker      continue
316*9e94795aSAndroid Build Coastguard Worker    result.add(module)
317*9e94795aSAndroid Build Coastguard Worker    if module in soong_data.deps:
318*9e94795aSAndroid Build Coastguard Worker      get_module_product_packages_plus_deps(soong_data.deps[module], result, soong_data)
319*9e94795aSAndroid Build Coastguard Worker
320*9e94795aSAndroid Build Coastguard Workerdef main():
321*9e94795aSAndroid Build Coastguard Worker  parser = argparse.ArgumentParser(description="Info about remaining Android.mk files.")
322*9e94795aSAndroid Build Coastguard Worker  parser.add_argument("--device", type=str, required=True,
323*9e94795aSAndroid Build Coastguard Worker                      help="TARGET_DEVICE")
324*9e94795aSAndroid Build Coastguard Worker  parser.add_argument("--product-packages", type=argparse.FileType('r'),
325*9e94795aSAndroid Build Coastguard Worker                      default=None,
326*9e94795aSAndroid Build Coastguard Worker                      help="PRODUCT_PACKAGES")
327*9e94795aSAndroid Build Coastguard Worker  parser.add_argument("--title", type=str,
328*9e94795aSAndroid Build Coastguard Worker                      help="page title")
329*9e94795aSAndroid Build Coastguard Worker  parser.add_argument("--codesearch", type=str,
330*9e94795aSAndroid Build Coastguard Worker                      default="https://cs.android.com/android/platform/superproject/+/master:",
331*9e94795aSAndroid Build Coastguard Worker                      help="page title")
332*9e94795aSAndroid Build Coastguard Worker  parser.add_argument("--out-dir", type=str,
333*9e94795aSAndroid Build Coastguard Worker                      default=None,
334*9e94795aSAndroid Build Coastguard Worker                      help="Equivalent of $OUT_DIR, which will also be checked if"
335*9e94795aSAndroid Build Coastguard Worker                        + " --out-dir is unset. If neither is set, default is"
336*9e94795aSAndroid Build Coastguard Worker                        + " 'out'.")
337*9e94795aSAndroid Build Coastguard Worker  parser.add_argument("--mode", type=str,
338*9e94795aSAndroid Build Coastguard Worker                      default="html",
339*9e94795aSAndroid Build Coastguard Worker                      help="output format: csv or html")
340*9e94795aSAndroid Build Coastguard Worker
341*9e94795aSAndroid Build Coastguard Worker  args = parser.parse_args()
342*9e94795aSAndroid Build Coastguard Worker
343*9e94795aSAndroid Build Coastguard Worker  # Guess out directory name
344*9e94795aSAndroid Build Coastguard Worker  if not args.out_dir:
345*9e94795aSAndroid Build Coastguard Worker    args.out_dir = os.getenv("OUT_DIR", "out")
346*9e94795aSAndroid Build Coastguard Worker  while args.out_dir.endswith("/") and len(args.out_dir) > 1:
347*9e94795aSAndroid Build Coastguard Worker    args.out_dir = args.out_dir[:-1]
348*9e94795aSAndroid Build Coastguard Worker
349*9e94795aSAndroid Build Coastguard Worker  TARGET_DEVICE = args.device
350*9e94795aSAndroid Build Coastguard Worker  global HOST_OUT_ROOT
351*9e94795aSAndroid Build Coastguard Worker  HOST_OUT_ROOT = args.out_dir + "/host"
352*9e94795aSAndroid Build Coastguard Worker  global PRODUCT_OUT
353*9e94795aSAndroid Build Coastguard Worker  PRODUCT_OUT = args.out_dir + "/target/product/%s" % TARGET_DEVICE
354*9e94795aSAndroid Build Coastguard Worker
355*9e94795aSAndroid Build Coastguard Worker  # Read target information
356*9e94795aSAndroid Build Coastguard Worker  # TODO: Pull from configurable location. This is also slightly different because it's
357*9e94795aSAndroid Build Coastguard Worker  # only a single build, where as the tree scanning we do below is all Android.mk files.
358*9e94795aSAndroid Build Coastguard Worker  with open("%s/obj/PACKAGING/soong_conversion_intermediates/soong_conv_data"
359*9e94795aSAndroid Build Coastguard Worker      % PRODUCT_OUT, "r", errors="ignore") as csvfile:
360*9e94795aSAndroid Build Coastguard Worker    soong = SoongData(csv.reader(csvfile))
361*9e94795aSAndroid Build Coastguard Worker
362*9e94795aSAndroid Build Coastguard Worker  # Read the makefiles
363*9e94795aSAndroid Build Coastguard Worker  all_makefiles = dict()
364*9e94795aSAndroid Build Coastguard Worker  for filename, modules in soong.reverse_makefiles.items():
365*9e94795aSAndroid Build Coastguard Worker    if filename.startswith(args.out_dir + "/"):
366*9e94795aSAndroid Build Coastguard Worker      continue
367*9e94795aSAndroid Build Coastguard Worker    all_makefiles[filename] = Makefile(filename)
368*9e94795aSAndroid Build Coastguard Worker
369*9e94795aSAndroid Build Coastguard Worker  # Get all the modules in $(PRODUCT_PACKAGES) and the correspoding deps
370*9e94795aSAndroid Build Coastguard Worker  product_package_modules_plus_deps = set()
371*9e94795aSAndroid Build Coastguard Worker  if args.product_packages:
372*9e94795aSAndroid Build Coastguard Worker    product_package_top_modules = args.product_packages.read().strip().split('\n')
373*9e94795aSAndroid Build Coastguard Worker    get_module_product_packages_plus_deps(product_package_top_modules, product_package_modules_plus_deps, soong)
374*9e94795aSAndroid Build Coastguard Worker
375*9e94795aSAndroid Build Coastguard Worker  if args.mode == "html":
376*9e94795aSAndroid Build Coastguard Worker    HtmlProcessor(args=args, soong=soong, all_makefiles=all_makefiles,
377*9e94795aSAndroid Build Coastguard Worker        product_packages_modules=product_package_modules_plus_deps).execute()
378*9e94795aSAndroid Build Coastguard Worker  elif args.mode == "csv":
379*9e94795aSAndroid Build Coastguard Worker    CsvProcessor(args=args, soong=soong, all_makefiles=all_makefiles,
380*9e94795aSAndroid Build Coastguard Worker        product_packages_modules=product_package_modules_plus_deps).execute()
381*9e94795aSAndroid Build Coastguard Worker
382*9e94795aSAndroid Build Coastguard Workerclass HtmlProcessor(object):
383*9e94795aSAndroid Build Coastguard Worker  def __init__(self, args, soong, all_makefiles, product_packages_modules):
384*9e94795aSAndroid Build Coastguard Worker    self.args = args
385*9e94795aSAndroid Build Coastguard Worker    self.soong = soong
386*9e94795aSAndroid Build Coastguard Worker    self.all_makefiles = all_makefiles
387*9e94795aSAndroid Build Coastguard Worker    self.product_packages_modules = product_packages_modules
388*9e94795aSAndroid Build Coastguard Worker    self.annotations = Annotations()
389*9e94795aSAndroid Build Coastguard Worker
390*9e94795aSAndroid Build Coastguard Worker  def execute(self):
391*9e94795aSAndroid Build Coastguard Worker    if self.args.title:
392*9e94795aSAndroid Build Coastguard Worker      page_title = self.args.title
393*9e94795aSAndroid Build Coastguard Worker    else:
394*9e94795aSAndroid Build Coastguard Worker      page_title = "Remaining Android.mk files"
395*9e94795aSAndroid Build Coastguard Worker
396*9e94795aSAndroid Build Coastguard Worker    # Which modules are installed where
397*9e94795aSAndroid Build Coastguard Worker    modules_by_partition = dict()
398*9e94795aSAndroid Build Coastguard Worker    partitions = set()
399*9e94795aSAndroid Build Coastguard Worker    for installed, module in self.soong.installed.items():
400*9e94795aSAndroid Build Coastguard Worker      if len(self.product_packages_modules) > 0 and module not in self.product_packages_modules:
401*9e94795aSAndroid Build Coastguard Worker        continue
402*9e94795aSAndroid Build Coastguard Worker      partition = get_partition_from_installed(HOST_OUT_ROOT, PRODUCT_OUT, installed)
403*9e94795aSAndroid Build Coastguard Worker      modules_by_partition.setdefault(partition, []).append(module)
404*9e94795aSAndroid Build Coastguard Worker      partitions.add(partition)
405*9e94795aSAndroid Build Coastguard Worker
406*9e94795aSAndroid Build Coastguard Worker    print("""
407*9e94795aSAndroid Build Coastguard Worker    <html>
408*9e94795aSAndroid Build Coastguard Worker      <head>
409*9e94795aSAndroid Build Coastguard Worker        <title>%(page_title)s</title>
410*9e94795aSAndroid Build Coastguard Worker        <style type="text/css">
411*9e94795aSAndroid Build Coastguard Worker          body, table {
412*9e94795aSAndroid Build Coastguard Worker            font-family: Roboto, sans-serif;
413*9e94795aSAndroid Build Coastguard Worker            font-size: 9pt;
414*9e94795aSAndroid Build Coastguard Worker          }
415*9e94795aSAndroid Build Coastguard Worker          body {
416*9e94795aSAndroid Build Coastguard Worker            margin: 0;
417*9e94795aSAndroid Build Coastguard Worker            padding: 0;
418*9e94795aSAndroid Build Coastguard Worker            display: flex;
419*9e94795aSAndroid Build Coastguard Worker            flex-direction: column;
420*9e94795aSAndroid Build Coastguard Worker            height: 100vh;
421*9e94795aSAndroid Build Coastguard Worker          }
422*9e94795aSAndroid Build Coastguard Worker          #container {
423*9e94795aSAndroid Build Coastguard Worker            flex: 1;
424*9e94795aSAndroid Build Coastguard Worker            display: flex;
425*9e94795aSAndroid Build Coastguard Worker            flex-direction: row;
426*9e94795aSAndroid Build Coastguard Worker            overflow: hidden;
427*9e94795aSAndroid Build Coastguard Worker          }
428*9e94795aSAndroid Build Coastguard Worker          #tables {
429*9e94795aSAndroid Build Coastguard Worker            padding: 0 20px 40px 20px;
430*9e94795aSAndroid Build Coastguard Worker            overflow: scroll;
431*9e94795aSAndroid Build Coastguard Worker            flex: 2 2 600px;
432*9e94795aSAndroid Build Coastguard Worker          }
433*9e94795aSAndroid Build Coastguard Worker          #details {
434*9e94795aSAndroid Build Coastguard Worker            display: none;
435*9e94795aSAndroid Build Coastguard Worker            overflow: scroll;
436*9e94795aSAndroid Build Coastguard Worker            flex: 1 1 650px;
437*9e94795aSAndroid Build Coastguard Worker            padding: 0 20px 0 20px;
438*9e94795aSAndroid Build Coastguard Worker          }
439*9e94795aSAndroid Build Coastguard Worker          h1 {
440*9e94795aSAndroid Build Coastguard Worker            margin: 16px 0 16px 20px;
441*9e94795aSAndroid Build Coastguard Worker          }
442*9e94795aSAndroid Build Coastguard Worker          h2 {
443*9e94795aSAndroid Build Coastguard Worker            margin: 12px 0 4px 0;
444*9e94795aSAndroid Build Coastguard Worker          }
445*9e94795aSAndroid Build Coastguard Worker          .RowTitle {
446*9e94795aSAndroid Build Coastguard Worker            text-align: left;
447*9e94795aSAndroid Build Coastguard Worker            width: 200px;
448*9e94795aSAndroid Build Coastguard Worker            min-width: 200px;
449*9e94795aSAndroid Build Coastguard Worker          }
450*9e94795aSAndroid Build Coastguard Worker          .Count {
451*9e94795aSAndroid Build Coastguard Worker            text-align: center;
452*9e94795aSAndroid Build Coastguard Worker            width: 60px;
453*9e94795aSAndroid Build Coastguard Worker            min-width: 60px;
454*9e94795aSAndroid Build Coastguard Worker            max-width: 60px;
455*9e94795aSAndroid Build Coastguard Worker          }
456*9e94795aSAndroid Build Coastguard Worker          th.Clean,
457*9e94795aSAndroid Build Coastguard Worker          th.Unblocked {
458*9e94795aSAndroid Build Coastguard Worker            background-color: #1e8e3e;
459*9e94795aSAndroid Build Coastguard Worker          }
460*9e94795aSAndroid Build Coastguard Worker          th.Blocked {
461*9e94795aSAndroid Build Coastguard Worker            background-color: #d93025;
462*9e94795aSAndroid Build Coastguard Worker          }
463*9e94795aSAndroid Build Coastguard Worker          th.Warning {
464*9e94795aSAndroid Build Coastguard Worker            background-color: #e8710a;
465*9e94795aSAndroid Build Coastguard Worker          }
466*9e94795aSAndroid Build Coastguard Worker          th {
467*9e94795aSAndroid Build Coastguard Worker            background-color: #1a73e8;
468*9e94795aSAndroid Build Coastguard Worker            color: white;
469*9e94795aSAndroid Build Coastguard Worker            font-weight: bold;
470*9e94795aSAndroid Build Coastguard Worker          }
471*9e94795aSAndroid Build Coastguard Worker          td.Unblocked {
472*9e94795aSAndroid Build Coastguard Worker            background-color: #81c995;
473*9e94795aSAndroid Build Coastguard Worker          }
474*9e94795aSAndroid Build Coastguard Worker          td.Blocked {
475*9e94795aSAndroid Build Coastguard Worker            background-color: #f28b82;
476*9e94795aSAndroid Build Coastguard Worker          }
477*9e94795aSAndroid Build Coastguard Worker          td, th {
478*9e94795aSAndroid Build Coastguard Worker            padding: 2px 4px;
479*9e94795aSAndroid Build Coastguard Worker            border-right: 2px solid white;
480*9e94795aSAndroid Build Coastguard Worker          }
481*9e94795aSAndroid Build Coastguard Worker          tr.TotalRow td {
482*9e94795aSAndroid Build Coastguard Worker            background-color: white;
483*9e94795aSAndroid Build Coastguard Worker            border-right-color: white;
484*9e94795aSAndroid Build Coastguard Worker          }
485*9e94795aSAndroid Build Coastguard Worker          tr.AospDir td {
486*9e94795aSAndroid Build Coastguard Worker            background-color: #e6f4ea;
487*9e94795aSAndroid Build Coastguard Worker            border-right-color: #e6f4ea;
488*9e94795aSAndroid Build Coastguard Worker          }
489*9e94795aSAndroid Build Coastguard Worker          tr.GoogleDir td {
490*9e94795aSAndroid Build Coastguard Worker            background-color: #e8f0fe;
491*9e94795aSAndroid Build Coastguard Worker            border-right-color: #e8f0fe;
492*9e94795aSAndroid Build Coastguard Worker          }
493*9e94795aSAndroid Build Coastguard Worker          tr.PartnerDir td {
494*9e94795aSAndroid Build Coastguard Worker            background-color: #fce8e6;
495*9e94795aSAndroid Build Coastguard Worker            border-right-color: #fce8e6;
496*9e94795aSAndroid Build Coastguard Worker          }
497*9e94795aSAndroid Build Coastguard Worker          table {
498*9e94795aSAndroid Build Coastguard Worker            border-spacing: 0;
499*9e94795aSAndroid Build Coastguard Worker            border-collapse: collapse;
500*9e94795aSAndroid Build Coastguard Worker          }
501*9e94795aSAndroid Build Coastguard Worker          div.Makefile {
502*9e94795aSAndroid Build Coastguard Worker            margin: 12px 0 0 0;
503*9e94795aSAndroid Build Coastguard Worker          }
504*9e94795aSAndroid Build Coastguard Worker          div.Makefile:first {
505*9e94795aSAndroid Build Coastguard Worker            margin-top: 0;
506*9e94795aSAndroid Build Coastguard Worker          }
507*9e94795aSAndroid Build Coastguard Worker          div.FileModules {
508*9e94795aSAndroid Build Coastguard Worker            padding: 4px 0 0 20px;
509*9e94795aSAndroid Build Coastguard Worker          }
510*9e94795aSAndroid Build Coastguard Worker          td.LineNo {
511*9e94795aSAndroid Build Coastguard Worker            vertical-align: baseline;
512*9e94795aSAndroid Build Coastguard Worker            padding: 6px 0 0 20px;
513*9e94795aSAndroid Build Coastguard Worker            width: 50px;
514*9e94795aSAndroid Build Coastguard Worker            vertical-align: baseline;
515*9e94795aSAndroid Build Coastguard Worker          }
516*9e94795aSAndroid Build Coastguard Worker          td.LineText {
517*9e94795aSAndroid Build Coastguard Worker            vertical-align: baseline;
518*9e94795aSAndroid Build Coastguard Worker            font-family: monospace;
519*9e94795aSAndroid Build Coastguard Worker            padding: 6px 0 0 0;
520*9e94795aSAndroid Build Coastguard Worker          }
521*9e94795aSAndroid Build Coastguard Worker          a.CsLink {
522*9e94795aSAndroid Build Coastguard Worker            font-family: monospace;
523*9e94795aSAndroid Build Coastguard Worker          }
524*9e94795aSAndroid Build Coastguard Worker          div.Help {
525*9e94795aSAndroid Build Coastguard Worker            width: 550px;
526*9e94795aSAndroid Build Coastguard Worker          }
527*9e94795aSAndroid Build Coastguard Worker          table.HelpColumns tr {
528*9e94795aSAndroid Build Coastguard Worker            border-bottom: 2px solid white;
529*9e94795aSAndroid Build Coastguard Worker          }
530*9e94795aSAndroid Build Coastguard Worker          .ModuleName {
531*9e94795aSAndroid Build Coastguard Worker            vertical-align: baseline;
532*9e94795aSAndroid Build Coastguard Worker            padding: 6px 0 0 20px;
533*9e94795aSAndroid Build Coastguard Worker            width: 275px;
534*9e94795aSAndroid Build Coastguard Worker          }
535*9e94795aSAndroid Build Coastguard Worker          .ModuleDeps {
536*9e94795aSAndroid Build Coastguard Worker            vertical-align: baseline;
537*9e94795aSAndroid Build Coastguard Worker            padding: 6px 0 0 0;
538*9e94795aSAndroid Build Coastguard Worker          }
539*9e94795aSAndroid Build Coastguard Worker          table#Modules td {
540*9e94795aSAndroid Build Coastguard Worker            vertical-align: baseline;
541*9e94795aSAndroid Build Coastguard Worker          }
542*9e94795aSAndroid Build Coastguard Worker          tr.Alt {
543*9e94795aSAndroid Build Coastguard Worker            background-color: #ececec;
544*9e94795aSAndroid Build Coastguard Worker          }
545*9e94795aSAndroid Build Coastguard Worker          tr.Alt td {
546*9e94795aSAndroid Build Coastguard Worker            border-right-color: #ececec;
547*9e94795aSAndroid Build Coastguard Worker          }
548*9e94795aSAndroid Build Coastguard Worker          .AnalysisCol {
549*9e94795aSAndroid Build Coastguard Worker            width: 300px;
550*9e94795aSAndroid Build Coastguard Worker            padding: 2px;
551*9e94795aSAndroid Build Coastguard Worker            line-height: 21px;
552*9e94795aSAndroid Build Coastguard Worker          }
553*9e94795aSAndroid Build Coastguard Worker          .Analysis {
554*9e94795aSAndroid Build Coastguard Worker            color: white;
555*9e94795aSAndroid Build Coastguard Worker            font-weight: bold;
556*9e94795aSAndroid Build Coastguard Worker            background-color: #e8710a;
557*9e94795aSAndroid Build Coastguard Worker            border-radius: 6px;
558*9e94795aSAndroid Build Coastguard Worker            margin: 4px;
559*9e94795aSAndroid Build Coastguard Worker            padding: 2px 6px;
560*9e94795aSAndroid Build Coastguard Worker            white-space: nowrap;
561*9e94795aSAndroid Build Coastguard Worker          }
562*9e94795aSAndroid Build Coastguard Worker          .Nav {
563*9e94795aSAndroid Build Coastguard Worker            margin: 4px 0 16px 20px;
564*9e94795aSAndroid Build Coastguard Worker          }
565*9e94795aSAndroid Build Coastguard Worker          .NavSpacer {
566*9e94795aSAndroid Build Coastguard Worker            display: inline-block;
567*9e94795aSAndroid Build Coastguard Worker            width: 6px;
568*9e94795aSAndroid Build Coastguard Worker          }
569*9e94795aSAndroid Build Coastguard Worker          .ModuleDetails {
570*9e94795aSAndroid Build Coastguard Worker            margin-top: 20px;
571*9e94795aSAndroid Build Coastguard Worker          }
572*9e94795aSAndroid Build Coastguard Worker          .ModuleDetails td {
573*9e94795aSAndroid Build Coastguard Worker            vertical-align: baseline;
574*9e94795aSAndroid Build Coastguard Worker          }
575*9e94795aSAndroid Build Coastguard Worker        </style>
576*9e94795aSAndroid Build Coastguard Worker      </head>
577*9e94795aSAndroid Build Coastguard Worker      <body>
578*9e94795aSAndroid Build Coastguard Worker        <h1>%(page_title)s</h1>
579*9e94795aSAndroid Build Coastguard Worker        <div class="Nav">
580*9e94795aSAndroid Build Coastguard Worker          <a href='#help'>Help</a>
581*9e94795aSAndroid Build Coastguard Worker          <span class='NavSpacer'></span><span class='NavSpacer'> </span>
582*9e94795aSAndroid Build Coastguard Worker          Partitions:
583*9e94795aSAndroid Build Coastguard Worker    """ % {
584*9e94795aSAndroid Build Coastguard Worker      "page_title": page_title,
585*9e94795aSAndroid Build Coastguard Worker    })
586*9e94795aSAndroid Build Coastguard Worker    for partition in sorted(partitions):
587*9e94795aSAndroid Build Coastguard Worker      print("<a href='#partition_%s'>%s</a><span class='NavSpacer'></span>" % (partition, partition))
588*9e94795aSAndroid Build Coastguard Worker
589*9e94795aSAndroid Build Coastguard Worker    print("""
590*9e94795aSAndroid Build Coastguard Worker          <span class='NavSpacer'></span><span class='NavSpacer'> </span>
591*9e94795aSAndroid Build Coastguard Worker          <a href='#summary'>Overall Summary</a>
592*9e94795aSAndroid Build Coastguard Worker        </div>
593*9e94795aSAndroid Build Coastguard Worker        <div id="container">
594*9e94795aSAndroid Build Coastguard Worker          <div id="tables">
595*9e94795aSAndroid Build Coastguard Worker          <a name="help"></a>
596*9e94795aSAndroid Build Coastguard Worker          <div class="Help">
597*9e94795aSAndroid Build Coastguard Worker            <p>
598*9e94795aSAndroid Build Coastguard Worker            This page analyzes the remaining Android.mk files in the Android Source tree.
599*9e94795aSAndroid Build Coastguard Worker            <p>
600*9e94795aSAndroid Build Coastguard Worker            The modules are first broken down by which of the device filesystem partitions
601*9e94795aSAndroid Build Coastguard Worker            they are installed to. This also includes host tools and testcases which don't
602*9e94795aSAndroid Build Coastguard Worker            actually reside in their own partition but convenitely group together.
603*9e94795aSAndroid Build Coastguard Worker            <p>
604*9e94795aSAndroid Build Coastguard Worker            The makefiles for each partition are further are grouped into a set of directories
605*9e94795aSAndroid Build Coastguard Worker            aritrarily picked to break down the problem size by owners.
606*9e94795aSAndroid Build Coastguard Worker            <ul style="width: 300px">
607*9e94795aSAndroid Build Coastguard Worker              <li style="background-color: #e6f4ea">AOSP directories are colored green.</li>
608*9e94795aSAndroid Build Coastguard Worker              <li style="background-color: #e8f0fe">Google directories are colored blue.</li>
609*9e94795aSAndroid Build Coastguard Worker              <li style="background-color: #fce8e6">Other partner directories are colored red.</li>
610*9e94795aSAndroid Build Coastguard Worker            </ul>
611*9e94795aSAndroid Build Coastguard Worker            Each of the makefiles are scanned for issues that are likely to come up during
612*9e94795aSAndroid Build Coastguard Worker            conversion to soong.  Clicking the number in each cell shows additional information,
613*9e94795aSAndroid Build Coastguard Worker            including the line that triggered the warning.
614*9e94795aSAndroid Build Coastguard Worker            <p>
615*9e94795aSAndroid Build Coastguard Worker            <table class="HelpColumns">
616*9e94795aSAndroid Build Coastguard Worker              <tr>
617*9e94795aSAndroid Build Coastguard Worker                <th>Total</th>
618*9e94795aSAndroid Build Coastguard Worker                <td>The total number of makefiles in this each directory.</td>
619*9e94795aSAndroid Build Coastguard Worker              </tr>
620*9e94795aSAndroid Build Coastguard Worker              <tr>
621*9e94795aSAndroid Build Coastguard Worker                <th class="Clean">Easy</th>
622*9e94795aSAndroid Build Coastguard Worker                <td>The number of makefiles that have no warnings themselves, and also
623*9e94795aSAndroid Build Coastguard Worker                    none of their dependencies have warnings either.</td>
624*9e94795aSAndroid Build Coastguard Worker              </tr>
625*9e94795aSAndroid Build Coastguard Worker              <tr>
626*9e94795aSAndroid Build Coastguard Worker                <th class="Clean">Unblocked Clean</th>
627*9e94795aSAndroid Build Coastguard Worker                <td>The number of makefiles that are both Unblocked and Clean.</td>
628*9e94795aSAndroid Build Coastguard Worker              </tr>
629*9e94795aSAndroid Build Coastguard Worker
630*9e94795aSAndroid Build Coastguard Worker              <tr>
631*9e94795aSAndroid Build Coastguard Worker                <th class="Unblocked">Unblocked</th>
632*9e94795aSAndroid Build Coastguard Worker                <td>Makefiles containing one or more modules that don't have any
633*9e94795aSAndroid Build Coastguard Worker                    additional dependencies pending before conversion.</td>
634*9e94795aSAndroid Build Coastguard Worker              </tr>
635*9e94795aSAndroid Build Coastguard Worker              <tr>
636*9e94795aSAndroid Build Coastguard Worker                <th class="Blocked">Blocked</th>
637*9e94795aSAndroid Build Coastguard Worker                <td>Makefiles containiong one or more modules which <i>do</i> have
638*9e94795aSAndroid Build Coastguard Worker                    additional prerequesite depenedencies that are not yet converted.</td>
639*9e94795aSAndroid Build Coastguard Worker              </tr>
640*9e94795aSAndroid Build Coastguard Worker              <tr>
641*9e94795aSAndroid Build Coastguard Worker                <th class="Clean">Clean</th>
642*9e94795aSAndroid Build Coastguard Worker                <td>The number of makefiles that have none of the following warnings.</td>
643*9e94795aSAndroid Build Coastguard Worker              </tr>
644*9e94795aSAndroid Build Coastguard Worker              <tr>
645*9e94795aSAndroid Build Coastguard Worker                <th class="Warning">ifeq / ifneq</th>
646*9e94795aSAndroid Build Coastguard Worker                <td>Makefiles that use <code>ifeq</code> or <code>ifneq</code>. i.e.
647*9e94795aSAndroid Build Coastguard Worker                conditionals.</td>
648*9e94795aSAndroid Build Coastguard Worker              </tr>
649*9e94795aSAndroid Build Coastguard Worker              <tr>
650*9e94795aSAndroid Build Coastguard Worker                <th class="Warning">Wacky Includes</th>
651*9e94795aSAndroid Build Coastguard Worker                <td>Makefiles that <code>include</code> files other than the standard build-system
652*9e94795aSAndroid Build Coastguard Worker                    defined template and macros.</td>
653*9e94795aSAndroid Build Coastguard Worker              </tr>
654*9e94795aSAndroid Build Coastguard Worker              <tr>
655*9e94795aSAndroid Build Coastguard Worker                <th class="Warning">Calls base_rules</th>
656*9e94795aSAndroid Build Coastguard Worker                <td>Makefiles that include base_rules.mk directly.</td>
657*9e94795aSAndroid Build Coastguard Worker              </tr>
658*9e94795aSAndroid Build Coastguard Worker              <tr>
659*9e94795aSAndroid Build Coastguard Worker                <th class="Warning">Calls define</th>
660*9e94795aSAndroid Build Coastguard Worker                <td>Makefiles that define their own macros. Some of these are easy to convert
661*9e94795aSAndroid Build Coastguard Worker                    to soong <code>defaults</code>, but others are complex.</td>
662*9e94795aSAndroid Build Coastguard Worker              </tr>
663*9e94795aSAndroid Build Coastguard Worker              <tr>
664*9e94795aSAndroid Build Coastguard Worker                <th class="Warning">Has ../</th>
665*9e94795aSAndroid Build Coastguard Worker                <td>Makefiles containing the string "../" outside of a comment. These likely
666*9e94795aSAndroid Build Coastguard Worker                    access files outside their directories.</td>
667*9e94795aSAndroid Build Coastguard Worker              </tr>
668*9e94795aSAndroid Build Coastguard Worker              <tr>
669*9e94795aSAndroid Build Coastguard Worker                <th class="Warning">dist-for-goals</th>
670*9e94795aSAndroid Build Coastguard Worker                <td>Makefiles that call <code>dist-for-goals</code> directly.</td>
671*9e94795aSAndroid Build Coastguard Worker              </tr>
672*9e94795aSAndroid Build Coastguard Worker              <tr>
673*9e94795aSAndroid Build Coastguard Worker                <th class="Warning">.PHONY</th>
674*9e94795aSAndroid Build Coastguard Worker                <td>Makefiles that declare .PHONY targets.</td>
675*9e94795aSAndroid Build Coastguard Worker              </tr>
676*9e94795aSAndroid Build Coastguard Worker              <tr>
677*9e94795aSAndroid Build Coastguard Worker                <th class="Warning">renderscript</th>
678*9e94795aSAndroid Build Coastguard Worker                <td>Makefiles defining targets that depend on <code>.rscript</code> source files.</td>
679*9e94795aSAndroid Build Coastguard Worker              </tr>
680*9e94795aSAndroid Build Coastguard Worker              <tr>
681*9e94795aSAndroid Build Coastguard Worker                <th class="Warning">vts src</th>
682*9e94795aSAndroid Build Coastguard Worker                <td>Makefiles defining targets that depend on <code>.vts</code> source files.</td>
683*9e94795aSAndroid Build Coastguard Worker              </tr>
684*9e94795aSAndroid Build Coastguard Worker              <tr>
685*9e94795aSAndroid Build Coastguard Worker                <th class="Warning">COPY_HEADERS</th>
686*9e94795aSAndroid Build Coastguard Worker                <td>Makefiles using LOCAL_COPY_HEADERS.</td>
687*9e94795aSAndroid Build Coastguard Worker              </tr>
688*9e94795aSAndroid Build Coastguard Worker            </table>
689*9e94795aSAndroid Build Coastguard Worker            <p>
690*9e94795aSAndroid Build Coastguard Worker            Following the list of directories is a list of the modules that are installed on
691*9e94795aSAndroid Build Coastguard Worker            each partition. Potential issues from their makefiles are listed, as well as the
692*9e94795aSAndroid Build Coastguard Worker            total number of dependencies (both blocking that module and blocked by that module)
693*9e94795aSAndroid Build Coastguard Worker            and the list of direct dependencies.  Note: The number is the number of all transitive
694*9e94795aSAndroid Build Coastguard Worker            dependencies and the list of modules is only the direct dependencies.
695*9e94795aSAndroid Build Coastguard Worker          </div>
696*9e94795aSAndroid Build Coastguard Worker    """)
697*9e94795aSAndroid Build Coastguard Worker
698*9e94795aSAndroid Build Coastguard Worker    overall_summary = Summary()
699*9e94795aSAndroid Build Coastguard Worker
700*9e94795aSAndroid Build Coastguard Worker    # For each partition
701*9e94795aSAndroid Build Coastguard Worker    for partition in sorted(partitions):
702*9e94795aSAndroid Build Coastguard Worker      modules = modules_by_partition[partition]
703*9e94795aSAndroid Build Coastguard Worker
704*9e94795aSAndroid Build Coastguard Worker      makefiles = set(itertools.chain.from_iterable(
705*9e94795aSAndroid Build Coastguard Worker          [self.soong.makefiles[module] for module in modules]))
706*9e94795aSAndroid Build Coastguard Worker
707*9e94795aSAndroid Build Coastguard Worker      # Read makefiles
708*9e94795aSAndroid Build Coastguard Worker      summary = Summary()
709*9e94795aSAndroid Build Coastguard Worker      for filename in makefiles:
710*9e94795aSAndroid Build Coastguard Worker        makefile = self.all_makefiles.get(filename)
711*9e94795aSAndroid Build Coastguard Worker        if makefile:
712*9e94795aSAndroid Build Coastguard Worker          summary.Add(makefile)
713*9e94795aSAndroid Build Coastguard Worker          overall_summary.Add(makefile)
714*9e94795aSAndroid Build Coastguard Worker
715*9e94795aSAndroid Build Coastguard Worker      # Categorize directories by who is responsible
716*9e94795aSAndroid Build Coastguard Worker      aosp_dirs = []
717*9e94795aSAndroid Build Coastguard Worker      google_dirs = []
718*9e94795aSAndroid Build Coastguard Worker      partner_dirs = []
719*9e94795aSAndroid Build Coastguard Worker      for dirname in sorted(summary.directories.keys()):
720*9e94795aSAndroid Build Coastguard Worker        if is_aosp(dirname):
721*9e94795aSAndroid Build Coastguard Worker          aosp_dirs.append(dirname)
722*9e94795aSAndroid Build Coastguard Worker        elif is_google(dirname):
723*9e94795aSAndroid Build Coastguard Worker          google_dirs.append(dirname)
724*9e94795aSAndroid Build Coastguard Worker        else:
725*9e94795aSAndroid Build Coastguard Worker          partner_dirs.append(dirname)
726*9e94795aSAndroid Build Coastguard Worker
727*9e94795aSAndroid Build Coastguard Worker      print_analysis_header("partition_" + partition, partition)
728*9e94795aSAndroid Build Coastguard Worker
729*9e94795aSAndroid Build Coastguard Worker      for dirgroup, rowclass in [(aosp_dirs, "AospDir"),
730*9e94795aSAndroid Build Coastguard Worker                                 (google_dirs, "GoogleDir"),
731*9e94795aSAndroid Build Coastguard Worker                                 (partner_dirs, "PartnerDir"),]:
732*9e94795aSAndroid Build Coastguard Worker        for dirname in dirgroup:
733*9e94795aSAndroid Build Coastguard Worker          self.print_analysis_row(summary, modules,
734*9e94795aSAndroid Build Coastguard Worker                               dirname, rowclass, summary.directories[dirname])
735*9e94795aSAndroid Build Coastguard Worker
736*9e94795aSAndroid Build Coastguard Worker      self.print_analysis_row(summary, modules,
737*9e94795aSAndroid Build Coastguard Worker                           "Total", "TotalRow",
738*9e94795aSAndroid Build Coastguard Worker                           set(itertools.chain.from_iterable(summary.directories.values())))
739*9e94795aSAndroid Build Coastguard Worker      print("""
740*9e94795aSAndroid Build Coastguard Worker        </table>
741*9e94795aSAndroid Build Coastguard Worker      """)
742*9e94795aSAndroid Build Coastguard Worker
743*9e94795aSAndroid Build Coastguard Worker      module_details = [(count_deps(self.soong.deps, m, []),
744*9e94795aSAndroid Build Coastguard Worker                         -count_deps(self.soong.reverse_deps, m, []), m)
745*9e94795aSAndroid Build Coastguard Worker                 for m in modules]
746*9e94795aSAndroid Build Coastguard Worker      module_details.sort()
747*9e94795aSAndroid Build Coastguard Worker      module_details = [m[2] for m in module_details]
748*9e94795aSAndroid Build Coastguard Worker      print("""
749*9e94795aSAndroid Build Coastguard Worker        <table class="ModuleDetails">""")
750*9e94795aSAndroid Build Coastguard Worker      print("<tr>")
751*9e94795aSAndroid Build Coastguard Worker      print("  <th>Module Name</th>")
752*9e94795aSAndroid Build Coastguard Worker      print("  <th>Issues</th>")
753*9e94795aSAndroid Build Coastguard Worker      print("  <th colspan='2'>Blocked By</th>")
754*9e94795aSAndroid Build Coastguard Worker      print("  <th colspan='2'>Blocking</th>")
755*9e94795aSAndroid Build Coastguard Worker      print("</tr>")
756*9e94795aSAndroid Build Coastguard Worker      altRow = True
757*9e94795aSAndroid Build Coastguard Worker      for module in module_details:
758*9e94795aSAndroid Build Coastguard Worker        analyses = set()
759*9e94795aSAndroid Build Coastguard Worker        for filename in self.soong.makefiles[module]:
760*9e94795aSAndroid Build Coastguard Worker          makefile = summary.makefiles.get(filename)
761*9e94795aSAndroid Build Coastguard Worker          if makefile:
762*9e94795aSAndroid Build Coastguard Worker            for analyzer, analysis in makefile.analyses.items():
763*9e94795aSAndroid Build Coastguard Worker              if analysis:
764*9e94795aSAndroid Build Coastguard Worker                analyses.add(analyzer.title)
765*9e94795aSAndroid Build Coastguard Worker
766*9e94795aSAndroid Build Coastguard Worker        altRow = not altRow
767*9e94795aSAndroid Build Coastguard Worker        print("<tr class='%s'>" % ("Alt" if altRow else "",))
768*9e94795aSAndroid Build Coastguard Worker        print("  <td><a name='module_%s'></a>%s</td>" % (module, module))
769*9e94795aSAndroid Build Coastguard Worker        print("  <td class='AnalysisCol'>%s</td>" % " ".join(["<span class='Analysis'>%s</span>" % title
770*9e94795aSAndroid Build Coastguard Worker            for title in analyses]))
771*9e94795aSAndroid Build Coastguard Worker        print("  <td>%s</td>" % count_deps(self.soong.deps, module, []))
772*9e94795aSAndroid Build Coastguard Worker        print("  <td>%s</td>" % format_module_list(self.soong.deps.get(module, [])))
773*9e94795aSAndroid Build Coastguard Worker        print("  <td>%s</td>" % count_deps(self.soong.reverse_deps, module, []))
774*9e94795aSAndroid Build Coastguard Worker        print("  <td>%s</td>" % format_module_list(self.soong.reverse_deps.get(module, [])))
775*9e94795aSAndroid Build Coastguard Worker        print("</tr>")
776*9e94795aSAndroid Build Coastguard Worker      print("""</table>""")
777*9e94795aSAndroid Build Coastguard Worker
778*9e94795aSAndroid Build Coastguard Worker    print_analysis_header("summary", "Overall Summary")
779*9e94795aSAndroid Build Coastguard Worker
780*9e94795aSAndroid Build Coastguard Worker    modules = [module for installed, module in self.soong.installed.items()]
781*9e94795aSAndroid Build Coastguard Worker    self.print_analysis_row(overall_summary, modules,
782*9e94795aSAndroid Build Coastguard Worker                         "All Makefiles", "TotalRow",
783*9e94795aSAndroid Build Coastguard Worker                         set(itertools.chain.from_iterable(overall_summary.directories.values())))
784*9e94795aSAndroid Build Coastguard Worker    print("""
785*9e94795aSAndroid Build Coastguard Worker        </table>
786*9e94795aSAndroid Build Coastguard Worker    """)
787*9e94795aSAndroid Build Coastguard Worker
788*9e94795aSAndroid Build Coastguard Worker    print("""
789*9e94795aSAndroid Build Coastguard Worker      <script type="text/javascript">
790*9e94795aSAndroid Build Coastguard Worker      function close_details() {
791*9e94795aSAndroid Build Coastguard Worker        document.getElementById('details').style.display = 'none';
792*9e94795aSAndroid Build Coastguard Worker      }
793*9e94795aSAndroid Build Coastguard Worker
794*9e94795aSAndroid Build Coastguard Worker      class LineMatch {
795*9e94795aSAndroid Build Coastguard Worker        constructor(lineno, text) {
796*9e94795aSAndroid Build Coastguard Worker          this.lineno = lineno;
797*9e94795aSAndroid Build Coastguard Worker          this.text = text;
798*9e94795aSAndroid Build Coastguard Worker        }
799*9e94795aSAndroid Build Coastguard Worker      }
800*9e94795aSAndroid Build Coastguard Worker
801*9e94795aSAndroid Build Coastguard Worker      class Analysis {
802*9e94795aSAndroid Build Coastguard Worker        constructor(filename, modules, line_matches) {
803*9e94795aSAndroid Build Coastguard Worker          this.filename = filename;
804*9e94795aSAndroid Build Coastguard Worker          this.modules = modules;
805*9e94795aSAndroid Build Coastguard Worker          this.line_matches = line_matches;
806*9e94795aSAndroid Build Coastguard Worker        }
807*9e94795aSAndroid Build Coastguard Worker      }
808*9e94795aSAndroid Build Coastguard Worker
809*9e94795aSAndroid Build Coastguard Worker      class Module {
810*9e94795aSAndroid Build Coastguard Worker        constructor(deps) {
811*9e94795aSAndroid Build Coastguard Worker          this.deps = deps;
812*9e94795aSAndroid Build Coastguard Worker        }
813*9e94795aSAndroid Build Coastguard Worker      }
814*9e94795aSAndroid Build Coastguard Worker
815*9e94795aSAndroid Build Coastguard Worker      function make_module_link(module) {
816*9e94795aSAndroid Build Coastguard Worker        var a = document.createElement('a');
817*9e94795aSAndroid Build Coastguard Worker        a.className = 'ModuleLink';
818*9e94795aSAndroid Build Coastguard Worker        a.innerText = module;
819*9e94795aSAndroid Build Coastguard Worker        a.href = '#module_' + module;
820*9e94795aSAndroid Build Coastguard Worker        return a;
821*9e94795aSAndroid Build Coastguard Worker      }
822*9e94795aSAndroid Build Coastguard Worker
823*9e94795aSAndroid Build Coastguard Worker      function update_details(id) {
824*9e94795aSAndroid Build Coastguard Worker        document.getElementById('details').style.display = 'block';
825*9e94795aSAndroid Build Coastguard Worker
826*9e94795aSAndroid Build Coastguard Worker        var analyses = ANALYSIS[id];
827*9e94795aSAndroid Build Coastguard Worker
828*9e94795aSAndroid Build Coastguard Worker        var details = document.getElementById("details_data");
829*9e94795aSAndroid Build Coastguard Worker        while (details.firstChild) {
830*9e94795aSAndroid Build Coastguard Worker            details.removeChild(details.firstChild);
831*9e94795aSAndroid Build Coastguard Worker        }
832*9e94795aSAndroid Build Coastguard Worker
833*9e94795aSAndroid Build Coastguard Worker        for (var i=0; i<analyses.length; i++) {
834*9e94795aSAndroid Build Coastguard Worker          var analysis = analyses[i];
835*9e94795aSAndroid Build Coastguard Worker
836*9e94795aSAndroid Build Coastguard Worker          var makefileDiv = document.createElement('div');
837*9e94795aSAndroid Build Coastguard Worker          makefileDiv.className = 'Makefile';
838*9e94795aSAndroid Build Coastguard Worker          details.appendChild(makefileDiv);
839*9e94795aSAndroid Build Coastguard Worker
840*9e94795aSAndroid Build Coastguard Worker          var fileA = document.createElement('a');
841*9e94795aSAndroid Build Coastguard Worker          makefileDiv.appendChild(fileA);
842*9e94795aSAndroid Build Coastguard Worker          fileA.className = 'CsLink';
843*9e94795aSAndroid Build Coastguard Worker          fileA.href = '%(codesearch)s' + analysis.filename;
844*9e94795aSAndroid Build Coastguard Worker          fileA.innerText = analysis.filename;
845*9e94795aSAndroid Build Coastguard Worker          fileA.target = "_blank";
846*9e94795aSAndroid Build Coastguard Worker
847*9e94795aSAndroid Build Coastguard Worker          if (analysis.modules.length > 0) {
848*9e94795aSAndroid Build Coastguard Worker            var moduleTable = document.createElement('table');
849*9e94795aSAndroid Build Coastguard Worker            details.appendChild(moduleTable);
850*9e94795aSAndroid Build Coastguard Worker
851*9e94795aSAndroid Build Coastguard Worker            for (var j=0; j<analysis.modules.length; j++) {
852*9e94795aSAndroid Build Coastguard Worker              var moduleRow = document.createElement('tr');
853*9e94795aSAndroid Build Coastguard Worker              moduleTable.appendChild(moduleRow);
854*9e94795aSAndroid Build Coastguard Worker
855*9e94795aSAndroid Build Coastguard Worker              var moduleNameCell = document.createElement('td');
856*9e94795aSAndroid Build Coastguard Worker              moduleRow.appendChild(moduleNameCell);
857*9e94795aSAndroid Build Coastguard Worker              moduleNameCell.className = 'ModuleName';
858*9e94795aSAndroid Build Coastguard Worker              moduleNameCell.appendChild(make_module_link(analysis.modules[j]));
859*9e94795aSAndroid Build Coastguard Worker
860*9e94795aSAndroid Build Coastguard Worker              var moduleData = MODULE_DATA[analysis.modules[j]];
861*9e94795aSAndroid Build Coastguard Worker              console.log(moduleData);
862*9e94795aSAndroid Build Coastguard Worker
863*9e94795aSAndroid Build Coastguard Worker              var depCell = document.createElement('td');
864*9e94795aSAndroid Build Coastguard Worker              moduleRow.appendChild(depCell);
865*9e94795aSAndroid Build Coastguard Worker
866*9e94795aSAndroid Build Coastguard Worker              if (moduleData.deps.length == 0) {
867*9e94795aSAndroid Build Coastguard Worker                depCell.className = 'ModuleDeps Unblocked';
868*9e94795aSAndroid Build Coastguard Worker                depCell.innerText = 'UNBLOCKED';
869*9e94795aSAndroid Build Coastguard Worker              } else {
870*9e94795aSAndroid Build Coastguard Worker                depCell.className = 'ModuleDeps Blocked';
871*9e94795aSAndroid Build Coastguard Worker
872*9e94795aSAndroid Build Coastguard Worker                for (var k=0; k<moduleData.deps.length; k++) {
873*9e94795aSAndroid Build Coastguard Worker                  depCell.appendChild(make_module_link(moduleData.deps[k]));
874*9e94795aSAndroid Build Coastguard Worker                  depCell.appendChild(document.createElement('br'));
875*9e94795aSAndroid Build Coastguard Worker                }
876*9e94795aSAndroid Build Coastguard Worker              }
877*9e94795aSAndroid Build Coastguard Worker            }
878*9e94795aSAndroid Build Coastguard Worker          }
879*9e94795aSAndroid Build Coastguard Worker
880*9e94795aSAndroid Build Coastguard Worker          if (analysis.line_matches.length > 0) {
881*9e94795aSAndroid Build Coastguard Worker            var lineTable = document.createElement('table');
882*9e94795aSAndroid Build Coastguard Worker            details.appendChild(lineTable);
883*9e94795aSAndroid Build Coastguard Worker
884*9e94795aSAndroid Build Coastguard Worker            for (var j=0; j<analysis.line_matches.length; j++) {
885*9e94795aSAndroid Build Coastguard Worker              var line_match = analysis.line_matches[j];
886*9e94795aSAndroid Build Coastguard Worker
887*9e94795aSAndroid Build Coastguard Worker              var lineRow = document.createElement('tr');
888*9e94795aSAndroid Build Coastguard Worker              lineTable.appendChild(lineRow);
889*9e94795aSAndroid Build Coastguard Worker
890*9e94795aSAndroid Build Coastguard Worker              var linenoCell = document.createElement('td');
891*9e94795aSAndroid Build Coastguard Worker              lineRow.appendChild(linenoCell);
892*9e94795aSAndroid Build Coastguard Worker              linenoCell.className = 'LineNo';
893*9e94795aSAndroid Build Coastguard Worker
894*9e94795aSAndroid Build Coastguard Worker              var linenoA = document.createElement('a');
895*9e94795aSAndroid Build Coastguard Worker              linenoCell.appendChild(linenoA);
896*9e94795aSAndroid Build Coastguard Worker              linenoA.className = 'CsLink';
897*9e94795aSAndroid Build Coastguard Worker              linenoA.href = '%(codesearch)s' + analysis.filename
898*9e94795aSAndroid Build Coastguard Worker                  + ';l=' + line_match.lineno;
899*9e94795aSAndroid Build Coastguard Worker              linenoA.innerText = line_match.lineno;
900*9e94795aSAndroid Build Coastguard Worker              linenoA.target = "_blank";
901*9e94795aSAndroid Build Coastguard Worker
902*9e94795aSAndroid Build Coastguard Worker              var textCell = document.createElement('td');
903*9e94795aSAndroid Build Coastguard Worker              lineRow.appendChild(textCell);
904*9e94795aSAndroid Build Coastguard Worker              textCell.className = 'LineText';
905*9e94795aSAndroid Build Coastguard Worker              textCell.innerText = line_match.text;
906*9e94795aSAndroid Build Coastguard Worker            }
907*9e94795aSAndroid Build Coastguard Worker          }
908*9e94795aSAndroid Build Coastguard Worker        }
909*9e94795aSAndroid Build Coastguard Worker      }
910*9e94795aSAndroid Build Coastguard Worker
911*9e94795aSAndroid Build Coastguard Worker      var ANALYSIS = [
912*9e94795aSAndroid Build Coastguard Worker      """ % {
913*9e94795aSAndroid Build Coastguard Worker          "codesearch": self.args.codesearch,
914*9e94795aSAndroid Build Coastguard Worker      })
915*9e94795aSAndroid Build Coastguard Worker    for entry, mods in self.annotations.entries:
916*9e94795aSAndroid Build Coastguard Worker      print("  [")
917*9e94795aSAndroid Build Coastguard Worker      for analysis in entry:
918*9e94795aSAndroid Build Coastguard Worker        print("    new Analysis('%(filename)s', %(modules)s, [%(line_matches)s])," % {
919*9e94795aSAndroid Build Coastguard Worker          "filename": analysis.filename,
920*9e94795aSAndroid Build Coastguard Worker          #"modules": json.dumps([m for m in mods if m in filename in self.soong.makefiles[m]]),
921*9e94795aSAndroid Build Coastguard Worker          "modules": json.dumps(
922*9e94795aSAndroid Build Coastguard Worker              [m for m in self.soong.reverse_makefiles[analysis.filename] if m in mods]),
923*9e94795aSAndroid Build Coastguard Worker          "line_matches": ", ".join([
924*9e94795aSAndroid Build Coastguard Worker              "new LineMatch(%d, %s)" % (lineno, json.dumps(text))
925*9e94795aSAndroid Build Coastguard Worker              for lineno, text in analysis.line_matches]),
926*9e94795aSAndroid Build Coastguard Worker        })
927*9e94795aSAndroid Build Coastguard Worker      print("  ],")
928*9e94795aSAndroid Build Coastguard Worker    print("""
929*9e94795aSAndroid Build Coastguard Worker      ];
930*9e94795aSAndroid Build Coastguard Worker      var MODULE_DATA = {
931*9e94795aSAndroid Build Coastguard Worker    """)
932*9e94795aSAndroid Build Coastguard Worker    for module in self.soong.modules:
933*9e94795aSAndroid Build Coastguard Worker      print("      '%(name)s': new Module(%(deps)s)," % {
934*9e94795aSAndroid Build Coastguard Worker        "name": module,
935*9e94795aSAndroid Build Coastguard Worker        "deps": json.dumps(self.soong.deps[module]),
936*9e94795aSAndroid Build Coastguard Worker      })
937*9e94795aSAndroid Build Coastguard Worker    print("""
938*9e94795aSAndroid Build Coastguard Worker      };
939*9e94795aSAndroid Build Coastguard Worker      </script>
940*9e94795aSAndroid Build Coastguard Worker
941*9e94795aSAndroid Build Coastguard Worker    """)
942*9e94795aSAndroid Build Coastguard Worker
943*9e94795aSAndroid Build Coastguard Worker    print("""
944*9e94795aSAndroid Build Coastguard Worker        </div> <!-- id=tables -->
945*9e94795aSAndroid Build Coastguard Worker        <div id="details">
946*9e94795aSAndroid Build Coastguard Worker          <div style="text-align: right;">
947*9e94795aSAndroid Build Coastguard Worker            <a href="javascript:close_details();">
948*9e94795aSAndroid Build Coastguard Worker              <svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
949*9e94795aSAndroid Build Coastguard Worker            </a>
950*9e94795aSAndroid Build Coastguard Worker          </div>
951*9e94795aSAndroid Build Coastguard Worker          <div id="details_data"></div>
952*9e94795aSAndroid Build Coastguard Worker        </div>
953*9e94795aSAndroid Build Coastguard Worker      </body>
954*9e94795aSAndroid Build Coastguard Worker    </html>
955*9e94795aSAndroid Build Coastguard Worker    """)
956*9e94795aSAndroid Build Coastguard Worker
957*9e94795aSAndroid Build Coastguard Worker  def traverse_ready_makefiles(self, summary, makefiles):
958*9e94795aSAndroid Build Coastguard Worker    return [Analysis(makefile.filename, []) for makefile in makefiles
959*9e94795aSAndroid Build Coastguard Worker        if clean_and_only_blocked_by_clean(self.soong, self.all_makefiles, makefile)]
960*9e94795aSAndroid Build Coastguard Worker
961*9e94795aSAndroid Build Coastguard Worker  def print_analysis_row(self, summary, modules, rowtitle, rowclass, makefiles):
962*9e94795aSAndroid Build Coastguard Worker    all_makefiles = [Analysis(makefile.filename, []) for makefile in makefiles]
963*9e94795aSAndroid Build Coastguard Worker    clean_makefiles = [Analysis(makefile.filename, []) for makefile in makefiles
964*9e94795aSAndroid Build Coastguard Worker        if is_clean(makefile)]
965*9e94795aSAndroid Build Coastguard Worker    easy_makefiles = self.traverse_ready_makefiles(summary, makefiles)
966*9e94795aSAndroid Build Coastguard Worker    unblocked_clean_makefiles = [Analysis(makefile.filename, []) for makefile in makefiles
967*9e94795aSAndroid Build Coastguard Worker        if (self.soong.contains_unblocked_modules(makefile.filename)
968*9e94795aSAndroid Build Coastguard Worker            and is_clean(makefile))]
969*9e94795aSAndroid Build Coastguard Worker    unblocked_makefiles = [Analysis(makefile.filename, []) for makefile in makefiles
970*9e94795aSAndroid Build Coastguard Worker        if self.soong.contains_unblocked_modules(makefile.filename)]
971*9e94795aSAndroid Build Coastguard Worker    blocked_makefiles = [Analysis(makefile.filename, []) for makefile in makefiles
972*9e94795aSAndroid Build Coastguard Worker        if self.soong.contains_blocked_modules(makefile.filename)]
973*9e94795aSAndroid Build Coastguard Worker
974*9e94795aSAndroid Build Coastguard Worker    print("""
975*9e94795aSAndroid Build Coastguard Worker      <tr class="%(rowclass)s">
976*9e94795aSAndroid Build Coastguard Worker        <td class="RowTitle">%(rowtitle)s</td>
977*9e94795aSAndroid Build Coastguard Worker        <td class="Count">%(makefiles)s</td>
978*9e94795aSAndroid Build Coastguard Worker        <td class="Count">%(easy)s</td>
979*9e94795aSAndroid Build Coastguard Worker        <td class="Count">%(unblocked_clean)s</td>
980*9e94795aSAndroid Build Coastguard Worker        <td class="Count">%(unblocked)s</td>
981*9e94795aSAndroid Build Coastguard Worker        <td class="Count">%(blocked)s</td>
982*9e94795aSAndroid Build Coastguard Worker        <td class="Count">%(clean)s</td>
983*9e94795aSAndroid Build Coastguard Worker    """ % {
984*9e94795aSAndroid Build Coastguard Worker      "rowclass": rowclass,
985*9e94795aSAndroid Build Coastguard Worker      "rowtitle": rowtitle,
986*9e94795aSAndroid Build Coastguard Worker      "makefiles": self.make_annotation_link(all_makefiles, modules),
987*9e94795aSAndroid Build Coastguard Worker      "unblocked": self.make_annotation_link(unblocked_makefiles, modules),
988*9e94795aSAndroid Build Coastguard Worker      "blocked": self.make_annotation_link(blocked_makefiles, modules),
989*9e94795aSAndroid Build Coastguard Worker      "clean": self.make_annotation_link(clean_makefiles, modules),
990*9e94795aSAndroid Build Coastguard Worker      "unblocked_clean": self.make_annotation_link(unblocked_clean_makefiles, modules),
991*9e94795aSAndroid Build Coastguard Worker      "easy": self.make_annotation_link(easy_makefiles, modules),
992*9e94795aSAndroid Build Coastguard Worker    })
993*9e94795aSAndroid Build Coastguard Worker
994*9e94795aSAndroid Build Coastguard Worker    for analyzer in ANALYZERS:
995*9e94795aSAndroid Build Coastguard Worker      analyses = [m.analyses.get(analyzer) for m in makefiles if m.analyses.get(analyzer)]
996*9e94795aSAndroid Build Coastguard Worker      print("""<td class="Count">%s</td>"""
997*9e94795aSAndroid Build Coastguard Worker          % self.make_annotation_link(analyses, modules))
998*9e94795aSAndroid Build Coastguard Worker
999*9e94795aSAndroid Build Coastguard Worker    print("      </tr>")
1000*9e94795aSAndroid Build Coastguard Worker
1001*9e94795aSAndroid Build Coastguard Worker  def make_annotation_link(self, analysis, modules):
1002*9e94795aSAndroid Build Coastguard Worker    if analysis:
1003*9e94795aSAndroid Build Coastguard Worker      return "<a href='javascript:update_details(%d)'>%s</a>" % (
1004*9e94795aSAndroid Build Coastguard Worker        self.annotations.Add(analysis, modules),
1005*9e94795aSAndroid Build Coastguard Worker        len(analysis)
1006*9e94795aSAndroid Build Coastguard Worker      )
1007*9e94795aSAndroid Build Coastguard Worker    else:
1008*9e94795aSAndroid Build Coastguard Worker      return "";
1009*9e94795aSAndroid Build Coastguard Worker
1010*9e94795aSAndroid Build Coastguard Workerclass CsvProcessor(object):
1011*9e94795aSAndroid Build Coastguard Worker  def __init__(self, args, soong, all_makefiles, product_packages_modules):
1012*9e94795aSAndroid Build Coastguard Worker    self.args = args
1013*9e94795aSAndroid Build Coastguard Worker    self.soong = soong
1014*9e94795aSAndroid Build Coastguard Worker    self.all_makefiles = all_makefiles
1015*9e94795aSAndroid Build Coastguard Worker    self.product_packages_modules = product_packages_modules
1016*9e94795aSAndroid Build Coastguard Worker
1017*9e94795aSAndroid Build Coastguard Worker  def execute(self):
1018*9e94795aSAndroid Build Coastguard Worker    csvout = csv.writer(sys.stdout)
1019*9e94795aSAndroid Build Coastguard Worker
1020*9e94795aSAndroid Build Coastguard Worker    # Title row
1021*9e94795aSAndroid Build Coastguard Worker    row = ["Filename", "Module", "Partitions", "Easy", "Unblocked Clean", "Unblocked",
1022*9e94795aSAndroid Build Coastguard Worker           "Blocked", "Clean"]
1023*9e94795aSAndroid Build Coastguard Worker    for analyzer in ANALYZERS:
1024*9e94795aSAndroid Build Coastguard Worker      row.append(analyzer.title)
1025*9e94795aSAndroid Build Coastguard Worker    csvout.writerow(row)
1026*9e94795aSAndroid Build Coastguard Worker
1027*9e94795aSAndroid Build Coastguard Worker    # Makefile & module data
1028*9e94795aSAndroid Build Coastguard Worker    for filename in sorted(self.all_makefiles.keys()):
1029*9e94795aSAndroid Build Coastguard Worker      makefile = self.all_makefiles[filename]
1030*9e94795aSAndroid Build Coastguard Worker      for module in self.soong.reverse_makefiles[filename]:
1031*9e94795aSAndroid Build Coastguard Worker        if len(self.product_packages_modules) > 0 and module not in self.product_packages_modules:
1032*9e94795aSAndroid Build Coastguard Worker          continue
1033*9e94795aSAndroid Build Coastguard Worker        row = [filename, module]
1034*9e94795aSAndroid Build Coastguard Worker        # Partitions
1035*9e94795aSAndroid Build Coastguard Worker        row.append(";".join(sorted(set([get_partition_from_installed(HOST_OUT_ROOT, PRODUCT_OUT,
1036*9e94795aSAndroid Build Coastguard Worker                                         installed)
1037*9e94795aSAndroid Build Coastguard Worker                                        for installed
1038*9e94795aSAndroid Build Coastguard Worker                                        in self.soong.reverse_installed.get(module, [])]))))
1039*9e94795aSAndroid Build Coastguard Worker        # Easy
1040*9e94795aSAndroid Build Coastguard Worker        row.append(1
1041*9e94795aSAndroid Build Coastguard Worker            if clean_and_only_blocked_by_clean(self.soong, self.all_makefiles, makefile)
1042*9e94795aSAndroid Build Coastguard Worker            else "")
1043*9e94795aSAndroid Build Coastguard Worker        # Unblocked Clean
1044*9e94795aSAndroid Build Coastguard Worker        row.append(1
1045*9e94795aSAndroid Build Coastguard Worker            if (self.soong.contains_unblocked_modules(makefile.filename) and is_clean(makefile))
1046*9e94795aSAndroid Build Coastguard Worker            else "")
1047*9e94795aSAndroid Build Coastguard Worker        # Unblocked
1048*9e94795aSAndroid Build Coastguard Worker        row.append(1 if self.soong.contains_unblocked_modules(makefile.filename) else "")
1049*9e94795aSAndroid Build Coastguard Worker        # Blocked
1050*9e94795aSAndroid Build Coastguard Worker        row.append(1 if self.soong.contains_blocked_modules(makefile.filename) else "")
1051*9e94795aSAndroid Build Coastguard Worker        # Clean
1052*9e94795aSAndroid Build Coastguard Worker        row.append(1 if is_clean(makefile) else "")
1053*9e94795aSAndroid Build Coastguard Worker        # Analysis
1054*9e94795aSAndroid Build Coastguard Worker        for analyzer in ANALYZERS:
1055*9e94795aSAndroid Build Coastguard Worker          row.append(1 if makefile.analyses.get(analyzer) else "")
1056*9e94795aSAndroid Build Coastguard Worker        # Write results
1057*9e94795aSAndroid Build Coastguard Worker        csvout.writerow(row)
1058*9e94795aSAndroid Build Coastguard Worker
1059*9e94795aSAndroid Build Coastguard Workerif __name__ == "__main__":
1060*9e94795aSAndroid Build Coastguard Worker  main()
1061*9e94795aSAndroid Build Coastguard Worker
1062