Adding additional_transformations

Add additional_transformations for module sdk build. This feature is
only supported by S+ releases.

Bug: 254111089
Test: atest mainline_modules_sdks_test --host
Ignore-AOSP-First: Check into internal branch first to make sure all
testing works.

Merged-In: I94989519011e31c7db33656c6730c4f8fd5e0a4f
Change-Id: Idc8bd682550f59e086c431b0be38bfbdf8a75127
This commit is contained in:
Zhi Dou
2023-03-17 16:20:59 +00:00
committed by zhidou
parent b50e8ce2fb
commit 7c3ab89443
3 changed files with 132 additions and 18 deletions

View File

@@ -72,12 +72,12 @@ class FileTransformation:
# The path of the file within the SDK snapshot zip file. # The path of the file within the SDK snapshot zip file.
path: str path: str
def apply(self, producer, path, build_release): def apply(self, producer, path):
"""Apply the transformation to the path; changing it in place.""" """Apply the transformation to the path; changing it in place."""
with open(path, "r+", encoding="utf8") as file: with open(path, "r+", encoding="utf8") as file:
self._apply_transformation(producer, file, build_release) self._apply_transformation(producer, file)
def _apply_transformation(self, producer, file, build_release): def _apply_transformation(self, producer, file):
"""Apply the transformation to the file. """Apply the transformation to the file.
The file has been opened in read/write mode so the implementation of The file has been opened in read/write mode so the implementation of
@@ -96,7 +96,7 @@ class SoongConfigVarTransformation(FileTransformation):
# The line containing the prefer property. # The line containing the prefer property.
PREFER_LINE = " prefer: false," PREFER_LINE = " prefer: false,"
def _apply_transformation(self, producer, file, build_release): def _apply_transformation(self, producer, file):
raise NotImplementedError raise NotImplementedError
@@ -117,10 +117,6 @@ class SoongConfigBoilerplateInserter(SoongConfigVarTransformation):
def config_module_type(self, module_type): def config_module_type(self, module_type):
return self.configModuleTypePrefix + module_type return self.configModuleTypePrefix + module_type
def apply(self, producer, path, build_release):
with open(path, "r+", encoding="utf8") as file:
self._apply_transformation(producer, file, build_release)
def _apply_transformation(self, producer, file, build_release): def _apply_transformation(self, producer, file, build_release):
# TODO(b/174997203): Remove this when we have a proper way to control # TODO(b/174997203): Remove this when we have a proper way to control
# prefer flags in Mainline modules. # prefer flags in Mainline modules.
@@ -228,7 +224,7 @@ soong_config_module_type {{
@dataclasses.dataclass(frozen=True) @dataclasses.dataclass(frozen=True)
class UseSourceConfigVarTransformation(SoongConfigVarTransformation): class UseSourceConfigVarTransformation(SoongConfigVarTransformation):
def _apply_transformation(self, producer, file, build_release): def _apply_transformation(self, producer, file):
lines = [] lines = []
for line in file: for line in file:
line = line.rstrip("\n") line = line.rstrip("\n")
@@ -864,6 +860,9 @@ class MainlineModule:
# Defaults to the last part of the apex name. # Defaults to the last part of the apex name.
short_name: str = "" short_name: str = ""
# Additional transformations
additional_transformations: list[FileTransformation] = None
def __post_init__(self): def __post_init__(self):
# If short_name is not set then set it to the last component of the apex # If short_name is not set then set it to the last component of the apex
# name. # name.
@@ -905,6 +904,9 @@ class MainlineModule:
"Android.bp", configVar=config_var) "Android.bp", configVar=config_var)
transformations.append(transformation) transformations.append(transformation)
if self.additional_transformations and build_release > R:
transformations.extend(self.additional_transformations)
return transformations return transformations
def is_required_for(self, target_build_release): def is_required_for(self, target_build_release):
@@ -1259,11 +1261,9 @@ class SdkDistProducer:
sdk_path = sdk_snapshot_zip_file(snapshots_dir, sdk) sdk_path = sdk_snapshot_zip_file(snapshots_dir, sdk)
sdk_type = sdk_type_from_name(sdk) sdk_type = sdk_type_from_name(sdk)
transformations = module.transformations(build_release, sdk_type) transformations = module.transformations(build_release, sdk_type)
self.dist_sdk_snapshot_zip( self.dist_sdk_snapshot_zip(sdk_path, sdk_dist_subdir, transformations)
build_release, sdk_path, sdk_dist_subdir, transformations)
def dist_sdk_snapshot_zip( def dist_sdk_snapshot_zip(self, src_sdk_zip, sdk_dist_dir, transformations):
self, build_release, src_sdk_zip, sdk_dist_dir, transformations):
"""Copy the sdk snapshot zip file to a dist directory. """Copy the sdk snapshot zip file to a dist directory.
If no transformations are provided then this simply copies the show sdk If no transformations are provided then this simply copies the show sdk
@@ -1271,8 +1271,7 @@ class SdkDistProducer:
provided then the files to be transformed are extracted from the provided then the files to be transformed are extracted from the
snapshot zip file, they are transformed to files in a separate directory snapshot zip file, they are transformed to files in a separate directory
and then a new zip file is created in the dist directory with the and then a new zip file is created in the dist directory with the
original files replaced by the newly transformed files. build_release is original files replaced by the newly transformed files.
provided for transformations if it is needed.
""" """
os.makedirs(sdk_dist_dir, exist_ok=True) os.makedirs(sdk_dist_dir, exist_ok=True)
dest_sdk_zip = os.path.join(sdk_dist_dir, os.path.basename(src_sdk_zip)) dest_sdk_zip = os.path.join(sdk_dist_dir, os.path.basename(src_sdk_zip))
@@ -1295,7 +1294,7 @@ class SdkDistProducer:
extract_matching_files_from_zip(src_sdk_zip, tmp_dir, pattern) extract_matching_files_from_zip(src_sdk_zip, tmp_dir, pattern)
# Apply the transformations to the extracted files in situ. # Apply the transformations to the extracted files in situ.
apply_transformations(self, tmp_dir, transformations, build_release) apply_transformations(self, tmp_dir, transformations)
# Replace the original entries in the zip with the transformed # Replace the original entries in the zip with the transformed
# files. # files.
@@ -1349,7 +1348,7 @@ def copy_zip_and_replace(producer, src_zip_path, dest_zip_path, src_dir, paths):
cwd=src_dir) cwd=src_dir)
def apply_transformations(producer, tmp_dir, transformations, build_release): def apply_transformations(producer, tmp_dir, transformations):
for transformation in transformations: for transformation in transformations:
path = os.path.join(tmp_dir, transformation.path) path = os.path.join(tmp_dir, transformation.path)
@@ -1357,7 +1356,7 @@ def apply_transformations(producer, tmp_dir, transformations, build_release):
modified = os.path.getmtime(path) modified = os.path.getmtime(path)
# Transform the file. # Transform the file.
transformation.apply(producer, path, build_release) transformation.apply(producer, path)
# Reset the timestamp of the file to the original timestamp before the # Reset the timestamp of the file to the original timestamp before the
# transformation was applied. # transformation was applied.

