Add exported_bootclasspath_fragments to prebuilt_apex/apex_set

This is needed to allow a prebuilt_bootclasspath_fragment to be used
interchangeably with a bootclasspath_fragment in the
platform_bootclasspath module.

The platform_bootclasspath module depends on APEX specific variants of
bootclasspath_fragment modules. That works because the
bootclasspath_fragment modules are part of an apex and so have an APEX
specific variant which the platform_bootclasspath can specify.

Using a prebuilt_bootclasspath_fragment in place of a
bootclasspath_fragment requires that the prebuilt also has an APEX
specific variant.

Specifying exported_bootclasspath_fragments on a prebuilt_apex/apex_set
will cause it to create an APEX variant for the named module whcih will
allow it to be selected by the platform_bootclasspath module.

Bug: 186034565
Bug: 177892522
Test: m nothing
Change-Id: I7ddacc6498ec3a4a9f26c5f78b7f9a033e494d78
This commit is contained in:
Paul Duffin 2021-04-22 01:45:29 +01:00
parent a3693772a6
commit 023dba0a3f
5 changed files with 71 additions and 21 deletions

View file

@ -44,9 +44,13 @@ import (
// module.`
type DeapexerProperties struct {
// List of java libraries that are embedded inside this prebuilt APEX bundle and for which this
// APEX bundle will provide dex implementation jars for use by dexpreopt and boot jars package
// check.
// APEX bundle will create an APEX variant and provide dex implementation jars for use by
// dexpreopt and boot jars package check.
Exported_java_libs []string
// List of bootclasspath fragments inside this prebuiltd APEX bundle and for which this APEX
// bundle will create an APEX variant.
Exported_bootclasspath_fragments []string
}
type SelectedApexProperties struct {

View file

@ -97,10 +97,17 @@ func (p *prebuiltCommon) checkForceDisable(ctx android.ModuleContext) bool {
func (p *prebuiltCommon) deapexerDeps(ctx android.BottomUpMutatorContext) {
// Add dependencies onto the java modules that represent the java libraries that are provided by
// and exported from this prebuilt apex.
for _, lib := range p.deapexerProperties.Exported_java_libs {
dep := prebuiltApexExportedModuleName(ctx, lib)
for _, exported := range p.deapexerProperties.Exported_java_libs {
dep := prebuiltApexExportedModuleName(ctx, exported)
ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), exportedJavaLibTag, dep)
}
// Add dependencies onto the bootclasspath fragment modules that are exported from this prebuilt
// apex.
for _, exported := range p.deapexerProperties.Exported_bootclasspath_fragments {
dep := prebuiltApexExportedModuleName(ctx, exported)
ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), exportedBootclasspathFragmentTag, dep)
}
}
// apexInfoMutator marks any modules for which this apex exports a file as requiring an apex
@ -137,18 +144,19 @@ func (p *prebuiltCommon) apexInfoMutator(mctx android.TopDownMutatorContext) {
var dependencies []android.ApexModule
mctx.VisitDirectDeps(func(m android.Module) {
tag := mctx.OtherModuleDependencyTag(m)
if tag == exportedJavaLibTag {
if exportedTag, ok := tag.(exportedDependencyTag); ok {
propertyName := exportedTag.name
depName := mctx.OtherModuleName(m)
// It is an error if the other module is not a prebuilt.
if _, ok := m.(android.PrebuiltInterface); !ok {
mctx.PropertyErrorf("exported_java_libs", "%q is not a prebuilt module", depName)
mctx.PropertyErrorf(propertyName, "%q is not a prebuilt module", depName)
return
}
// It is an error if the other module is not an ApexModule.
if _, ok := m.(android.ApexModule); !ok {
mctx.PropertyErrorf("exported_java_libs", "%q is not usable within an apex", depName)
mctx.PropertyErrorf(propertyName, "%q is not usable within an apex", depName)
return
}
@ -451,7 +459,8 @@ type exportedDependencyTag struct {
func (t exportedDependencyTag) ExcludeFromVisibilityEnforcement() {}
var (
exportedJavaLibTag = exportedDependencyTag{name: "exported_java_lib"}
exportedJavaLibTag = exportedDependencyTag{name: "exported_java_libs"}
exportedBootclasspathFragmentTag = exportedDependencyTag{name: "exported_bootclasspath_fragments"}
)
func (p *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) {

View file

@ -124,8 +124,22 @@ func bootImageConsistencyCheck(ctx android.EarlyModuleContext, m *BootImageModul
if m.properties.Image_name != nil && len(contents) != 0 {
ctx.ModuleErrorf(`both of the "image_name" and "contents" properties have been supplied, please supply exactly one`)
}
imageName := proptools.String(m.properties.Image_name)
if imageName == "art" {
// TODO(b/177892522): Prebuilts (versioned or not) should not use the image_name property.
if m.MemberName() != "" {
// The module is a versioned prebuilt so ignore it. This is done for a couple of reasons:
// 1. There is no way to use this at the moment so ignoring it is safe.
// 2. Attempting to initialize the contents property from the configuration will end up having
// the versioned prebuilt depending on the unversioned prebuilt. That will cause problems
// as the unversioned prebuilt could end up with an APEX variant created for the source
// APEX which will prevent it from having an APEX variant for the prebuilt APEX which in
// turn will prevent it from accessing the dex implementation jar from that which will
// break hidden API processing, amongst others.
return
}
// Get the configuration for the art apex jars. Do not use getImageConfig(ctx) here as this is
// too early in the Soong processing for that to work.
global := dexpreopt.GetGlobalConfig(ctx)

View file

@ -24,6 +24,7 @@ import (
func TestSnapshotWithBootclasspathFragment_ImageName(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
java.PrepareForTestWithJavaDefaultModules,
prepareForSdkTestWithApex,
// Some additional files needed for the art apex.
@ -32,6 +33,20 @@ func TestSnapshotWithBootclasspathFragment_ImageName(t *testing.T) {
"com.android.art.pem": nil,
"system/sepolicy/apex/com.android.art-file_contexts": nil,
}),
// platform_bootclasspath that depends on the fragment.
android.FixtureAddTextFile("frameworks/base/boot/Android.bp", `
platform_bootclasspath {
name: "platform-bootclasspath",
fragments: [
{
apex: "com.android.art",
module: "mybootclasspathfragment",
},
],
}
`),
java.FixtureConfigureBootJars("com.android.art:mybootlib"),
android.FixtureWithRootAndroidBp(`
sdk {
@ -72,6 +87,23 @@ func TestSnapshotWithBootclasspathFragment_ImageName(t *testing.T) {
`),
).RunTest(t)
// A preparer to add a prebuilt apex to the test fixture.
prepareWithPrebuiltApex := android.GroupFixturePreparers(
android.FixtureAddTextFile("prebuilts/apex/Android.bp", `
prebuilt_apex {
name: "com.android.art",
src: "art.apex",
exported_java_libs: [
"mybootlib",
],
exported_bootclasspath_fragments: [
"mybootclasspathfragment",
],
}
`),
android.FixtureAddFile("prebuilts/apex/art.apex", nil),
)
CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@ -121,19 +153,9 @@ sdk_snapshot {
checkAllCopyRules(`
.intermediates/mybootlib/android_common/javac/mybootlib.jar -> java/mybootlib.jar
`),
snapshotTestPreparer(checkSnapshotPreferredWithSource, android.GroupFixturePreparers(
android.FixtureAddTextFile("prebuilts/apex/Android.bp", `
prebuilt_apex {
name: "com.android.art",
src: "art.apex",
exported_java_libs: [
"mybootlib",
],
}
`),
android.FixtureAddFile("prebuilts/apex/art.apex", nil),
),
),
snapshotTestPreparer(checkSnapshotWithoutSource, prepareWithPrebuiltApex),
snapshotTestPreparer(checkSnapshotWithSourcePreferred, prepareWithPrebuiltApex),
snapshotTestPreparer(checkSnapshotPreferredWithSource, prepareWithPrebuiltApex),
)
}

View file

@ -254,6 +254,7 @@ func CheckSnapshot(t *testing.T, result *android.TestResult, name string, dir st
snapshotPreparer := android.GroupFixturePreparers(sourcePreparers, fs.AddToFixture())
var runSnapshotTestWithCheckers = func(t *testing.T, testConfig snapshotTest, extraPreparer android.FixturePreparer) {
t.Helper()
customization := snapshotBuildInfo.snapshotTestCustomization(testConfig)
customizedPreparers := android.GroupFixturePreparers(customization.preparers...)