diff options
author | Paul Duffin <paulduffin@google.com> | 2022-06-08 11:06:00 +0000 |
---|---|---|
committer | Cherrypicker Worker <android-build-cherrypicker-worker@google.com> | 2022-06-09 19:08:18 +0000 |
commit | e75e7c57e75f8099a8bfdcdcd1c30d3f32797746 (patch) | |
tree | 90fdd9dd79f57a2b4b5712e2b80710f3b2d6038d | |
parent | 60aabe84e99025954d0a183151ea73badb081574 (diff) | |
download | common-e75e7c57e75f8099a8bfdcdcd1c30d3f32797746.tar.gz |
Optional modules need a module specific soong config variable
Optional modules, i.e. those modules which may be provided by Google or
vendors depending on the vendor, need to have its own Soong config
variable that controls whether prebuilts are used or not. Without that
the build will always attempt to use the Google prebuilt module instead
of the vendor provided module.
This change:
1. Adds support for specifying which modules are optional and will
generate a module specific soong_config_module_type that uses a
module specific Soong config variable.
2. Generates the soong_config_module_type for optional modules inline
in the snapshot Android.bp file (instead of importing from a
manually curated definitions files). That simplifies the cost of
adding optional modules.
3. Adds some extra tests to ensure that S and Tiramisu behave the
same way.
Bug: 233965247
Test: atest mainline_modules_sdks_test
packages/modules/common/build/mainline_modules_sdks.sh
# Check the output to ensure that wifi uses the wifi specific
# Soong config but ipsec (as a non-optional module) does not.
# Unpack the wifi snapshot into prebuilts/module_sdk/Wifi
Change-Id: I6a85b6f9877fc251010ff2bbee75fe8fa99db9b4
(cherry picked from commit d20edd6c69cf07dc357d674463233c95aaa664ac)
Merged-In: I6a85b6f9877fc251010ff2bbee75fe8fa99db9b4
-rwxr-xr-x | build/mainline_modules_sdks.py | 97 | ||||
-rw-r--r-- | build/mainline_modules_sdks_test.py | 30 | ||||
-rw-r--r-- | build/mainline_modules_sdks_test_data/wifi_Android.bp.expected | 168 | ||||
-rw-r--r-- | build/mainline_modules_sdks_test_data/wifi_Android.bp.input | 108 |
4 files changed, 390 insertions, 13 deletions
diff --git a/build/mainline_modules_sdks.py b/build/mainline_modules_sdks.py index d3b4993f..a4dd1aca 100755 --- a/build/mainline_modules_sdks.py +++ b/build/mainline_modules_sdks.py @@ -20,6 +20,7 @@ the APEXes in it are built, otherwise all configured SDKs are built. """ import argparse import dataclasses +import functools import io import os import re @@ -161,25 +162,29 @@ class SoongConfigBoilerplateInserter(FileTransformation): }}, }},""") + # Add the module type to the list of module types that need to + # have corresponding config module types. + config_module_types.add(module_type) + # Change the module type to the corresponding soong config # module type by adding the prefix. module_type = self.configModuleTypePrefix + module_type - # Add the module type to the list of module types that need to - # be imported into the bp file. - config_module_types.add(module_type) # Generate the module, possibly with the new module type and - # containing the + # containing the soong config variables entry. content_lines.append(module_type + " {") content_lines.extend(module_content) content_lines.append("}") - # Add the soong_config_module_type_import module definition that 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' "{mt}",' for mt in sorted(config_module_types)]) - header_lines.append(f""" + if self.configBpDefFile: + # Add the soong_config_module_type_import module definition that + # 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}",' + for mt in sorted(config_module_types) + ]) + header_lines.append(f""" // Soong config variable stanza added by {producer.script}. soong_config_module_type_import {{ from: "{self.configBpDefFile}", @@ -188,6 +193,24 @@ soong_config_module_type_import {{ ], }} """) + else: + # Add the soong_config_module_type module definitions to the header + # lines so that they appear before any uses. + header_lines.append("") + 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 + header_lines.append(f""" +// Soong config variable module type added by {producer.script}. +soong_config_module_type {{ + name: "{config_module_type}", + module_type: "{module_type}", + config_namespace: "{self.configVar.namespace}", + bool_variables: ["{self.configVar.name}"], + properties: ["prefer"], +}} +""".lstrip()) # Overwrite the file with the updated contents. file.seek(0) @@ -396,6 +419,7 @@ ALL_BUILD_RELEASES = [] @dataclasses.dataclass(frozen=True) +@functools.total_ordering class BuildRelease: """Represents a build release""" @@ -453,6 +477,9 @@ class BuildRelease: "SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": self.name, }) + def __eq__(self, other): + return self.ordinal == other.ordinal + def __le__(self, other): return self.ordinal <= other.ordinal @@ -628,6 +655,30 @@ class MainlineModule: for_r_build: typing.Optional[ForRBuild] = None + # The last release on which this module was optional. + # + # Some modules are optional when they are first released, usually because + # some vendors of Android devices have their own customizations of the + # module that they would like to preserve and which cannot yet be achieved + # through the existing APIs. Once those issues have been resolved then they + # will become mandatory. + # + # This field records the last build release in which they are optional. It + # defaults to None which indicates that the module was never optional. + last_optional_release: typing.Optional[BuildRelease] = None + + # The short name for the module. + # + # Defaults to the last part of the apex name. + short_name: str = "" + + def __post_init__(self): + # If short_name is not set then set it to the last component of the apex + # name. + if not self.short_name: + short_name = self.apex.rsplit(".", 1)[-1] + object.__setattr__(self, "short_name", short_name) + def is_bundled(self): """Returns true for bundled modules. See BundledMainlineModule.""" return False @@ -636,11 +687,29 @@ class MainlineModule: """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 + + # 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 = "" + inserter = SoongConfigBoilerplateInserter( "Android.bp", - configVar=self.configVar, - configModuleTypePrefix=self.configModuleTypePrefix, - configBpDefFile=self.configBpDefFile) + configVar=config_var, + configModuleTypePrefix=config_module_type_prefix, + configBpDefFile=config_bp_def_file) transformations.append(inserter) return transformations @@ -800,6 +869,8 @@ MAINLINE_MODULES = [ for_r_build=ForRBuild(sdk_libraries=[ SdkLibrary(name="framework-wifi"), ]), + # Wifi has always been and is still optional. + last_optional_release=LATEST, ), ] diff --git a/build/mainline_modules_sdks_test.py b/build/mainline_modules_sdks_test.py index 6d06303c..56bc3218 100644 --- a/build/mainline_modules_sdks_test.py +++ b/build/mainline_modules_sdks_test.py @@ -413,6 +413,36 @@ 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(self): + """Tests the transformations applied to an optional mainline module. + + This uses wifi as an example of a optional mainline module. This checks + that the module specific Soong config module types and variables are + used. + """ + src = read_test_data("wifi_Android.bp.input") + + expected = read_test_data("wifi_Android.bp.expected") + + module = MAINLINE_MODULES_BY_APEX["com.android.wifi"] + transformations = module.transformations(mm.S) + + 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_art(self): """Tests the transformations applied to a the ART mainline module. diff --git a/build/mainline_modules_sdks_test_data/wifi_Android.bp.expected b/build/mainline_modules_sdks_test_data/wifi_Android.bp.expected new file mode 100644 index 00000000..d68abfef --- /dev/null +++ b/build/mainline_modules_sdks_test_data/wifi_Android.bp.expected @@ -0,0 +1,168 @@ +// This is auto-generated. DO NOT EDIT. + +// Soong config variable module type added by test_optional_mainline_module. +soong_config_module_type { + name: "wifi_prebuilt_java_import", + module_type: "java_import", + config_namespace: "wifi_module", + bool_variables: ["source_build"], + properties: ["prefer"], +} + +// Soong config variable module type added by test_optional_mainline_module. +soong_config_module_type { + name: "wifi_prebuilt_java_sdk_library_import", + module_type: "java_sdk_library_import", + config_namespace: "wifi_module", + bool_variables: ["source_build"], + properties: ["prefer"], +} + +// Soong config variable module type added by test_optional_mainline_module. +soong_config_module_type { + name: "wifi_prebuilt_prebuilt_bootclasspath_fragment", + module_type: "prebuilt_bootclasspath_fragment", + config_namespace: "wifi_module", + bool_variables: ["source_build"], + properties: ["prefer"], +} + +// Soong config variable module type added by test_optional_mainline_module. +soong_config_module_type { + name: "wifi_prebuilt_prebuilt_systemserverclasspath_fragment", + module_type: "prebuilt_systemserverclasspath_fragment", + config_namespace: "wifi_module", + bool_variables: ["source_build"], + properties: ["prefer"], +} + +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"], +} + +wifi_prebuilt_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. + prefer: true, + soong_config_variables: { + source_build: { + prefer: false, + }, + }, + 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", + }, +} + +wifi_prebuilt_java_sdk_library_import { + name: "framework-wifi", + // Do not prefer prebuilt if the Soong config variable "source_build" in namespace "wifi_module" is true. + prefer: true, + soong_config_variables: { + source_build: { + prefer: false, + }, + }, + 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", + }, +} + +wifi_prebuilt_java_import { + name: "service-wifi", + // Do not prefer prebuilt if the Soong config variable "source_build" in namespace "wifi_module" is true. + prefer: true, + soong_config_variables: { + source_build: { + prefer: false, + }, + }, + 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"], +} + +wifi_prebuilt_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. + prefer: true, + soong_config_variables: { + source_build: { + prefer: false, + }, + }, + visibility: ["//visibility:public"], + apex_available: ["com.android.wifi"], + licenses: ["wifi-module-sdk_Android-Apache-2.0"], + standalone_contents: ["service-wifi"], +} diff --git a/build/mainline_modules_sdks_test_data/wifi_Android.bp.input b/build/mainline_modules_sdks_test_data/wifi_Android.bp.input new file mode 100644 index 00000000..29ce3987 --- /dev/null +++ b/build/mainline_modules_sdks_test_data/wifi_Android.bp.input @@ -0,0 +1,108 @@ +// 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", + prefer: false, + 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", + prefer: false, + 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", + prefer: false, + 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", + prefer: false, + visibility: ["//visibility:public"], + apex_available: ["com.android.wifi"], + licenses: ["wifi-module-sdk_Android-Apache-2.0"], + standalone_contents: ["service-wifi"], +} |