aboutsummaryrefslogtreecommitdiff
path: root/scripts/incremental_build
diff options
context:
space:
mode:
authorusta <usta@google.com>2023-08-24 15:21:46 -0400
committerusta <usta@google.com>2023-08-28 12:24:40 -0400
commit30d6c20d7d6f4bc86e7d235984957fa5334a402f (patch)
tree52e9fb0faebb1dfce8f198ee0b2d5731512a700e /scripts/incremental_build
parent7f5852d16867409cad6d30fe90e0641d2a52a337 (diff)
downloadbazel-30d6c20d7d6f4bc86e7d235984957fa5334a402f.tar.gz
Split script into files
Bug: NA Test: ./incremental_build.sh -c "no change" Change-Id: Ida0d2638642ba9d1a8dc54d0ff9ee741e64e2d8e
Diffstat (limited to 'scripts/incremental_build')
-rw-r--r--scripts/incremental_build/BUILD.bazel1
-rw-r--r--scripts/incremental_build/clone.py2
-rw-r--r--scripts/incremental_build/cuj.py5
-rw-r--r--scripts/incremental_build/cuj_catalog.py269
-rw-r--r--scripts/incremental_build/cuj_regex_based.py106
5 files changed, 191 insertions, 192 deletions
diff --git a/scripts/incremental_build/BUILD.bazel b/scripts/incremental_build/BUILD.bazel
index 28c89537..e443bed5 100644
--- a/scripts/incremental_build/BUILD.bazel
+++ b/scripts/incremental_build/BUILD.bazel
@@ -18,6 +18,7 @@ py_binary(
"clone.py",
"cuj.py",
"cuj_catalog.py",
+ "cuj_regex_based.py",
"go_allowlists.py",
"incremental_build.py",
"pretty.py",
diff --git a/scripts/incremental_build/clone.py b/scripts/incremental_build/clone.py
index bb911eb6..2a8c0867 100644
--- a/scripts/incremental_build/clone.py
+++ b/scripts/incremental_build/clone.py
@@ -304,7 +304,7 @@ class Clone(cuj.CujGroup):
super().__init__(group_name)
self.bps = bps
- def get_steps(self):
+ def get_steps(self) -> Iterable[cuj.CujStep]:
bp2templates = _extract_templates(self.bps)
bp_count = len(bp2templates)
if bp_count == 0:
diff --git a/scripts/incremental_build/cuj.py b/scripts/incremental_build/cuj.py
index 2337b55e..e5f638fc 100644
--- a/scripts/incremental_build/cuj.py
+++ b/scripts/incremental_build/cuj.py
@@ -17,8 +17,7 @@ import enum
import logging
import os
from pathlib import Path
-from typing import Callable
-from typing import TypeAlias
+from typing import Callable, Iterable, TypeAlias
import util
from util import BuildType
@@ -133,7 +132,7 @@ class CujGroup(abc.ABC):
return self._desc
@abc.abstractmethod
- def get_steps(self) -> list[CujStep]:
+ def get_steps(self) -> Iterable[CujStep]:
pass
diff --git a/scripts/incremental_build/cuj_catalog.py b/scripts/incremental_build/cuj_catalog.py
index 26866fc4..a03009c7 100644
--- a/scripts/incremental_build/cuj_catalog.py
+++ b/scripts/incremental_build/cuj_catalog.py
@@ -19,14 +19,13 @@ import shutil
import tempfile
import uuid
from pathlib import Path
-from typing import Callable, Final, Optional
+from typing import Final, Iterable, Optional
import clone
import cuj
import finder
import util
-import random
-import re
+import cuj_regex_based
from cuj import CujGroup
from cuj import CujStep
from cuj import InWorkspace
@@ -46,7 +45,7 @@ class Clean(CujGroup):
def __init__(self):
super().__init__("clean")
- def get_steps(self) -> list[CujStep]:
+ def get_steps(self) -> Iterable[CujStep]:
def clean():
if util.get_out_dir().exists():
shutil.rmtree(util.get_out_dir())
@@ -58,7 +57,7 @@ class NoChange(CujGroup):
def __init__(self):
super().__init__("no change")
- def get_steps(self) -> list[CujStep]:
+ def get_steps(self) -> Iterable[CujStep]:
return [CujStep("", lambda: None)]
@@ -82,7 +81,7 @@ class Modify(CujGroup):
self.file = file
self.text = text
- def get_steps(self):
+ def get_steps(self) -> Iterable[CujStep]:
if self.text is None:
self.text = f"//BOGUS {uuid.uuid4()}\n"
@@ -99,106 +98,6 @@ class Modify(CujGroup):
return [CujStep("", add_line), CujStep("revert", revert)]
-class RegexModify(CujGroup):
- """
- A pair of CujSteps, where the fist modifies the file and the
- second reverts it
- Attributes:
- file: the file to be edited and reverted
- pattern: the string that will be replaced, only the FIRST occurrence will be replaced
- replace: a function that generates the replacement string
- modify_type: types of modification
- """
-
- def __init__(
- self, file: Path, pattern: str, replacer: Callable[[], str], modify_type: str
- ):
- super().__init__(f"{modify_type} {de_src(file)}")
- if not file.exists():
- raise RuntimeError(f"{file} does not exist")
- self.file = file
- self.pattern = pattern
- self.replacer = replacer
-
- def get_steps(self) -> list[CujStep]:
- original_text: str
-
- def modify():
- nonlocal original_text
- original_text = self.file.read_text()
- modified_text = re.sub(
- self.pattern,
- self.replacer(),
- original_text,
- count=1,
- flags=re.MULTILINE,
- )
- self.file.write_text(modified_text)
-
- def revert():
- self.file.write_text(original_text)
-
- return [CujStep("", modify), CujStep("revert", revert)]
-
-
-def modify_private_method(file: Path) -> CujGroup:
- pattern = r"(private static boolean.*{)"
-
- def replacement():
- return r'\1 Log.d("Placeholder", "Placeholder{}");'.format(
- random.randint(0, 1000)
- )
-
- modify_type = "modify_private_method"
- return RegexModify(file, pattern, replacement, modify_type)
-
-
-def add_private_field(file: Path) -> CujGroup:
- pattern = r"^\}$"
-
- def replacement():
- return (
- r"private static final int FOO = " + str(random.randint(0, 1000)) + ";\n}"
- )
-
- modify_type = "add_private_field"
- return RegexModify(file, pattern, replacement, modify_type)
-
-
-def add_public_api(file: Path) -> CujGroup:
- pattern = r"\}$"
-
- def replacement():
- return r"public static final int BAZ = " + str(random.randint(0, 1000)) + ";\n}"
-
- modify_type = "add_public_api"
- return RegexModify(file, pattern, replacement, modify_type)
-
-
-def modify_resource(file: Path) -> CujGroup:
- pattern = r">0<"
-
- def replacement():
- return r">" + str(random.randint(0, 1000)) + r"<"
-
- modify_type = "modify_resource"
- return RegexModify(file, pattern, replacement, modify_type)
-
-
-def add_resource(file: Path) -> CujGroup:
- pattern = r"</resources>"
-
- def replacement():
- return (
- r' <integer name="foo">'
- + str(random.randint(0, 1000))
- + r"</integer>\n</resources>"
- )
-
- modify_type = "add_resource"
- return RegexModify(file, pattern, replacement, modify_type)
-
-
class Create(CujGroup):
"""
A pair of CujSteps, where the fist creates the file and the
@@ -223,7 +122,7 @@ class Create(CujGroup):
if self.text is None:
self.text = f"//Test File: safe to delete {uuid.uuid4()}\n"
- def get_steps(self):
+ def get_steps(self) -> Iterable[CujStep]:
missing_dirs = [f for f in self.file.parents if not f.exists()]
shallowest_missing_dir = missing_dirs[-1] if len(missing_dirs) else None
@@ -274,7 +173,7 @@ class Delete(CujGroup):
self.original = original
self.ws = ws
- def get_steps(self):
+ def get_steps(self) -> Iterable[CujStep]:
tempdir = Path(tempfile.gettempdir())
if tempdir.is_relative_to(util.get_top_dir()):
raise SystemExit(f"Temp dir {tempdir} is under source tree")
@@ -309,7 +208,7 @@ class ReplaceFileWithDir(CujGroup):
super().__init__(f"replace {de_src(p)} with dir")
self.p = p
- def get_steps(self):
+ def get_steps(self) -> Iterable[CujStep]:
# an Android.bp is always a symlink in the workspace and thus its parent
# will be a directory in the workspace
create_dir: CujStep
@@ -369,7 +268,7 @@ class ModifyKeptBuildFile(CujGroup):
super().__init__(f"modify kept {de_src(build_file)}")
self.build_file = build_file
- def get_steps(self):
+ def get_steps(self) -> Iterable[CujStep]:
content = f"//BOGUS {uuid.uuid4()}\n"
step1, step2, *tail = Modify(self.build_file, content).get_steps()
assert len(tail) == 0
@@ -450,7 +349,7 @@ class CreateUnkeptBuildFile(CujGroup):
]
-def _kept_build_cujs() -> list[CujGroup]:
+def _kept_build_cujs() -> tuple[CujGroup, ...]:
# Bp2BuildKeepExistingBuildFile(build/bazel) is True(recursive)
kept = src("build/bazel")
finder.confirm(
@@ -461,105 +360,65 @@ def _kept_build_cujs() -> list[CujGroup]:
"rules/python/BUILD",
)
- return [
- *[
+ return (
+ *(
CreateKeptBuildFile(kept.joinpath("compliance").joinpath(b))
for b in ["BUILD", "BUILD.bazel"]
- ],
+ ),
Create(kept.joinpath("BUILD/kept-dir"), InWorkspace.SYMLINK),
ModifyKeptBuildFile(kept.joinpath("rules/python/BUILD")),
- ]
+ )
-def _unkept_build_cujs() -> list[CujGroup]:
+def _unkept_build_cujs() -> tuple[CujGroup, ...]:
# Bp2BuildKeepExistingBuildFile(bionic) is False(recursive)
unkept = src("bionic/libm")
finder.confirm(unkept, "Android.bp", "!BUILD", "!BUILD.bazel")
- return [
- *[CreateUnkeptBuildFile(unkept.joinpath(b)) for b in ["BUILD", "BUILD.bazel"]],
- *[
+ return (
+ *(CreateUnkeptBuildFile(unkept.joinpath(b)) for b in ["BUILD", "BUILD.bazel"]),
+ *(
Create(build_file, InWorkspace.OMISSION)
for build_file in [
unkept.joinpath("bogus-unkept/BUILD"),
unkept.joinpath("bogus-unkept/BUILD.bazel"),
]
- ],
+ ),
# TODO: b/258873199 - Support directories named BUILD.
Create(unkept.joinpath("BUILD/unkept-dir"), InWorkspace.SYMLINK),
- ]
-
+ )
-@functools.cache
-def get_cujgroups() -> list[CujGroup]:
- # we are choosing "package" directories that have Android.bp but
- # not BUILD nor BUILD.bazel because
- # we can't tell if ShouldKeepExistingBuildFile would be True or not
- non_empty_dir = "*/*"
- pkg = src("art")
- finder.confirm(pkg, non_empty_dir, "Android.bp", "!BUILD*")
- pkg_free = src("bionic/docs")
- finder.confirm(pkg_free, non_empty_dir, "!**/Android.bp", "!**/BUILD*")
- ancestor = src("bionic")
- finder.confirm(ancestor, "**/Android.bp", "!Android.bp", "!BUILD*")
- leaf_pkg_free = src("bionic/build")
- finder.confirm(leaf_pkg_free, f"!{non_empty_dir}", "!**/Android.bp", "!**/BUILD*")
- android_bp_cujs = [
- Modify(src("Android.bp")),
- *[
- CreateBp(d.joinpath("Android.bp"))
- for d in [ancestor, pkg_free, leaf_pkg_free]
- ],
- ]
- mixed_build_launch_cujs = [
+def _mixed_build_launch_cujs() -> tuple[CujGroup, ...]:
+ core_settings = src("frameworks/base/core/java/android/provider/Settings.java")
+ ams = src(
+ "frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java"
+ )
+ resource = src("frameworks/base/core/res/res/values/config.xml")
+ return (
Modify(src("bionic/libc/tzcode/asctime.c")),
Modify(src("bionic/libc/stdio/stdio.cpp")),
Modify(src("packages/modules/adb/daemon/main.cpp")),
Modify(src("frameworks/base/core/java/android/view/View.java")),
- Modify(src("frameworks/base/core/java/android/provider/Settings.java")),
- modify_private_method(
- src("frameworks/base/core/java/android/provider/Settings.java")
- ),
- add_private_field(
- src("frameworks/base/core/java/android/provider/Settings.java")
- ),
- add_public_api(src("frameworks/base/core/java/android/provider/Settings.java")),
- modify_private_method(
- src(
- "frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java"
- )
- ),
- add_private_field(
- src(
- "frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java"
- )
- ),
- add_public_api(
- src(
- "frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java"
- )
- ),
- modify_resource(src("frameworks/base/core/res/res/values/config.xml")),
- add_resource(src("frameworks/base/core/res/res/values/config.xml")),
- ]
- unreferenced_file_cujs = [
- *[
- Create(d.joinpath("unreferenced.txt"), InWorkspace.SYMLINK)
- for d in [ancestor, pkg]
- ],
- *[
- Create(d.joinpath("unreferenced.txt"), InWorkspace.UNDER_SYMLINK)
- for d in [pkg_free, leaf_pkg_free]
- ],
- ]
+ Modify(core_settings),
+ cuj_regex_based.modify_private_method(core_settings),
+ cuj_regex_based.add_private_field(core_settings),
+ cuj_regex_based.add_public_api(core_settings),
+ cuj_regex_based.modify_private_method(ams),
+ cuj_regex_based.add_private_field(ams),
+ cuj_regex_based.add_public_api(ams),
+ cuj_regex_based.modify_resource(resource),
+ cuj_regex_based.add_resource(resource),
+ )
+
+def _cloning_cujs() -> tuple[CujGroup, ...]:
cc_ = (
lambda t, name: t.startswith("cc_")
and "test" not in t
and not name.startswith("libcrypto") # has some unique hash
)
libNN = lambda t, name: t == "cc_library_shared" and name == "libneuralnetworks"
- cloning_cujs = [
+ return (
clone.Clone("clone genrules", {src("."): clone.type_in("genrule")}),
clone.Clone("clone cc_", {src("."): cc_}),
clone.Clone(
@@ -577,26 +436,60 @@ def get_cujgroups() -> list[CujGroup]:
src("packages/modules/NeuralNetworks/runtime/Android.bp"): libNN,
},
),
- ]
+ )
+
+
+@functools.cache
+def get_cujgroups() -> tuple[CujGroup, ...]:
+ # we are choosing "package" directories that have Android.bp but
+ # not BUILD nor BUILD.bazel because
+ # we can't tell if ShouldKeepExistingBuildFile would be True or not
+ non_empty_dir = "*/*"
+ pkg = src("art")
+ finder.confirm(pkg, non_empty_dir, "Android.bp", "!BUILD*")
+ pkg_free = src("bionic/docs")
+ finder.confirm(pkg_free, non_empty_dir, "!**/Android.bp", "!**/BUILD*")
+ ancestor = src("bionic")
+ finder.confirm(ancestor, "**/Android.bp", "!Android.bp", "!BUILD*")
+ leaf_pkg_free = src("bionic/build")
+ finder.confirm(leaf_pkg_free, f"!{non_empty_dir}", "!**/Android.bp", "!**/BUILD*")
+
+ android_bp_cujs = (
+ Modify(src("Android.bp")),
+ *(
+ CreateBp(d.joinpath("Android.bp"))
+ for d in [ancestor, pkg_free, leaf_pkg_free]
+ ),
+ )
+ unreferenced_file_cujs = (
+ *(
+ Create(d.joinpath("unreferenced.txt"), InWorkspace.SYMLINK)
+ for d in [ancestor, pkg]
+ ),
+ *(
+ Create(d.joinpath("unreferenced.txt"), InWorkspace.UNDER_SYMLINK)
+ for d in [pkg_free, leaf_pkg_free]
+ ),
+ )
- return [
+ return (
Clean(),
NoChange(),
- *cloning_cujs,
+ *_cloning_cujs(),
Create(src("bionic/libc/tzcode/globbed.c"), InWorkspace.UNDER_SYMLINK),
# TODO (usta): find targets that should be affected
- *[
+ *(
Delete(f, InWorkspace.SYMLINK)
for f in [
src("bionic/libc/version_script.txt"),
src("external/cbor-java/AndroidManifest.xml"),
]
- ],
+ ),
*unreferenced_file_cujs,
- *mixed_build_launch_cujs,
+ *_mixed_build_launch_cujs(),
*android_bp_cujs,
*_unkept_build_cujs(),
*_kept_build_cujs(),
ReplaceFileWithDir(src("bionic/README.txt")),
# TODO(usta): add a dangling symlink
- ]
+ )
diff --git a/scripts/incremental_build/cuj_regex_based.py b/scripts/incremental_build/cuj_regex_based.py
new file mode 100644
index 00000000..0a399647
--- /dev/null
+++ b/scripts/incremental_build/cuj_regex_based.py
@@ -0,0 +1,106 @@
+import re
+import random
+from pathlib import Path
+from typing import Callable, Iterable
+
+from cuj import CujGroup, CujStep, de_src
+
+
+class RegexModify(CujGroup):
+ """
+ A pair of CujSteps, where the fist modifies the file and the
+ second reverts it
+ Attributes:
+ file: the file to be edited and reverted
+ pattern: the string that will be replaced, only the FIRST occurrence will be replaced
+ replace: a function that generates the replacement string
+ modify_type: types of modification
+ """
+
+ def __init__(
+ self, file: Path, pattern: str, replacer: Callable[[], str], modify_type: str
+ ):
+ super().__init__(f"{modify_type} {de_src(file)}")
+ if not file.exists():
+ raise RuntimeError(f"{file} does not exist")
+ self.file = file
+ self.pattern = pattern
+ self.replacer = replacer
+
+ def get_steps(self) -> Iterable[CujStep]:
+ original_text: str
+
+ def modify():
+ nonlocal original_text
+ original_text = self.file.read_text()
+ modified_text = re.sub(
+ self.pattern,
+ self.replacer(),
+ original_text,
+ count=1,
+ flags=re.MULTILINE,
+ )
+ self.file.write_text(modified_text)
+
+ def revert():
+ self.file.write_text(original_text)
+
+ return [CujStep("", modify), CujStep("revert", revert)]
+
+
+def modify_private_method(file: Path) -> CujGroup:
+ pattern = r"(private static boolean.*{)"
+
+ def replacement():
+ return r'\1 Log.d("Placeholder", "Placeholder{}");'.format(
+ random.randint(0, 1000)
+ )
+
+ modify_type = "modify_private_method"
+ return RegexModify(file, pattern, replacement, modify_type)
+
+
+def add_private_field(file: Path) -> CujGroup:
+ pattern = r"^\}$"
+
+ def replacement():
+ return (
+ r"private static final int FOO = " + str(random.randint(0, 1000)) + ";\n}"
+ )
+
+ modify_type = "add_private_field"
+ return RegexModify(file, pattern, replacement, modify_type)
+
+
+def add_public_api(file: Path) -> CujGroup:
+ pattern = r"\}$"
+
+ def replacement():
+ return r"public static final int BAZ = " + str(random.randint(0, 1000)) + ";\n}"
+
+ modify_type = "add_public_api"
+ return RegexModify(file, pattern, replacement, modify_type)
+
+
+def modify_resource(file: Path) -> CujGroup:
+ pattern = r">0<"
+
+ def replacement():
+ return r">" + str(random.randint(0, 1000)) + r"<"
+
+ modify_type = "modify_resource"
+ return RegexModify(file, pattern, replacement, modify_type)
+
+
+def add_resource(file: Path) -> CujGroup:
+ pattern = r"</resources>"
+
+ def replacement():
+ return (
+ r' <integer name="foo">'
+ + str(random.randint(0, 1000))
+ + r"</integer>\n</resources>"
+ )
+
+ modify_type = "add_resource"
+ return RegexModify(file, pattern, replacement, modify_type)