Merge "Workaround to make AlwaysUsePrebuiltSdks() work with platform_bootclasspath"
This commit is contained in:
@@ -20,6 +20,7 @@ import (
|
||||
"android/soong/android"
|
||||
"android/soong/java"
|
||||
"github.com/google/blueprint"
|
||||
"github.com/google/blueprint/proptools"
|
||||
)
|
||||
|
||||
// Contains tests for platform_bootclasspath logic from java/platform_bootclasspath.go that requires
|
||||
@@ -174,6 +175,141 @@ func TestPlatformBootclasspathDependencies(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
// TestPlatformBootclasspath_AlwaysUsePrebuiltSdks verifies that the build does not fail when
|
||||
// AlwaysUsePrebuiltSdk() returns true. The structure of the modules in this test matches what
|
||||
// currently exists in some places in the Android build but it is not the intended structure. It is
|
||||
// in fact an invalid structure that should cause build failures. However, fixing that structure
|
||||
// will take too long so in the meantime this tests the workarounds to avoid build breakages.
|
||||
//
|
||||
// The main issues with this structure are:
|
||||
// 1. There is no prebuilt_bootclasspath_fragment referencing the "foo" java_sdk_library_import.
|
||||
// 2. There is no prebuilt_apex/apex_set which makes the dex implementation jar available to the
|
||||
// prebuilt_bootclasspath_fragment and the "foo" java_sdk_library_import.
|
||||
//
|
||||
// Together these cause the following symptoms:
|
||||
// 1. The "foo" java_sdk_library_import does not have a dex implementation jar.
|
||||
// 2. The "foo" java_sdk_library_import does not have a myapex variant.
|
||||
//
|
||||
// TODO(b/179354495): Fix the structure in this test once the main Android build has been fixed.
|
||||
func TestPlatformBootclasspath_AlwaysUsePrebuiltSdks(t *testing.T) {
|
||||
result := android.GroupFixturePreparers(
|
||||
prepareForTestWithPlatformBootclasspath,
|
||||
prepareForTestWithMyapex,
|
||||
// Configure two libraries, the first is a java_sdk_library whose prebuilt will be used because
|
||||
// of AlwaysUsePrebuiltsSdk() but does not have an appropriate apex variant and does not provide
|
||||
// a boot dex jar. The second is a normal library that is unaffected. The order matters because
|
||||
// if the dependency on myapex:foo is filtered out because of either of those conditions then
|
||||
// the dependencies resolved by the platform_bootclasspath will not match the configured list
|
||||
// and so will fail the test.
|
||||
java.FixtureConfigureUpdatableBootJars("myapex:foo", "myapex:bar"),
|
||||
java.PrepareForTestWithJavaSdkLibraryFiles,
|
||||
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
||||
variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
|
||||
}),
|
||||
java.FixtureWithPrebuiltApis(map[string][]string{
|
||||
"current": {},
|
||||
"30": {"foo"},
|
||||
}),
|
||||
).RunTestWithBp(t, `
|
||||
apex {
|
||||
name: "myapex",
|
||||
key: "myapex.key",
|
||||
bootclasspath_fragments: [
|
||||
"mybootclasspath-fragment",
|
||||
],
|
||||
updatable: false,
|
||||
}
|
||||
|
||||
apex_key {
|
||||
name: "myapex.key",
|
||||
public_key: "testkey.avbpubkey",
|
||||
private_key: "testkey.pem",
|
||||
}
|
||||
|
||||
java_library {
|
||||
name: "bar",
|
||||
srcs: ["b.java"],
|
||||
installable: true,
|
||||
apex_available: ["myapex"],
|
||||
permitted_packages: ["bar"],
|
||||
}
|
||||
|
||||
java_sdk_library {
|
||||
name: "foo",
|
||||
srcs: ["b.java"],
|
||||
shared_library: false,
|
||||
public: {
|
||||
enabled: true,
|
||||
},
|
||||
apex_available: ["myapex"],
|
||||
permitted_packages: ["foo"],
|
||||
}
|
||||
|
||||
// A prebuilt java_sdk_library_import that is not preferred by default but will be preferred
|
||||
// because AlwaysUsePrebuiltSdks() is true.
|
||||
java_sdk_library_import {
|
||||
name: "foo",
|
||||
prefer: false,
|
||||
shared_library: false,
|
||||
public: {
|
||||
jars: ["sdk_library/public/foo-stubs.jar"],
|
||||
stub_srcs: ["sdk_library/public/foo_stub_sources"],
|
||||
current_api: "sdk_library/public/foo.txt",
|
||||
removed_api: "sdk_library/public/foo-removed.txt",
|
||||
sdk_version: "current",
|
||||
},
|
||||
apex_available: ["myapex"],
|
||||
}
|
||||
|
||||
// This always depends on the source foo module, its dependencies are not affected by the
|
||||
// AlwaysUsePrebuiltSdks().
|
||||
bootclasspath_fragment {
|
||||
name: "mybootclasspath-fragment",
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
contents: [
|
||||
"foo", "bar",
|
||||
],
|
||||
}
|
||||
|
||||
platform_bootclasspath {
|
||||
name: "myplatform-bootclasspath",
|
||||
}
|
||||
`,
|
||||
)
|
||||
|
||||
java.CheckPlatformBootclasspathModules(t, result, "myplatform-bootclasspath", []string{
|
||||
// The configured contents of BootJars.
|
||||
"platform:prebuilt_foo", // Note: This is the platform not myapex variant.
|
||||
"myapex:bar",
|
||||
})
|
||||
|
||||
// Make sure that the myplatform-bootclasspath has the correct dependencies.
|
||||
CheckModuleDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
|
||||
// The following are stubs.
|
||||
"platform:prebuilt_sdk_public_current_android",
|
||||
"platform:prebuilt_sdk_system_current_android",
|
||||
"platform:prebuilt_sdk_test_current_android",
|
||||
|
||||
// Not a prebuilt as no prebuilt existed when it was added.
|
||||
"platform:legacy.core.platform.api.stubs",
|
||||
|
||||
// Needed for generating the boot image.
|
||||
`platform:dex2oatd`,
|
||||
|
||||
// The platform_bootclasspath intentionally adds dependencies on both source and prebuilt
|
||||
// modules when available as it does not know which one will be preferred.
|
||||
//
|
||||
// The source module has an APEX variant but the prebuilt does not.
|
||||
"myapex:foo",
|
||||
"platform:prebuilt_foo",
|
||||
|
||||
// Only a source module exists.
|
||||
"myapex:bar",
|
||||
})
|
||||
}
|
||||
|
||||
// CheckModuleDependencies checks the dependencies of the selected module against the expected list.
|
||||
//
|
||||
// The expected list must be a list of strings of the form "<apex>:<module>", where <apex> is the
|
||||
|
@@ -29,7 +29,7 @@ func init() {
|
||||
|
||||
func registerBootclasspathBuildComponents(ctx android.RegistrationContext) {
|
||||
ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
||||
ctx.BottomUp("bootclasspath_deps", bootclasspathDepsMutator)
|
||||
ctx.BottomUp("bootclasspath_deps", bootclasspathDepsMutator).Parallel()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -95,6 +95,15 @@ func addDependencyOntoApexModulePair(ctx android.BottomUpMutatorContext, apex st
|
||||
if ctx.OtherModuleDependencyVariantExists(variations, prebuiltName) {
|
||||
ctx.AddVariationDependencies(variations, tag, prebuiltName)
|
||||
addedDep = true
|
||||
} else if ctx.Config().AlwaysUsePrebuiltSdks() && len(variations) > 0 {
|
||||
// TODO(b/179354495): Remove this code path once the Android build has been fully migrated to
|
||||
// use bootclasspath_fragment properly.
|
||||
// Some prebuilt java_sdk_library modules do not yet have an APEX variations so try and add a
|
||||
// dependency on the non-APEX variant.
|
||||
if ctx.OtherModuleDependencyVariantExists(nil, prebuiltName) {
|
||||
ctx.AddVariationDependencies(nil, tag, prebuiltName)
|
||||
addedDep = true
|
||||
}
|
||||
}
|
||||
|
||||
// If no appropriate variant existing for this, so no dependency could be added, then it is an
|
||||
|
@@ -766,7 +766,7 @@ func generateUpdatableBcpPackagesRule(ctx android.ModuleContext, image *bootImag
|
||||
if len(pp) > 0 {
|
||||
updatablePackages = append(updatablePackages, pp...)
|
||||
} else {
|
||||
ctx.ModuleErrorf("Missing permitted_packages")
|
||||
ctx.OtherModuleErrorf(module, "Missing permitted_packages")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@
|
||||
package java
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"android/soong/android"
|
||||
@@ -560,7 +561,25 @@ func extractBootDexJarsFromHiddenAPIModules(ctx android.ModuleContext, contents
|
||||
for _, module := range contents {
|
||||
bootDexJar := module.bootDexJar()
|
||||
if bootDexJar == nil {
|
||||
ctx.ModuleErrorf("module %s does not provide a dex jar", module)
|
||||
if ctx.Config().AlwaysUsePrebuiltSdks() {
|
||||
// TODO(b/179354495): Remove this work around when it is unnecessary.
|
||||
// Prebuilt modules like framework-wifi do not yet provide dex implementation jars. So,
|
||||
// create a fake one that will cause a build error only if it is used.
|
||||
fake := android.PathForModuleOut(ctx, "fake/boot-dex/%s.jar", module.Name())
|
||||
|
||||
// Create an error rule that pretends to create the output file but will actually fail if it
|
||||
// is run.
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: android.ErrorRule,
|
||||
Output: fake,
|
||||
Args: map[string]string{
|
||||
"error": fmt.Sprintf("missing dependencies: boot dex jar for %s", module),
|
||||
},
|
||||
})
|
||||
bootDexJars = append(bootDexJars, fake)
|
||||
} else {
|
||||
ctx.ModuleErrorf("module %s does not provide a dex jar", module)
|
||||
}
|
||||
} else {
|
||||
bootDexJars = append(bootDexJars, bootDexJar)
|
||||
}
|
||||
|
@@ -242,8 +242,15 @@ func (b *platformBootclasspathModule) checkUpdatableModules(ctx android.ModuleCo
|
||||
} else {
|
||||
name := ctx.OtherModuleName(m)
|
||||
if apexInfo.IsForPlatform() {
|
||||
// error: this jar is part of the platform
|
||||
ctx.ModuleErrorf("module %q from platform is not allowed in the updatable boot jars list", name)
|
||||
// If AlwaysUsePrebuiltSdks() returns true then it is possible that the updatable list will
|
||||
// include platform variants of a prebuilt module due to workarounds elsewhere. In that case
|
||||
// do not treat this as an error.
|
||||
// TODO(b/179354495): Always treat this as an error when migration to bootclasspath_fragment
|
||||
// modules is complete.
|
||||
if !ctx.Config().AlwaysUsePrebuiltSdks() {
|
||||
// error: this jar is part of the platform
|
||||
ctx.ModuleErrorf("module %q from platform is not allowed in the updatable boot jars list", name)
|
||||
}
|
||||
} else {
|
||||
// TODO(b/177892522): Treat this as an error.
|
||||
// Cannot do that at the moment because framework-wifi and framework-tethering are in the
|
||||
|
Reference in New Issue
Block a user