Switch T+ sdk snapshots to use use_source_config_var property am: db3a3c7df6

Original change: https://android-review.googlesource.com/c/platform/packages/modules/common/+/2165043

Change-Id: I17a489e2def737629711be6bc10f49a3e4a8ebd8
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Paul Duffin
2022-07-26 19:36:17 +00:00
committed by Automerger Merge Worker
4 changed files with 341 additions and 45 deletions

View File

@@ -21,6 +21,7 @@ the APEXes in it are built, otherwise all configured SDKs are built.
import argparse
import dataclasses
import datetime
import enum
import functools
import io
import json
@@ -72,21 +73,41 @@ class FileTransformation:
path: str
def apply(self, producer, path):
"""Apply the transformation to the src_path to produce the dest_path."""
"""Apply the transformation to the path; changing it in place."""
with open(path, "r+", encoding="utf8") as file:
self._apply_transformation(producer, file)
def _apply_transformation(self, producer, file):
"""Apply the transformation to the file.
The file has been opened in read/write mode so the implementation of
this must read the contents and then reset the file to the beginning
and write the altered contents.
"""
raise NotImplementedError
@dataclasses.dataclass(frozen=True)
class SoongConfigBoilerplateInserter(FileTransformation):
class SoongConfigVarTransformation(FileTransformation):
# The configuration variable that will control the prefer setting.
configVar: ConfigVar
# The line containing the prefer property.
PREFER_LINE = " prefer: false,"
def _apply_transformation(self, producer, file):
raise NotImplementedError
@dataclasses.dataclass(frozen=True)
class SoongConfigBoilerplateInserter(SoongConfigVarTransformation):
"""Transforms an Android.bp file to add soong config boilerplate.
The boilerplate allows the prefer setting of the modules to be controlled
through a Soong configuration variable.
"""
# The configuration variable that will control the prefer setting.
configVar: ConfigVar
# The bp file containing the definitions of the configuration module types
# to use in the sdk.
configBpDefFile: str
@@ -94,6 +115,9 @@ class SoongConfigBoilerplateInserter(FileTransformation):
# The prefix to use for the soong config module types.
configModuleTypePrefix: str
def config_module_type(self, module_type):
return self.configModuleTypePrefix + module_type
def apply(self, producer, path):
with open(path, "r+", encoding="utf8") as file:
self._apply_transformation(producer, file)
@@ -144,7 +168,7 @@ class SoongConfigBoilerplateInserter(FileTransformation):
# unversioned relies on the fact that the unversioned modules
# set "prefer: false", while the versioned modules do not. That
# is a little bit fragile so may require some additional checks.
if module_line != " prefer: false,":
if module_line != self.PREFER_LINE:
# The line does not indicate that the module needs the
# soong config boilerplate so add the line and skip to the
# next one.
@@ -170,7 +194,7 @@ class SoongConfigBoilerplateInserter(FileTransformation):
# Change the module type to the corresponding soong config
# module type by adding the prefix.
module_type = self.configModuleTypePrefix + module_type
module_type = self.config_module_type(module_type)
# Generate the module, possibly with the new module type and
# containing the soong config variables entry.
@@ -183,7 +207,7 @@ class SoongConfigBoilerplateInserter(FileTransformation):
# imports the soong config module types into this bp file to the
# header lines so that they appear before any uses.
module_types = "\n".join([
f' "{self.configModuleTypePrefix}{mt}",'
f' "{self.config_module_type(mt)}",'
for mt in sorted(config_module_types)
])
header_lines.append(f"""
@@ -202,7 +226,7 @@ soong_config_module_type_import {{
for module_type in sorted(config_module_types):
# Create the corresponding soong config module type name by
# adding the prefix.
config_module_type = self.configModuleTypePrefix + module_type
config_module_type = self.config_module_type(module_type)
header_lines.append(f"""
// Soong config variable module type added by {producer.script}.
soong_config_module_type {{
@@ -220,6 +244,33 @@ soong_config_module_type {{
file.write("\n".join(header_lines + content_lines) + "\n")
@dataclasses.dataclass(frozen=True)
class UseSourceConfigVarTransformation(SoongConfigVarTransformation):
def _apply_transformation(self, producer, file):
lines = []
for line in file:
line = line.rstrip("\n")
if line != self.PREFER_LINE:
lines.append(line)
continue
# Replace "prefer: false" with "use_source_config_var {...}".
namespace = self.configVar.namespace
name = self.configVar.name
lines.append(f"""\
// Do not prefer prebuilt if the Soong config variable "{name}" in namespace "{namespace}" is true.
use_source_config_var: {{
config_namespace: "{namespace}",
var_name: "{name}",
}},""")
# Overwrite the file with the updated contents.
file.seek(0)
file.truncate()
file.write("\n".join(lines) + "\n")
@dataclasses.dataclass()
class SubprocessRunner:
"""Runs subprocesses"""
@@ -565,6 +616,19 @@ SDK_VERSIONS = [
ALL_BUILD_RELEASES = []
class PreferHandling(enum.Enum):
"""Enumeration of the various ways of handling prefer properties"""
# No special prefer property handling is required.
NONE = enum.auto()
# Apply the SoongConfigBoilerplateInserter transformation.
SOONG_CONFIG = enum.auto()
# Use the use_source_config_var property added in T.
USE_SOURCE_CONFIG_VAR_PROPERTY = enum.auto()
@dataclasses.dataclass(frozen=True)
@functools.total_ordering
class BuildRelease:
@@ -601,7 +665,8 @@ class BuildRelease:
# Whether this build release supports the Soong config boilerplate that is
# used to control the prefer setting of modules via a Soong config variable.
supports_soong_config_boilerplate: bool = True
preferHandling: PreferHandling = \
PreferHandling.USE_SOURCE_CONFIG_VAR_PROPERTY
def __post_init__(self):
# The following use object.__setattr__ as this object is frozen and
@@ -663,6 +728,8 @@ Q = BuildRelease(
name="Q",
# At the moment we do not generate a snapshot for Q.
creator=create_no_dist_snapshot,
# This does not support or need any special prefer property handling.
preferHandling=PreferHandling.NONE,
)
R = BuildRelease(
name="R",
@@ -673,17 +740,23 @@ R = BuildRelease(
# unlikely to) support building an sdk snapshot for R so create an empty
# environment to pass to Soong instead.
soong_env={},
# R does not support or need Soong config boilerplate.
supports_soong_config_boilerplate=False)
# This does not support or need any special prefer property handling.
preferHandling=PreferHandling.NONE,
)
S = BuildRelease(
name="S",
# Generate a snapshot for S using Soong.
creator=create_sdk_snapshots_in_soong,
# This requires the SoongConfigBoilerplateInserter transformation to be
# applied.
preferHandling=PreferHandling.SOONG_CONFIG,
)
Tiramisu = BuildRelease(
name="Tiramisu",
# Generate a snapshot for Tiramisu using Soong.
creator=create_sdk_snapshots_in_soong,
# This supports the use_source_config_var property.
preferHandling=PreferHandling.USE_SOURCE_CONFIG_VAR_PROPERTY,
)
# Insert additional BuildRelease definitions for following releases here,
@@ -801,31 +874,37 @@ class MainlineModule:
def transformations(self, build_release):
"""Returns the transformations to apply to this module's snapshot(s)."""
transformations = []
if build_release.supports_soong_config_boilerplate:
config_var = self.configVar
config_module_type_prefix = self.configModuleTypePrefix
config_bp_def_file = self.configBpDefFile
config_var = self.configVar
config_module_type_prefix = self.configModuleTypePrefix
config_bp_def_file = self.configBpDefFile
# If the module is optional then it needs its own Soong config
# variable to allow it to be managed separately from other modules.
if (self.last_optional_release and
self.last_optional_release > build_release):
config_var = ConfigVar(
namespace=f"{self.short_name}_module",
name="source_build",
)
config_module_type_prefix = f"{self.short_name}_prebuilt_"
# Optional modules don't have their own config_bp_def_file so
# they have to generate the soong_config_module_types inline.
config_bp_def_file = ""
# If the module is optional then it needs its own Soong config
# variable to allow it to be managed separately from other modules.
if (self.last_optional_release and
self.last_optional_release > build_release):
config_var = ConfigVar(
namespace=f"{self.short_name}_module",
name="source_build",
)
config_module_type_prefix = f"{self.short_name}_prebuilt_"
# Optional modules don't have their own config_bp_def_file so
# they have to generate the soong_config_module_types inline.
config_bp_def_file = ""
prefer_handling = build_release.preferHandling
if prefer_handling == PreferHandling.SOONG_CONFIG:
inserter = SoongConfigBoilerplateInserter(
"Android.bp",
configVar=config_var,
configModuleTypePrefix=config_module_type_prefix,
configBpDefFile=config_bp_def_file)
transformations.append(inserter)
elif prefer_handling == PreferHandling.USE_SOURCE_CONFIG_VAR_PROPERTY:
transformation = UseSourceConfigVarTransformation(
"Android.bp", configVar=config_var)
transformations.append(transformation)
return transformations
def is_required_for(self, target_build_release):

View File

@@ -391,7 +391,7 @@ def read_test_data(relative_path):
return f.read()
class TestSoongConfigBoilerplateInserter(unittest.TestCase):
class TestAndroidBpTransformations(unittest.TestCase):
def apply_transformations(self, src, transformations, expected):
producer = mm.SdkDistProducer(
@@ -414,9 +414,9 @@ class TestSoongConfigBoilerplateInserter(unittest.TestCase):
self.assertEqual(expected, result)
def test_common_mainline_module(self):
"""Tests the transformations applied to a common mainline module.
"""Tests the transformations applied to a common mainline sdk on S.
This uses ipsec as an example of a common mainline module. This checks
This uses ipsec as an example of a common mainline sdk. This checks
that the correct Soong config module types and variables are used and
that it imports the definitions from the correct location.
"""
@@ -429,17 +429,25 @@ class TestSoongConfigBoilerplateInserter(unittest.TestCase):
self.apply_transformations(src, transformations, expected)
# Check that Tiramisu provides the same transformations as S.
tiramisu_transformations = module.transformations(mm.Tiramisu)
self.assertEqual(
transformations,
tiramisu_transformations,
msg="Tiramisu must use the same transformations as S")
def test_common_mainline_module_tiramisu(self):
"""Tests the transformations applied to a common mainline sdk on T.
This uses ipsec as an example of a common mainline sdk. This checks
that the use_source_config_var property is inserted.
"""
src = read_test_data("ipsec_Android.bp.input")
expected = read_test_data("ipsec_tiramisu_Android.bp.expected")
module = MAINLINE_MODULES_BY_APEX["com.android.ipsec"]
transformations = module.transformations(mm.Tiramisu)
self.apply_transformations(src, transformations, expected)
def test_optional_mainline_module(self):
"""Tests the transformations applied to an optional mainline module.
"""Tests the transformations applied to an optional mainline sdk on S.
This uses wifi as an example of a optional mainline module. This checks
This uses wifi as an example of a optional mainline sdk. This checks
that the module specific Soong config module types and variables are
used.
"""
@@ -452,12 +460,20 @@ class TestSoongConfigBoilerplateInserter(unittest.TestCase):
self.apply_transformations(src, transformations, expected)
# Check that Tiramisu provides the same transformations as S.
tiramisu_transformations = module.transformations(mm.Tiramisu)
self.assertEqual(
transformations,
tiramisu_transformations,
msg="Tiramisu must use the same transformations as S")
def test_optional_mainline_module_tiramisu(self):
"""Tests the transformations applied to an optional mainline sdk on T.
This uses wifi as an example of a optional mainline sdk. This checks
that the use_source_config_var property is inserted.
"""
src = read_test_data("wifi_Android.bp.input")
expected = read_test_data("wifi_tiramisu_Android.bp.expected")
module = MAINLINE_MODULES_BY_APEX["com.android.wifi"]
transformations = module.transformations(mm.Tiramisu)
self.apply_transformations(src, transformations, expected)
def test_art(self):
"""Tests the transformations applied to a the ART mainline module.

View File

@@ -0,0 +1,77 @@
// 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"],
}

View File

@@ -0,0 +1,124 @@
// 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.wifi-bootclasspath-fragment",
// Do not prefer prebuilt if the Soong config variable "source_build" in namespace "wifi_module" is true.
use_source_config_var: {
config_namespace: "wifi_module",
var_name: "source_build",
},
visibility: ["//visibility:public"],
apex_available: ["com.android.wifi"],
licenses: ["wifi-module-sdk_Android-Apache-2.0"],
contents: ["framework-wifi"],
fragments: [
{
apex: "com.android.art",
module: "art-bootclasspath-fragment",
},
],
hidden_api: {
unsupported: ["hiddenapi/hiddenapi-unsupported.txt"],
max_target_r_low_priority: ["hiddenapi/hiddenapi-max-target-r-low-priority.txt"],
max_target_o_low_priority: ["hiddenapi/hiddenapi-max-target-o-low-priority.txt"],
annotation_flags: "hiddenapi/annotation-flags.csv",
metadata: "hiddenapi/metadata.csv",
index: "hiddenapi/index.csv",
signature_patterns: "hiddenapi/signature-patterns.csv",
filtered_stub_flags: "hiddenapi/filtered-stub-flags.csv",
filtered_flags: "hiddenapi/filtered-flags.csv",
},
}
java_sdk_library_import {
name: "framework-wifi",
// Do not prefer prebuilt if the Soong config variable "source_build" in namespace "wifi_module" is true.
use_source_config_var: {
config_namespace: "wifi_module",
var_name: "source_build",
},
visibility: ["//visibility:public"],
apex_available: [
"com.android.wifi",
"test_com.android.wifi",
],
licenses: ["wifi-module-sdk_Android-Apache-2.0"],
shared_library: false,
permitted_packages: [
"android.hardware.wifi",
"android.net.wifi",
"com.android.wifi.x",
],
public: {
jars: ["sdk_library/public/framework-wifi-stubs.jar"],
stub_srcs: ["sdk_library/public/framework-wifi_stub_sources"],
current_api: "sdk_library/public/framework-wifi.txt",
removed_api: "sdk_library/public/framework-wifi-removed.txt",
annotations: "sdk_library/public/framework-wifi_annotations.zip",
sdk_version: "module_current",
},
system: {
jars: ["sdk_library/system/framework-wifi-stubs.jar"],
stub_srcs: ["sdk_library/system/framework-wifi_stub_sources"],
current_api: "sdk_library/system/framework-wifi.txt",
removed_api: "sdk_library/system/framework-wifi-removed.txt",
annotations: "sdk_library/system/framework-wifi_annotations.zip",
sdk_version: "module_current",
},
module_lib: {
jars: ["sdk_library/module-lib/framework-wifi-stubs.jar"],
stub_srcs: ["sdk_library/module-lib/framework-wifi_stub_sources"],
current_api: "sdk_library/module-lib/framework-wifi.txt",
removed_api: "sdk_library/module-lib/framework-wifi-removed.txt",
annotations: "sdk_library/module-lib/framework-wifi_annotations.zip",
sdk_version: "module_current",
},
}
java_import {
name: "service-wifi",
// Do not prefer prebuilt if the Soong config variable "source_build" in namespace "wifi_module" is true.
use_source_config_var: {
config_namespace: "wifi_module",
var_name: "source_build",
},
visibility: [
"//frameworks/opt/net/wifi/service/apex",
"//frameworks/opt/net/wifi/tests/wifitests/apex",
"//packages/modules/Wifi/apex",
"//packages/modules/Wifi/service",
"//packages/modules/Wifi/service/tests/wifitests/apex",
],
apex_available: [
"com.android.wifi",
"test_com.android.wifi",
],
licenses: ["wifi-module-sdk_Android-Apache-2.0"],
jars: ["java_systemserver_libs/snapshot/jars/are/invalid/service-wifi.jar"],
}
license {
name: "wifi-module-sdk_Android-Apache-2.0",
visibility: ["//visibility:private"],
license_kinds: ["SPDX-license-identifier-Apache-2.0"],
license_text: ["licenses/build/soong/licenses/LICENSE"],
}
prebuilt_systemserverclasspath_fragment {
name: "com.android.wifi-systemserverclasspath-fragment",
// Do not prefer prebuilt if the Soong config variable "source_build" in namespace "wifi_module" is true.
use_source_config_var: {
config_namespace: "wifi_module",
var_name: "source_build",
},
visibility: ["//visibility:public"],
apex_available: ["com.android.wifi"],
licenses: ["wifi-module-sdk_Android-Apache-2.0"],
standalone_contents: ["service-wifi"],
}