diff options
| -rw-r--r-- | java/Android.bp | 2 | ||||
| -rw-r--r-- | java/platform_bootclasspath.go | 74 | ||||
| -rw-r--r-- | java/platform_bootclasspath_test.go | 38 | ||||
| -rw-r--r-- | java/testing.go | 1 | ||||
| -rwxr-xr-x | scripts/manifest_check.py | 69 | ||||
| -rwxr-xr-x | scripts/manifest_check_test.py | 4 |
6 files changed, 163 insertions, 25 deletions
diff --git a/java/Android.bp b/java/Android.bp index b6c14ac37..8334b85ec 100644 --- a/java/Android.bp +++ b/java/Android.bp @@ -50,6 +50,7 @@ bootstrap_go_package { "kotlin.go", "lint.go", "legacy_core_platform_api_usage.go", + "platform_bootclasspath.go", "platform_compat_config.go", "plugin.go", "prebuilt_apis.go", @@ -79,6 +80,7 @@ bootstrap_go_package { "java_test.go", "jdeps_test.go", "kotlin_test.go", + "platform_bootclasspath_test.go", "platform_compat_config_test.go", "plugin_test.go", "rro_test.go", diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go new file mode 100644 index 000000000..550707754 --- /dev/null +++ b/java/platform_bootclasspath.go @@ -0,0 +1,74 @@ +// Copyright 2021 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// 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. + +package java + +import ( + "android/soong/android" + "android/soong/dexpreopt" +) + +func init() { + registerPlatformBootclasspathBuildComponents(android.InitRegistrationContext) +} + +func registerPlatformBootclasspathBuildComponents(ctx android.RegistrationContext) { + ctx.RegisterModuleType("platform_bootclasspath", platformBootclasspathFactory) +} + +type platformBootclasspathModule struct { + android.ModuleBase +} + +func platformBootclasspathFactory() android.Module { + m := &platformBootclasspathModule{} + android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) + return m +} + +func (b *platformBootclasspathModule) DepsMutator(ctx android.BottomUpMutatorContext) { + if SkipDexpreoptBootJars(ctx) { + return + } + + // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The + // path is retrieved from the dependency by GetGlobalSoongConfig(ctx). + dexpreopt.RegisterToolDeps(ctx) +} + +func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { + // Nothing to do if skipping the dexpreopt of boot image jars. + if SkipDexpreoptBootJars(ctx) { + return + } + + // Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars + // GenerateSingletonBuildActions method as it cannot create it for itself. + dexpreopt.GetGlobalSoongConfig(ctx) + + imageConfig := b.getImageConfig(ctx) + if imageConfig == nil { + return + } + + // Construct the boot image info from the config. + info := BootImageInfo{imageConfig: imageConfig} + + // Make it available for other modules. + ctx.SetProvider(BootImageInfoProvider, info) +} + +func (b *platformBootclasspathModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig { + return defaultBootImageConfig(ctx) +} diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go new file mode 100644 index 000000000..1c81cfdc2 --- /dev/null +++ b/java/platform_bootclasspath_test.go @@ -0,0 +1,38 @@ +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// 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. + +package java + +import ( + "testing" + + "android/soong/android" + "android/soong/dexpreopt" +) + +// Contains some simple tests for platform_bootclasspath. + +var prepareForTestWithPlatformBootclasspath = android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + dexpreopt.PrepareForTestByEnablingDexpreopt, +) + +func TestPlatformBootclasspath(t *testing.T) { + prepareForTestWithPlatformBootclasspath. + RunTestWithBp(t, ` + platform_bootclasspath { + name: "platform-bootclasspath", + } + `) +} diff --git a/java/testing.go b/java/testing.go index 1113af72c..80c107d12 100644 --- a/java/testing.go +++ b/java/testing.go @@ -194,6 +194,7 @@ func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) { RegisterDocsBuildComponents(ctx) RegisterGenRuleBuildComponents(ctx) registerJavaBuildComponents(ctx) + registerPlatformBootclasspathBuildComponents(ctx) RegisterPrebuiltApisBuildComponents(ctx) RegisterRuntimeResourceOverlayBuildComponents(ctx) RegisterSdkLibraryBuildComponents(ctx) diff --git a/scripts/manifest_check.py b/scripts/manifest_check.py index 907f239cf..8168fbf6a 100755 --- a/scripts/manifest_check.py +++ b/scripts/manifest_check.py @@ -74,7 +74,7 @@ def parse_args(): return parser.parse_args() -def enforce_uses_libraries(manifest, required, optional, relax, is_apk = False): +def enforce_uses_libraries(manifest, required, optional, relax, is_apk, path): """Verify that the <uses-library> tags in the manifest match those provided by the build system. @@ -86,26 +86,36 @@ def enforce_uses_libraries(manifest, required, optional, relax, is_apk = False): is_apk: if the manifest comes from an APK or an XML file """ if is_apk: - manifest_required, manifest_optional = extract_uses_libs_apk(manifest) + manifest_required, manifest_optional, tags = extract_uses_libs_apk(manifest) else: - manifest_required, manifest_optional = extract_uses_libs_xml(manifest) - - err = [] - if manifest_required != required: - err.append('Expected required <uses-library> tags "%s", got "%s"' % - (', '.join(required), ', '.join(manifest_required))) - - if manifest_optional != optional: - err.append('Expected optional <uses-library> tags "%s", got "%s"' % - (', '.join(optional), ', '.join(manifest_optional))) - - if err: - errmsg = '\n'.join(err) - if not relax: - raise ManifestMismatchError(errmsg) - return errmsg - - return None + manifest_required, manifest_optional, tags = extract_uses_libs_xml(manifest) + + if manifest_required == required and manifest_optional == optional: + return None + + errmsg = ''.join([ + 'mismatch in the <uses-library> tags between the build system and the ' + 'manifest:\n', + '\t- required libraries in build system: [%s]\n' % ', '.join(required), + '\t vs. in the manifest: [%s]\n' % ', '.join(manifest_required), + '\t- optional libraries in build system: [%s]\n' % ', '.join(optional), + '\t vs. in the manifest: [%s]\n' % ', '.join(manifest_optional), + '\t- tags in the manifest (%s):\n' % path, + '\t\t%s\n' % '\t\t'.join(tags), + 'note: the following options are available:\n', + '\t- to temporarily disable the check on command line, rebuild with ', + 'RELAX_USES_LIBRARY_CHECK=true (this will set compiler filter "verify" ', + 'and disable AOT-compilation in dexpreopt)\n', + '\t- to temporarily disable the check for the whole product, set ', + 'PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true in the product makefiles\n', + '\t- to fix the check, make build system properties coherent with the ' + 'manifest\n', + '\t- see build/make/Changes.md for details\n']) + + if not relax: + raise ManifestMismatchError(errmsg) + + return errmsg def extract_uses_libs_apk(badging): @@ -115,14 +125,19 @@ def extract_uses_libs_apk(badging): required = [] optional = [] + lines = [] for match in re.finditer(pattern, badging): + lines.append(match.group(0)) libname = match.group(2) if match.group(1) == None: required.append(libname) else: optional.append(libname) - return first_unique_elements(required), first_unique_elements(optional) + required = first_unique_elements(required) + optional = first_unique_elements(optional) + tags = first_unique_elements(lines) + return required, optional, tags def extract_uses_libs_xml(xml): @@ -143,7 +158,15 @@ def extract_uses_libs_xml(xml): required = [uses_library_name(x) for x in libs if uses_library_required(x)] optional = [uses_library_name(x) for x in libs if not uses_library_required(x)] - return first_unique_elements(required), first_unique_elements(optional) + # render <uses-library> tags as XML for a pretty error message + tags = [] + for lib in libs: + tags.append(lib.toprettyxml()) + + required = first_unique_elements(required) + optional = first_unique_elements(optional) + tags = first_unique_elements(tags) + return required, optional, tags def first_unique_elements(l): @@ -278,7 +301,7 @@ def main(): # in the manifest. Raise an exception on mismatch, unless the script was # passed a special parameter to suppress exceptions. errmsg = enforce_uses_libraries(manifest, required, optional, - args.enforce_uses_libraries_relax, is_apk) + args.enforce_uses_libraries_relax, is_apk, args.input) # Create a status file that is empty on success, or contains an error # message on failure. When exceptions are suppressed, dexpreopt command diff --git a/scripts/manifest_check_test.py b/scripts/manifest_check_test.py index 635ba9d1d..7159bdd74 100755 --- a/scripts/manifest_check_test.py +++ b/scripts/manifest_check_test.py @@ -49,9 +49,9 @@ class EnforceUsesLibrariesTest(unittest.TestCase): try: relax = False manifest_check.enforce_uses_libraries(doc, uses_libraries, - optional_uses_libraries, relax, is_apk=False) + optional_uses_libraries, relax, False, 'path/to/X/AndroidManifest.xml') manifest_check.enforce_uses_libraries(apk, uses_libraries, - optional_uses_libraries, relax, is_apk=True) + optional_uses_libraries, relax, True, 'path/to/X/X.apk') return True except manifest_check.ManifestMismatchError: return False |