View File

@@ -570,6 +570,42 @@ class TestAndroidBpTransformations(unittest.TestCase):
self.apply_transformations(src, transformations, mm.R, expected) self.apply_transformations(src, transformations, mm.R, expected)
def test_additional_transformation(self):
"""Tests additional transformation.
This uses ipsec as an example of a common case for adding information
in Android.bp file.
This checks will append the information in Android.bp for a regular module.
"""
@dataclasses.dataclass(frozen=True)
class TestTransformation(mm.FileTransformation):
"""Transforms an Android.bp file by appending testing message."""
test_content: str = ""
def apply(self, producer, path, build_release):
with open(path, "a+", encoding="utf8") as file:
self._apply_transformation(producer, file, build_release)
def _apply_transformation(self, producer, file, build_release):
if build_release >= mm.Tiramisu:
file.write(self.test_content)
src = read_test_data("ipsec_Android.bp.input")
expected = read_test_data(
"ipsec_tiramisu_Android.bp.additional.expected")
test_transformation = TestTransformation(
"Android.bp", test_content="\n// Adding by test")
module = MAINLINE_MODULES_BY_APEX["com.android.ipsec"]
module = dataclasses.replace(
module, apex=module.apex,
first_release=module.first_release,
additional_transformations=[test_transformation])
transformations = module.transformations(mm.Tiramisu, mm.Sdk)
self.apply_transformations(src, transformations, mm.Tiramisu, expected)
class TestFilterModules(unittest.TestCase): class TestFilterModules(unittest.TestCase):

