Merge "Add mdns_aidl_interface libs to allowed_deps."
diff --git a/build/mainline_modules_sdks.py b/build/mainline_modules_sdks.py
index ed0f14a..3fe0ddd 100755
--- a/build/mainline_modules_sdks.py
+++ b/build/mainline_modules_sdks.py
@@ -13,7 +13,6 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-
"""Builds SDK snapshots.
If the environment variable TARGET_BUILD_APPS is nonempty then only the SDKs for
@@ -175,6 +174,88 @@
file.write("\n".join(header_lines + content_lines) + "\n")
+@dataclasses.dataclass()
+class SubprocessRunner:
+ """Runs subprocesses"""
+
+ # Destination for stdout from subprocesses.
+ #
+ # This (and the following stderr) are needed to allow the tests to be run
+ # in Intellij. This ensures that the tests are run with stdout/stderr
+ # objects that work when passed to subprocess.run(stdout/stderr). Without it
+ # the tests are run with a FlushingStringIO object that has no fileno
+ # attribute - https://youtrack.jetbrains.com/issue/PY-27883.
+ stdout: io.TextIOBase = sys.stdout
+
+ # Destination for stderr from subprocesses.
+ stderr: io.TextIOBase = sys.stderr
+
+ def run(self, *args, **kwargs):
+ return subprocess.run(
+ *args, check=True, stdout=self.stdout, stderr=self.stderr, **kwargs)
+
+
+@dataclasses.dataclass()
+class SnapshotBuilder:
+ """Builds sdk snapshots"""
+
+ # Used to run subprocesses for building snapshots.
+ subprocess_runner: SubprocessRunner
+
+ # The OUT_DIR environment variable.
+ out_dir: str
+
+ def get_mainline_sdks_path(self):
+ """Get the path to the Soong mainline-sdks directory"""
+ return os.path.join(self.out_dir, "soong/mainline-sdks")
+
+ def get_sdk_path(self, sdk_name, sdk_version):
+ """Get the path to the sdk snapshot zip file produced by soong"""
+ return os.path.join(self.get_mainline_sdks_path(),
+ f"{sdk_name}-{sdk_version}.zip")
+
+ def build_snapshots(self, sdk_versions, modules):
+ # Build the SDKs once for each version.
+ for sdk_version in sdk_versions:
+ # Compute the paths to all the Soong generated sdk snapshot files
+ # required by this script.
+ paths = [
+ self.get_sdk_path(sdk, sdk_version)
+ for module in modules
+ for sdk in module.sdks
+ ]
+
+ # TODO(ngeoffray): remove SOONG_ALLOW_MISSING_DEPENDENCIES, but we
+ # currently break without it.
+ #
+ # Set SOONG_SDK_SNAPSHOT_USE_SRCJAR to generate .srcjars inside sdk
+ # zip files as expected by prebuilt drop.
+ extraEnv = {
+ "SOONG_ALLOW_MISSING_DEPENDENCIES": "true",
+ "SOONG_SDK_SNAPSHOT_USE_SRCJAR": "true",
+ "SOONG_SDK_SNAPSHOT_VERSION": sdk_version,
+ }
+ # Unless explicitly specified in the calling environment set
+ # TARGET_BUILD_VARIANT=user.
+ # This MUST be identical to the TARGET_BUILD_VARIANT used to build
+ # the corresponding APEXes otherwise it could result in different
+ # hidden API flags, see http://b/202398851#comment29 for more info.
+ targetBuildVariant = os.environ.get("TARGET_BUILD_VARIANT", "user")
+ cmd = [
+ "build/soong/soong_ui.bash",
+ "--make-mode",
+ "--soong-only",
+ f"TARGET_BUILD_VARIANT={targetBuildVariant}",
+ "TARGET_PRODUCT=mainline_sdk",
+ "MODULE_BUILD_FROM_SOURCE=true",
+ "out/soong/apex/depsinfo/new-allowed-deps.txt.check",
+ ] + paths
+ print_command(extraEnv, cmd)
+ env = os.environ.copy()
+ env.update(extraEnv)
+ self.subprocess_runner.run(cmd, env=env)
+
+
@dataclasses.dataclass(frozen=True)
class MainlineModule:
"""Represents a mainline module"""
@@ -267,9 +348,6 @@
),
]
-# Only used by the test.
-MAINLINE_MODULES_BY_APEX = dict((m.apex, m) for m in MAINLINE_MODULES)
-
# A list of the sdk versions to build. Usually just current but can include a
# numeric version too.
SDK_VERSIONS = [
@@ -290,20 +368,11 @@
directory.
"""
- # Destination for stdout from subprocesses.
- #
- # This (and the following stderr) are needed to allow the tests to be run
- # in Intellij. This ensures that the tests are run with stdout/stderr
- # objects that work when passed to subprocess.run(stdout/stderr). Without it
- # the tests are run with a FlushingStringIO object that has no fileno
- # attribute - https://youtrack.jetbrains.com/issue/PY-27883.
- stdout: io.TextIOBase = sys.stdout
+ # Used to run subprocesses for this.
+ subprocess_runner: SubprocessRunner
- # Destination for stderr from subprocesses.
- stderr: io.TextIOBase = sys.stderr
-
- # The OUT_DIR environment variable.
- out_dir: str = "uninitialized-out"
+ # Builds sdk snapshots
+ snapshot_builder: SnapshotBuilder
# The DIST_DIR environment variable.
dist_dir: str = "uninitialized-dist"
@@ -312,65 +381,18 @@
# transformed to document where the changes came from.
script: str = sys.argv[0]
- def get_sdk_path(self, sdk_name, sdk_version):
- """Get the path to the sdk snapshot zip file produced by soong"""
- return os.path.join(self.out_dir, "soong/mainline-sdks",
- f"{sdk_name}-{sdk_version}.zip")
-
def produce_dist(self, modules):
sdk_versions = SDK_VERSIONS
self.build_sdks(sdk_versions, modules)
self.populate_dist(sdk_versions, modules)
+ self.populate_stubs(modules)
def build_sdks(self, sdk_versions, modules):
- # Build the SDKs once for each version.
- for sdk_version in sdk_versions:
- # Compute the paths to all the Soong generated sdk snapshot files
- # required by this script.
- paths = [
- self.get_sdk_path(sdk, sdk_version)
- for module in modules
- for sdk in module.sdks
- ]
-
- # TODO(ngeoffray): remove SOONG_ALLOW_MISSING_DEPENDENCIES, but we
- # currently break without it.
- #
- # Set SOONG_SDK_SNAPSHOT_USE_SRCJAR to generate .srcjars inside sdk
- # zip files as expected by prebuilt drop.
- extraEnv = {
- "SOONG_ALLOW_MISSING_DEPENDENCIES": "true",
- "SOONG_SDK_SNAPSHOT_USE_SRCJAR": "true",
- "SOONG_SDK_SNAPSHOT_VERSION": sdk_version,
- }
- # Unless explicitly specified in the calling environment set
- # TARGET_BUILD_VARIANT=user.
- # This MUST be identical to the TARGET_BUILD_VARIANT used to build
- # the corresponding APEXes otherwise it could result in different
- # hidden API flags, see http://b/202398851#comment29 for more info.
- targetBuildVariant = os.environ.get("TARGET_BUILD_VARIANT", "user")
- cmd = [
- "build/soong/soong_ui.bash",
- "--make-mode",
- "--soong-only",
- f"TARGET_BUILD_VARIANT={targetBuildVariant}",
- "TARGET_PRODUCT=mainline_sdk",
- "MODULE_BUILD_FROM_SOURCE=true",
- "out/soong/apex/depsinfo/new-allowed-deps.txt.check",
- ] + paths
- print_command(extraEnv, cmd)
- env = os.environ.copy()
- env.update(extraEnv)
- subprocess.run(
- cmd,
- env=env,
- check=True,
- stdout=self.stdout,
- stderr=self.stderr)
+ self.snapshot_builder.build_snapshots(sdk_versions, modules)
def unzip_current_stubs(self, sdk_name, apex_name):
"""Unzips stubs for "current" into {producer.dist_dir}/stubs/{apex}."""
- sdk_path = self.get_sdk_path(sdk_name, "current")
+ sdk_path = self.snapshot_builder.get_sdk_path(sdk_name, "current")
dest_dir = os.path.join(self.dist_dir, "stubs", apex_name)
print(
f"Extracting java_sdk_library files from {sdk_path} to {dest_dir}")
@@ -378,7 +400,7 @@
extract_matching_files_from_zip(
sdk_path, dest_dir, r"sdk_library/[^/]+/[^/]+\.(txt|jar|srcjar)")
- def populate_dist(self, sdk_versions, modules):
+ def populate_stubs(self, modules):
# TODO(b/199759953): Remove stubs once it is no longer used by gantry.
# Clear and populate the stubs directory.
stubs_dir = os.path.join(self.dist_dir, "stubs")
@@ -392,6 +414,7 @@
if sdk.endswith("-sdk"):
self.unzip_current_stubs(sdk, apex)
+ def populate_dist(self, sdk_versions, modules):
# Clear and populate the mainline-sdks dist directory.
sdks_dist_dir = os.path.join(self.dist_dir, "mainline-sdks")
shutil.rmtree(sdks_dist_dir, ignore_errors=True)
@@ -410,7 +433,8 @@
sdk_dist_dir = os.path.join(sdks_dist_dir, sdk_version,
apex, subdir)
- sdk_path = self.get_sdk_path(sdk, sdk_version)
+ sdk_path = self.snapshot_builder.get_sdk_path(
+ sdk, sdk_version)
self.dist_sdk_snapshot_zip(sdk_path, sdk_dist_dir,
module.transformations())
@@ -480,13 +504,10 @@
# not affected by a change of directory.
abs_src_zip_path = os.path.abspath(src_zip_path)
abs_dest_zip_path = os.path.abspath(dest_zip_path)
- subprocess.run(
+ producer.subprocess_runner.run(
["zip", "-q", abs_src_zip_path, "--out", abs_dest_zip_path] + paths,
# Change into the source directory before running zip.
- cwd=src_dir,
- stdout=producer.stdout,
- stderr=producer.stderr,
- check=True)
+ cwd=src_dir)
def apply_transformations(producer, tmp_dir, transformations):
@@ -505,12 +526,22 @@
def create_producer():
- return SdkDistProducer(
- # Variables initialized from environment variables that are set by the
- # calling mainline_modules_sdks.sh.
- out_dir=os.environ["OUT_DIR"],
- dist_dir=os.environ["DIST_DIR"],
+ # Variables initialized from environment variables that are set by the
+ # calling mainline_modules_sdks.sh.
+ out_dir = os.environ["OUT_DIR"]
+ dist_dir = os.environ["DIST_DIR"]
+
+ subprocess_runner = SubprocessRunner()
+ snapshot_builder = SnapshotBuilder(
+ subprocess_runner=subprocess_runner,
+ out_dir=out_dir,
)
+ return SdkDistProducer(
+ subprocess_runner=subprocess_runner,
+ snapshot_builder=snapshot_builder,
+ dist_dir=dist_dir,
+ )
+
def filter_modules(modules):
target_build_apps = os.environ.get("TARGET_BUILD_APPS")
@@ -520,6 +551,7 @@
else:
return modules
+
def main():
"""Program entry point."""
if not os.path.exists("build/make/core/Makefile"):
diff --git a/build/mainline_modules_sdks.sh b/build/mainline_modules_sdks.sh
index 4e25161..fb5cfd3 100755
--- a/build/mainline_modules_sdks.sh
+++ b/build/mainline_modules_sdks.sh
@@ -56,7 +56,7 @@
# provided by the build to ensure consistency across build environments.
export DIST_DIR OUT_DIR
- prebuilts/build-tools/linux-x86/bin/py3-cmd "${py3script}"
+ prebuilts/build-tools/linux-x86/bin/py3-cmd -u "${py3script}"
}
init "$@"
diff --git a/build/mainline_modules_sdks_test.py b/build/mainline_modules_sdks_test.py
index 5760136..cf6b28c 100644
--- a/build/mainline_modules_sdks_test.py
+++ b/build/mainline_modules_sdks_test.py
@@ -14,7 +14,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Unit tests for mainline_modules_sdks.py."""
-
from pathlib import Path
import os
import tempfile
@@ -23,13 +22,18 @@
import mainline_modules_sdks as mm
+MAINLINE_MODULES_BY_APEX = dict((m.apex, m) for m in mm.MAINLINE_MODULES)
-class TestPopulateDist(unittest.TestCase):
- def create_snapshot_file(self, out_dir, name, version):
- sdks_out_dir = Path(out_dir, "soong/mainline-sdks")
- sdks_out_dir.mkdir(parents=True, exist_ok=True)
- zip_file = Path(sdks_out_dir, f"{name}-{version}.zip")
+class FakeSnapshotBuilder(mm.SnapshotBuilder):
+ """A fake snapshot builder that does not run the build.
+
+ This skips the whole build process and just creates some fake sdk
+ modules.
+ """
+
+ def create_snapshot_file(self, name, version):
+ zip_file = Path(self.get_sdk_path(name, version))
with zipfile.ZipFile(zip_file, "w") as z:
z.writestr("Android.bp", "")
if name.endswith("-sdk"):
@@ -38,6 +42,19 @@
z.writestr("sdk_library/public/lib.jar", "")
z.writestr("sdk_library/public/api.txt", "")
+ def build_snapshots(self, sdk_versions, modules):
+ # Create input file structure.
+ sdks_out_dir = Path(self.get_mainline_sdks_path())
+ sdks_out_dir.mkdir(parents=True, exist_ok=True)
+ # Create a fake sdk zip file for each module.
+ for module in modules:
+ for sdk in module.sdks:
+ for sdk_version in sdk_versions:
+ self.create_snapshot_file(sdk, sdk_version)
+
+
+class TestProduceDist(unittest.TestCase):
+
def test(self):
"""Verify the dist/mainline-sdks directory is populated correctly"""
with tempfile.TemporaryDirectory() as tmp_dir:
@@ -47,22 +64,24 @@
os.mkdir(tmp_dist_dir)
modules = [
- mm.MAINLINE_MODULES_BY_APEX["com.android.art"],
- mm.MAINLINE_MODULES_BY_APEX["com.android.ipsec"],
+ MAINLINE_MODULES_BY_APEX["com.android.art"],
+ MAINLINE_MODULES_BY_APEX["com.android.ipsec"],
]
- # Create input file structure.
- for module in modules:
- for sdk in module.sdks:
- self.create_snapshot_file(tmp_out_dir, sdk, "current")
+ subprocess_runner = mm.SubprocessRunner()
+
+ snapshot_builder = FakeSnapshotBuilder(
+ subprocess_runner=subprocess_runner,
+ out_dir=tmp_out_dir,
+ )
producer = mm.SdkDistProducer(
- out_dir=tmp_out_dir,
+ subprocess_runner=subprocess_runner,
+ snapshot_builder=snapshot_builder,
dist_dir=tmp_dist_dir,
)
- sdk_versions = ["current"]
- producer.populate_dist(sdk_versions, modules)
+ producer.produce_dist(modules)
files = []
for abs_dir, _, filenames in os.walk(tmp_dist_dir):
@@ -114,7 +133,11 @@
class TestSoongConfigBoilerplateInserter(unittest.TestCase):
def apply_transformations(self, src, transformations, expected):
- producer = mm.SdkDistProducer(script=self._testMethodName)
+ producer = mm.SdkDistProducer(
+ subprocess_runner=None,
+ snapshot_builder=None,
+ script=self._testMethodName,
+ )
with tempfile.TemporaryDirectory() as tmp_dir:
path = os.path.join(tmp_dir, "Android.bp")
@@ -140,7 +163,7 @@
expected = readTestData("ipsec_Android.bp.expected")
- module = mm.MAINLINE_MODULES_BY_APEX["com.android.ipsec"]
+ module = MAINLINE_MODULES_BY_APEX["com.android.ipsec"]
transformations = module.transformations()
self.apply_transformations(src, transformations, expected)
@@ -156,7 +179,7 @@
expected = readTestData("art_Android.bp.expected")
- module = mm.MAINLINE_MODULES_BY_APEX["com.android.art"]
+ module = MAINLINE_MODULES_BY_APEX["com.android.art"]
transformations = module.transformations()
self.apply_transformations(src, transformations, expected)
@@ -171,7 +194,7 @@
def test_with_filter(self):
os.environ["TARGET_BUILD_APPS"] = "com.android.art"
modules = mm.filter_modules(mm.MAINLINE_MODULES)
- expected = mm.MAINLINE_MODULES_BY_APEX["com.android.art"]
+ expected = MAINLINE_MODULES_BY_APEX["com.android.art"]
self.assertEqual(modules, [expected])