summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Colin Cross <ccross@android.com> 2025-01-14 15:50:48 -0800
committer Colin Cross <ccross@android.com> 2025-02-07 16:00:56 -0800
commitd649580f3d46b39f8837d668063f9b8ebde0474a (patch)
tree819a6a4beb1eca9e6a705bb0f8ac28389b355b6e
parentbdd344b91a5990d797eef508821a877febd0d7a0 (diff)
Convert apex transition tag to dependency on apex
When the apex mutator moves to using an info struct instead of a simple string it becomes difficult to add a dependency directly on the apex variation of a module, as that would require constructing a matching ApexInfo to locate it. Simplify adding the dependency by adding it on the apex instead, and then traversing from the apex to the desired module inside the apex. This causes a few changes in behaviors that require updating tests to match. When AlwaysUsePrebuiltSdks is set, the previous behavior was to use the fragment and its dependencies from the source module for the platform bootclasspath. Since the fragment is now found by traversing from the apex, and the prebuilt apex is preferred, the fragment from the prebuilt will now be found instead. prebuilt_bootclasspath lists fragments in apexes that it depends on. Previously it would depend on the apex variant of the fragment, which then allowed the fragment to be replaced by the variant from an override apex that set apex_name. Now it always depends on the original apex to find the fragment. Test: go test ./... Bug: 372543712 Change-Id: I1a92ff461d4706cf68a0b8b37e53dea412efb8bf
-rw-r--r--android/prebuilt.go7
-rw-r--r--apex/apex.go10
-rw-r--r--apex/apex_test.go6
-rw-r--r--apex/bootclasspath_fragment_test.go8
-rw-r--r--apex/platform_bootclasspath_test.go32
-rw-r--r--java/bootclasspath.go73
-rw-r--r--java/bootclasspath_fragment.go2
-rw-r--r--java/dexpreopt_bootjars.go58
8 files changed, 142 insertions, 54 deletions
diff --git a/android/prebuilt.go b/android/prebuilt.go
index defec1186..6b076b7b4 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -612,6 +612,13 @@ func hideUnflaggedModules(ctx BottomUpMutatorContext, psi PrebuiltSelectionInfoM
}
}
+func IsDontReplaceSourceWithPrebuiltTag(tag blueprint.DependencyTag) bool {
+ if t, ok := tag.(ReplaceSourceWithPrebuilt); ok {
+ return !t.ReplaceSourceWithPrebuilt()
+ }
+ return false
+}
+
// PrebuiltPostDepsMutator replaces dependencies on the source module with dependencies on the
// prebuilt when both modules exist and the prebuilt should be used. When the prebuilt should not
// be used, disable installing it.
diff --git a/apex/apex.go b/apex/apex.go
index 1d74466b7..24b3118a4 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1211,13 +1211,6 @@ func markPlatformAvailability(mctx android.BottomUpMutatorContext) {
}
}
-type apexTransitionTag interface {
- // ApexTransition is a temporary interface used to tag dependencies with the apex variation they should use
- // when the dependency is added before the apex transition mutator has run. These will be replaced with
- // dependencies on the apex instead, which will then be used to find the necessary module inside the apex.
- ApexTransition() string
-}
-
type apexTransitionMutator struct{}
func (a *apexTransitionMutator) Split(ctx android.BaseModuleContext) []string {
@@ -1232,9 +1225,6 @@ func (a *apexTransitionMutator) Split(ctx android.BaseModuleContext) []string {
}
func (a *apexTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
- if tag, ok := ctx.DepTag().(apexTransitionTag); ok {
- return tag.ApexTransition()
- }
return sourceVariation
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 887767527..0d6d31999 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -5341,6 +5341,12 @@ func TestPrebuiltApexNameWithPlatformBootclasspath(t *testing.T) {
exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
}
+ prebuilt_apex {
+ name: "com.android.art",
+ src: "com.android.art-arm.apex",
+ exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
+ }
+
prebuilt_bootclasspath_fragment {
name: "art-bootclasspath-fragment",
image_name: "art",
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index 526e59696..e8e45adfc 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -863,8 +863,8 @@ func TestBootclasspathFragment_HiddenAPIList(t *testing.T) {
java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_myapex", []string{
"all_apex_contributions",
- "art-bootclasspath-fragment",
"bar",
+ "com.android.art",
"dex2oatd",
"foo",
})
@@ -1040,8 +1040,8 @@ func TestBootclasspathFragment_AndroidNonUpdatable_FromSource(t *testing.T) {
"android-non-updatable.stubs.module_lib",
"android-non-updatable.stubs.system",
"android-non-updatable.stubs.test",
- "art-bootclasspath-fragment",
"bar",
+ "com.android.art",
"dex2oatd",
"foo",
})
@@ -1214,8 +1214,8 @@ func TestBootclasspathFragment_AndroidNonUpdatable_FromText(t *testing.T) {
"android-non-updatable.stubs.system",
"android-non-updatable.stubs.test",
"android-non-updatable.stubs.test_module_lib",
- "art-bootclasspath-fragment",
"bar",
+ "com.android.art",
"dex2oatd",
"foo",
})
@@ -1365,8 +1365,8 @@ func TestBootclasspathFragment_AndroidNonUpdatable_AlwaysUsePrebuiltSdks(t *test
java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_myapex", []string{
"all_apex_contributions",
- "art-bootclasspath-fragment",
"bar",
+ "com.android.art",
"dex2oatd",
"foo",
"prebuilt_sdk_module-lib_current_android-non-updatable",
diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go
index 6ebd78fa2..cd8c320ed 100644
--- a/apex/platform_bootclasspath_test.go
+++ b/apex/platform_bootclasspath_test.go
@@ -401,17 +401,17 @@ func TestPlatformBootclasspathDependencies(t *testing.T) {
// Needed for generating the boot image.
`platform:dex2oatd`,
- // The configured contents of BootJars.
- `com.android.art:baz`,
- `com.android.art:quuz`,
+ // The configured contents of BootJars, via their apexes if necessary.
+ `platform:com.android.art`,
+ `platform:com.android.art`,
`platform:foo`,
- // The configured contents of ApexBootJars.
- `myapex:bar`,
+ // The configured contents of ApexBootJars, via their apex.
+ `platform:myapex`,
- // The fragments.
- `com.android.art:art-bootclasspath-fragment`,
- `myapex:my-bootclasspath-fragment`,
+ // The fragments via their apexes.
+ `platform:com.android.art`,
+ `platform:myapex`,
// Impl lib of sdk_library for transitive srcjar generation
`platform:foo.impl`,
@@ -429,7 +429,7 @@ func TestPlatformBootclasspath_AlwaysUsePrebuiltSdks(t *testing.T) {
// of AlwaysUsePrebuiltsSdk(). The second is a normal library that is unaffected. The order
// matters, so that the dependencies resolved by the platform_bootclasspath matches the
// configured list.
- java.FixtureConfigureApexBootJars("myapex:foo", "myapex:bar"),
+ java.FixtureConfigureApexBootJars("myapex:foo"),
java.PrepareForTestWithJavaSdkLibraryFiles,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
@@ -545,7 +545,6 @@ func TestPlatformBootclasspath_AlwaysUsePrebuiltSdks(t *testing.T) {
java.CheckPlatformBootclasspathModules(t, result, "myplatform-bootclasspath", []string{
// The configured contents of BootJars.
"myapex:prebuilt_foo",
- "myapex:bar",
})
// Make sure that the myplatform-bootclasspath has the correct dependencies.
@@ -561,14 +560,11 @@ func TestPlatformBootclasspath_AlwaysUsePrebuiltSdks(t *testing.T) {
// Not a prebuilt as no prebuilt existed when it was added.
"platform:legacy.core.platform.api.stubs.exportable",
- // The prebuilt.
- "myapex:prebuilt_foo",
-
- // Only a source module exists.
- "myapex:bar",
+ // The prebuilt library via the apex.
+ "platform:myapex",
- // The fragments.
- "myapex:prebuilt_mybootclasspath-fragment",
+ // The fragments via the apex.
+ "platform:myapex",
// Impl lib of sdk_library for transitive srcjar generation
"platform:foo.impl",
@@ -662,7 +658,7 @@ func TestBootJarNotInApex(t *testing.T) {
prepareForTestWithMyapex,
java.FixtureConfigureApexBootJars("myapex:foo"),
).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
- `module "myplatform-bootclasspath" variant ".*": module "foo" from platform is not allowed in the apex boot jars list`)).
+ `module "myplatform-bootclasspath" variant ".*": failed to find module "foo" in apex "myapex"`)).
RunTestWithBp(t, `
apex {
name: "myapex",
diff --git a/java/bootclasspath.go b/java/bootclasspath.go
index 856f43919..5500926e8 100644
--- a/java/bootclasspath.go
+++ b/java/bootclasspath.go
@@ -15,6 +15,8 @@
package java
import (
+ "fmt"
+
"android/soong/android"
"github.com/google/blueprint"
@@ -52,25 +54,76 @@ func addDependencyOntoApexModulePair(ctx android.BottomUpMutatorContext, apex st
tag := bootclasspathDependencyTag{
typ: tagType,
}
- if !android.IsConfiguredJarForPlatform(apex) {
- tag.apex = apex
- }
-
target := ctx.Module().Target()
+ if android.IsConfiguredJarForPlatform(apex) {
+ // Platform variant, add a direct dependency.
+ ctx.AddFarVariationDependencies(target.Variations(), tag, name)
+ } else {
+ // A module in an apex. Dependencies can't be added directly onto an apex variation, as that would
+ // require constructing a full ApexInfo configuration, which can't be predicted here. Add a dependency
+ // on the apex instead, and annotate the dependency tag with the desired module in the apex.
+ tag.moduleInApex = name
+ ctx.AddFarVariationDependencies(target.Variations(), tag, apex)
+ }
- ctx.AddFarVariationDependencies(target.Variations(), tag, name)
}
// gatherApexModulePairDepsWithTag returns the list of dependencies with the supplied tag that was
// added by addDependencyOntoApexModulePair.
func gatherApexModulePairDepsWithTag(ctx android.BaseModuleContext, tagType bootclasspathDependencyTagType) []android.Module {
var modules []android.Module
+
+ type moduleInApex struct {
+ module string
+ apex string
+ }
+
+ var modulesInApexes []moduleInApex
+
ctx.VisitDirectDeps(func(module android.Module) {
t := ctx.OtherModuleDependencyTag(module)
if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == tagType {
- modules = append(modules, module)
+ if bcpTag.moduleInApex != "" {
+ modulesInApexes = append(modulesInApexes, moduleInApex{bcpTag.moduleInApex, ctx.OtherModuleName(module)})
+ } else {
+ modules = append(modules, module)
+ }
}
})
+
+ for _, moduleInApex := range modulesInApexes {
+ var found android.Module
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ t := ctx.OtherModuleDependencyTag(child)
+ if parent == ctx.Module() {
+ if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == tagType && ctx.OtherModuleName(child) == moduleInApex.apex {
+ // recurse into the apex
+ return true
+ }
+ } else if tagType != fragment && android.IsFragmentInApexTag(t) {
+ return true
+ } else if android.IsDontReplaceSourceWithPrebuiltTag(t) {
+ return false
+ } else if t == android.PrebuiltDepTag {
+ return false
+ } else if IsBootclasspathFragmentContentDepTag(t) {
+ return false
+ } else if android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child)) == moduleInApex.module {
+ if found != nil && child != found {
+ panic(fmt.Errorf("found two conflicting modules %q in apex %q: %s and %s",
+ moduleInApex.module, moduleInApex.apex, found, child))
+ }
+ found = child
+ }
+ return false
+ })
+ if found != nil {
+ modules = append(modules, found)
+ } else if !ctx.Config().AllowMissingDependencies() {
+ ctx.ModuleErrorf("failed to find module %q in apex %q\n",
+ moduleInApex.module, moduleInApex.apex)
+ }
+ }
return modules
}
@@ -111,7 +164,9 @@ type bootclasspathDependencyTag struct {
typ bootclasspathDependencyTagType
- apex string
+ // moduleInApex is set to the name of the desired module when this dependency points
+ // to the apex that the modules is contained in.
+ moduleInApex string
}
type bootclasspathDependencyTagType int
@@ -130,8 +185,8 @@ const (
func (t bootclasspathDependencyTag) ExcludeFromVisibilityEnforcement() {
}
-func (t bootclasspathDependencyTag) ApexTransition() string {
- return t.apex
+func (t bootclasspathDependencyTag) LicenseAnnotations() []android.LicenseAnnotation {
+ return []android.LicenseAnnotation{android.LicenseAnnotationSharedDependency}
}
// Dependencies that use the bootclasspathDependencyTag instances are only added after all the
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 4d35b9fa5..f3bff12f2 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -621,7 +621,7 @@ func (b *BootclasspathFragmentModule) configuredJars(ctx android.ModuleContext)
if android.IsModulePrebuilt(ctx.Module()) {
// prebuilt bcpf. the validation of this will be done at the top-level apex
providerClasspathFragmentValidationInfoProvider(ctx, unknown)
- } else if !disableSourceApexVariant(ctx) {
+ } else if !disableSourceApexVariant(ctx) && android.IsModulePreferred(ctx.Module()) {
// source bcpf, and prebuilt apex are not selected.
ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_BOOT_JARS", unknown)
}
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 83b1f4df6..24bb99d7f 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -15,6 +15,7 @@
package java
import (
+ "fmt"
"path/filepath"
"strings"
@@ -552,12 +553,8 @@ func addDependenciesOntoSelectedBootImageApexes(ctx android.BottomUpMutatorConte
tag := bootclasspathDependencyTag{
typ: dexpreoptBootJar,
}
- if !android.IsConfiguredJarForPlatform(apex) {
- tag.apex = apex
- }
- if ctx.OtherModuleDependencyVariantExists(ctx.Target().Variations(), android.RemoveOptionalPrebuiltPrefix(selected)) {
- ctx.AddFarVariationDependencies(ctx.Target().Variations(), tag, android.RemoveOptionalPrebuiltPrefix(selected))
- }
+
+ ctx.AddFarVariationDependencies(ctx.Target().Variations(), tag, android.RemoveOptionalPrebuiltPrefix(selected))
}
}
}
@@ -565,6 +562,15 @@ func addDependenciesOntoSelectedBootImageApexes(ctx android.BottomUpMutatorConte
func gatherBootclasspathFragments(ctx android.ModuleContext) map[string]android.Module {
return ctx.Config().Once(dexBootJarsFragmentsKey, func() interface{} {
fragments := make(map[string]android.Module)
+
+ type moduleInApexPair struct {
+ module string
+ apex string
+ }
+
+ var modulesInApexes []moduleInApexPair
+
+ // Find the list of modules in apexes.
ctx.WalkDeps(func(child, parent android.Module) bool {
if !isActiveModule(ctx, child) {
return false
@@ -575,15 +581,36 @@ func gatherBootclasspathFragments(ctx android.ModuleContext) map[string]android.
return true
}
if bcpTag.typ == fragment {
- apexInfo, _ := android.OtherModuleProvider(ctx, child, android.ApexInfoProvider)
- for _, apex := range apexInfo.InApexVariants {
- fragments[apex] = child
+ if bcpTag.moduleInApex == "" {
+ panic(fmt.Errorf("expected fragment to be in apex"))
}
- return false
+ modulesInApexes = append(modulesInApexes, moduleInApexPair{bcpTag.moduleInApex, ctx.OtherModuleName(child)})
+ return true
}
}
return false
})
+
+ for _, moduleInApex := range modulesInApexes {
+ // Find a desired module in an apex.
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ t := ctx.OtherModuleDependencyTag(child)
+ if bcpTag, ok := t.(bootclasspathDependencyTag); ok {
+ if bcpTag.typ == platform {
+ return true
+ }
+ if bcpTag.typ == fragment && ctx.OtherModuleName(child) == moduleInApex.apex {
+ // This is the dependency from this module to the apex, recurse into it.
+ return true
+ }
+ } else if android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child)) == moduleInApex.module {
+ // This is the desired module inside the apex.
+ fragments[android.RemoveOptionalPrebuiltPrefix(moduleInApex.apex)] = child
+ }
+ return false
+ })
+ }
+
return fragments
}).(map[string]android.Module)
}
@@ -957,11 +984,15 @@ func getProfilePathForApex(ctx android.ModuleContext, apexName string, apexNameT
func getApexNameToApexExportsInfoMap(ctx android.ModuleContext) apexNameToApexExportsInfoMap {
apexNameToApexExportsInfoMap := apexNameToApexExportsInfoMap{}
+
ctx.VisitDirectDeps(func(am android.Module) {
tag := ctx.OtherModuleDependencyTag(am)
if bcpTag, ok := tag.(bootclasspathDependencyTag); ok && bcpTag.typ == dexpreoptBootJar {
- if info, exists := android.OtherModuleProvider(ctx, am, android.ApexExportsInfoProvider); exists {
- apexNameToApexExportsInfoMap[info.ApexName] = info
+ if bcpTag.moduleInApex == "" {
+ info, exists := android.OtherModuleProvider(ctx, am, android.ApexExportsInfoProvider)
+ if exists {
+ apexNameToApexExportsInfoMap[info.ApexName] = info
+ }
}
}
})
@@ -1455,6 +1486,9 @@ func (d *artBootImages) GenerateAndroidBuildActions(ctx android.ModuleContext) {
ctx.VisitDirectDeps(func(m android.Module) {
tag := ctx.OtherModuleDependencyTag(m)
if bcpTag, ok := tag.(bootclasspathDependencyTag); ok && bcpTag.typ == dexpreoptBootJar {
+ if bcpTag.moduleInApex != "" {
+ panic("unhandled moduleInApex")
+ }
hostInstallsInfo, ok := android.OtherModuleProvider(ctx, m, artBootImageHostInfoProvider)
if !ok {
ctx.ModuleErrorf("Could not find information about the host variant of ART boot image")