View File

@@ -0,0 +1,79 @@
// This is auto-generated. DO NOT EDIT.
package {
// A default list here prevents the license LSC from adding its own list which would
// be unnecessary as every module in the sdk already has its own licenses property.
default_applicable_licenses: ["Android-Apache-2.0"],
}
prebuilt_bootclasspath_fragment {
name: "com.android.ipsec-bootclasspath-fragment",
// Do not prefer prebuilt if the Soong config variable "module_build_from_source" in namespace "ANDROID" is true.
use_source_config_var: {
config_namespace: "ANDROID",
var_name: "module_build_from_source",
},
visibility: ["//visibility:public"],
apex_available: ["com.android.ipsec"],
licenses: ["ipsec-module-sdk_Android-Apache-2.0"],
contents: ["android.net.ipsec.ike"],
hidden_api: {
stub_flags: "hiddenapi/stub-flags.csv",
annotation_flags: "hiddenapi/annotation-flags.csv",
metadata: "hiddenapi/metadata.csv",
index: "hiddenapi/index.csv",
all_flags: "hiddenapi/all-flags.csv",
},
}
java_sdk_library_import {
name: "android.net.ipsec.ike",
// Do not prefer prebuilt if the Soong config variable "module_build_from_source" in namespace "ANDROID" is true.
use_source_config_var: {
config_namespace: "ANDROID",
var_name: "module_build_from_source",
},
visibility: ["//visibility:public"],
apex_available: [
"com.android.ipsec",
"test_com.android.ipsec",
],
licenses: ["ipsec-module-sdk_Android-Apache-2.0"],
shared_library: true,
compile_dex: true,
permitted_packages: [
"com.android.internal.net",
"android.net.ipsec.ike",
"android.net.eap",
],
public: {
jars: ["sdk_library/public/android.net.ipsec.ike-stubs.jar"],
stub_srcs: ["sdk_library/public/android.net.ipsec.ike.srcjar"],
current_api: "sdk_library/public/android.net.ipsec.ike.txt",
removed_api: "sdk_library/public/android.net.ipsec.ike-removed.txt",
sdk_version: "module_current",
},
system: {
jars: ["sdk_library/system/android.net.ipsec.ike-stubs.jar"],
stub_srcs: ["sdk_library/system/android.net.ipsec.ike.srcjar"],
current_api: "sdk_library/system/android.net.ipsec.ike.txt",
removed_api: "sdk_library/system/android.net.ipsec.ike-removed.txt",
sdk_version: "module_current",
},
module_lib: {
jars: ["sdk_library/module-lib/android.net.ipsec.ike-stubs.jar"],
stub_srcs: ["sdk_library/module-lib/android.net.ipsec.ike.srcjar"],
current_api: "sdk_library/module-lib/android.net.ipsec.ike.txt",
removed_api: "sdk_library/module-lib/android.net.ipsec.ike-removed.txt",
sdk_version: "module_current",
},
}
license {
name: "ipsec-module-sdk_Android-Apache-2.0",
visibility: ["//visibility:private"],
license_kinds: ["SPDX-license-identifier-Apache-2.0"],
license_text: ["licenses/build/soong/licenses/LICENSE"],
}
// Adding by test