blob: 8cf84f56295fe62bc02619c44d487f654881af3a [file] [log] [blame]
Joe Onoratocccf2ca2022-09-28 22:52:56 -07001#!/usr/bin/env python3
2
3import argparse
4import os
5import subprocess
6import sys
7
8def get_build_var(var):
9 return subprocess.run(["build/soong/soong_ui.bash","--dumpvar-mode", var],
10 check=True, capture_output=True, text=True).stdout.strip()
11
12
13def get_sources(modules):
14 result = subprocess.run(["./prebuilts/build-tools/linux-x86/bin/ninja", "-f",
15 "out/combined-" + os.environ["TARGET_PRODUCT"] + ".ninja",
16 "-t", "inputs", "-d", ] + modules,
17 stderr=subprocess.STDOUT, stdout=subprocess.PIPE, check=False, text=True)
18 if result.returncode != 0:
19 sys.stderr.write(result.stdout)
20 sys.exit(1)
21 return set([f for f in result.stdout.split("\n") if not f.startswith("out/")])
22
23
24def m_nothing():
25 result = subprocess.run(["build/soong/soong_ui.bash", "--build-mode", "--all-modules",
26 "--dir=" + os.getcwd(), "nothing"],
27 check=False, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, text=True)
28 if result.returncode != 0:
29 sys.stderr.write(result.stdout)
30 sys.exit(1)
31
32
33def get_git_dirs():
34 text = subprocess.run(["repo","list"], check=True, capture_output=True, text=True).stdout
35 return [line.split(" : ")[0] + "/" for line in text.split("\n")]
36
37
38def get_referenced_projects(git_dirs, files):
39 # files must be sorted
40 referenced_dirs = set()
41 prev_dir = None
42 for f in files:
43 # Optimization is ~5x speedup for large sets of files
44 if prev_dir:
45 if f.startswith(prev_dir):
46 referenced_dirs.add(d)
47 continue
48 for d in git_dirs:
49 if f.startswith(d):
50 referenced_dirs.add(d)
51 prev_dir = d
52 break
Fabián Cañas97ea68a2024-04-23 20:36:14 -040053 return referenced_dirs
Joe Onoratocccf2ca2022-09-28 22:52:56 -070054
55
56def main(argv):
57 # Argument parsing
58 ap = argparse.ArgumentParser(description="List the required git projects for the given modules")
59 ap.add_argument("--products", nargs="*",
60 help="The TARGET_PRODUCT to check. If not provided just uses whatever has"
61 + " already been built")
62 ap.add_argument("--variants", nargs="*",
63 help="The TARGET_BUILD_VARIANTS to check. If not provided just uses whatever has"
64 + " already been built, or eng if --products is supplied")
65 ap.add_argument("--modules", nargs="*",
Fabián Cañas97ea68a2024-04-23 20:36:14 -040066 help="The build modules to check, or droid if not supplied")
Joe Onoratocccf2ca2022-09-28 22:52:56 -070067 ap.add_argument("--why", nargs="*",
68 help="Also print the input files used in these projects, or \"*\" for all")
Fabián Cañas97ea68a2024-04-23 20:36:14 -040069 ap.add_argument("--unused", help="List the unused git projects for the given modules rather than"
70 + "the used ones. Ignores --why", action="store_true")
Joe Onoratocccf2ca2022-09-28 22:52:56 -070071 args = ap.parse_args(argv[1:])
72
73 modules = args.modules if args.modules else ["droid"]
74
75 # Get the list of sources for all of the requested build combos
76 if not args.products and not args.variants:
77 sources = get_sources(modules)
78 else:
79 if not args.products:
80 sys.stderr.write("Error: --products must be supplied if --variants is supplied")
81 sys.exit(1)
82 sources = set()
83 build_num = 1
84 for product in args.products:
85 os.environ["TARGET_PRODUCT"] = product
86 variants = args.variants if args.variants else ["user", "userdebug", "eng"]
87 for variant in variants:
88 sys.stderr.write(f"Analyzing build {build_num} of {len(args.products)*len(variants)}\r")
89 os.environ["TARGET_BUILD_VARIANT"] = variant
90 m_nothing()
91 sources.update(get_sources(modules))
92 build_num += 1
93 sys.stderr.write("\n\n")
94
95 sources = sorted(sources)
96
Fabián Cañas97ea68a2024-04-23 20:36:14 -040097 if args.unused:
98 # Print the list of git directories that don't contain sources
99 used_git_dirs = set(get_git_dirs())
100 for project in sorted(used_git_dirs.difference(set(get_referenced_projects(used_git_dirs, sources)))):
101 print(project[0:-1])
102 else:
103 # Print the list of git directories that has one or more of the sources in it
104 for project in sorted(get_referenced_projects(get_git_dirs(), sources)):
105 print(project[0:-1])
106 if args.why:
107 if "*" in args.why or project[0:-1] in args.why:
108 prefix = project
109 for f in sources:
110 if f.startswith(prefix):
111 print(" " + f)
Joe Onoratocccf2ca2022-09-28 22:52:56 -0700112
113
114if __name__ == "__main__":
115 sys.exit(main(sys.argv))
116
117
118# vim: set ts=2 sw=2 sts=2 expandtab nocindent tw=100: