Merge "Separate apex selection from apex.Prebuilt"
diff --git a/apex/boot_image_test.go b/apex/boot_image_test.go
index 574166a..aa0d9c4 100644
--- a/apex/boot_image_test.go
+++ b/apex/boot_image_test.go
@@ -305,6 +305,7 @@
`)
java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common", []string{
+ `com.android.art.apex.selector`,
`prebuilt_bar`,
`prebuilt_foo`,
})
diff --git a/apex/deapexer.go b/apex/deapexer.go
index e7aa551..1db13f9 100644
--- a/apex/deapexer.go
+++ b/apex/deapexer.go
@@ -49,21 +49,27 @@
Exported_java_libs []string
}
+type SelectedApexProperties struct {
+ // The path to the apex selected for use by this module.
+ //
+ // Is tagged as `android:"path"` because it will usually contain a string of the form ":<module>"
+ // and is tagged as "`blueprint:"mutate"` because it is only initialized in a LoadHook not an
+ // Android.bp file.
+ Selected_apex *string `android:"path" blueprint:"mutated"`
+}
+
type Deapexer struct {
android.ModuleBase
- properties DeapexerProperties
- apexFileProperties ApexFileProperties
+ properties DeapexerProperties
+ selectedApexProperties SelectedApexProperties
inputApex android.Path
}
func privateDeapexerFactory() android.Module {
module := &Deapexer{}
- module.AddProperties(
- &module.properties,
- &module.apexFileProperties,
- )
+ module.AddProperties(&module.properties, &module.selectedApexProperties)
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
return module
}
@@ -78,7 +84,7 @@
}
func (p *Deapexer) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- p.inputApex = android.SingleSourcePathFromSupplier(ctx, p.apexFileProperties.prebuiltApexSelector, "src")
+ p.inputApex = android.OptionalPathForModuleSrc(ctx, p.selectedApexProperties.Selected_apex).Path()
// Create and remember the directory into which the .apex file's contents will be unpacked.
deapexerOutput := android.PathForModuleOut(ctx, "deapexer")
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 8c7e64c..9d84281 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -91,11 +91,40 @@
return false
}
+// prebuiltApexSelectorModule is a private module type that is only created by the prebuilt_apex
+// module. It selects the apex to use and makes it available for use by prebuilt_apex and the
+// deapexer.
+type prebuiltApexSelectorModule struct {
+ android.ModuleBase
+
+ apexFileProperties ApexFileProperties
+
+ inputApex android.Path
+}
+
+func privateApexSelectorModuleFactory() android.Module {
+ module := &prebuiltApexSelectorModule{}
+ module.AddProperties(
+ &module.apexFileProperties,
+ )
+ android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ return module
+}
+
+func (p *prebuiltApexSelectorModule) Srcs() android.Paths {
+ return android.Paths{p.inputApex}
+}
+
+func (p *prebuiltApexSelectorModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ p.inputApex = android.SingleSourcePathFromSupplier(ctx, p.apexFileProperties.prebuiltApexSelector, "src")
+}
+
type Prebuilt struct {
android.ModuleBase
prebuiltCommon
- properties PrebuiltProperties
+ properties PrebuiltProperties
+ selectedApexProperties SelectedApexProperties
inputApex android.Path
installDir android.InstallPath
@@ -113,19 +142,19 @@
// This cannot be marked as `android:"arch_variant"` because the `prebuilt_apex` is only mutated
// for android_common. That is so that it will have the same arch variant as, and so be compatible
// with, the source `apex` module type that it replaces.
- Src *string
+ Src *string `android:"path"`
Arch struct {
Arm struct {
- Src *string
+ Src *string `android:"path"`
}
Arm64 struct {
- Src *string
+ Src *string `android:"path"`
}
X86 struct {
- Src *string
+ Src *string `android:"path"`
}
X86_64 struct {
- Src *string
+ Src *string `android:"path"`
}
}
}
@@ -224,28 +253,77 @@
// 3. The `deapexer` module adds a dependency from the modules that require the exported files onto
// itself so that they can retrieve the file paths to those files.
//
+// It also creates a child module `selector` that is responsible for selecting the appropriate
+// input apex for both the prebuilt_apex and the deapexer. That is needed for a couple of reasons:
+// 1. To dedup the selection logic so it only runs in one module.
+// 2. To allow the deapexer to be wired up to a different source for the input apex, e.g. an
+// `apex_set`.
+//
+// prebuilt_apex
+// / | \
+// / | \
+// V | V
+// selector <--- deapexer <--- exported java lib
+//
func PrebuiltFactory() android.Module {
module := &Prebuilt{}
- module.AddProperties(&module.properties)
- android.InitPrebuiltModuleWithSrcSupplier(module, module.properties.prebuiltApexSelector, "src")
+ module.AddProperties(&module.properties, &module.selectedApexProperties)
+ android.InitSingleSourcePrebuiltModule(module, &module.selectedApexProperties, "Selected_apex")
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.AddLoadHook(module, func(ctx android.LoadHookContext) {
- props := struct {
- Name *string
- }{
- Name: proptools.StringPtr(module.BaseModuleName() + ".deapexer"),
+ baseModuleName := module.BaseModuleName()
+
+ apexSelectorModuleName := apexSelectorModuleName(baseModuleName)
+ createApexSelectorModule(ctx, apexSelectorModuleName, &module.properties.ApexFileProperties)
+
+ apexFileSource := ":" + apexSelectorModuleName
+ if len(module.properties.Exported_java_libs) != 0 {
+ createDeapexerModule(ctx, deapexerModuleName(baseModuleName), apexFileSource, &module.properties.DeapexerProperties)
}
- ctx.CreateModule(privateDeapexerFactory,
- &props,
- &module.properties.ApexFileProperties,
- &module.properties.DeapexerProperties,
- )
+
+ // Add a source reference to retrieve the selected apex from the selector module.
+ module.selectedApexProperties.Selected_apex = proptools.StringPtr(apexFileSource)
})
return module
}
+func createApexSelectorModule(ctx android.LoadHookContext, name string, apexFileProperties *ApexFileProperties) {
+ props := struct {
+ Name *string
+ }{
+ Name: proptools.StringPtr(name),
+ }
+
+ ctx.CreateModule(privateApexSelectorModuleFactory,
+ &props,
+ apexFileProperties,
+ )
+}
+
+func createDeapexerModule(ctx android.LoadHookContext, deapexerName string, apexFileSource string, deapexerProperties *DeapexerProperties) {
+ props := struct {
+ Name *string
+ Selected_apex *string
+ }{
+ Name: proptools.StringPtr(deapexerName),
+ Selected_apex: proptools.StringPtr(apexFileSource),
+ }
+ ctx.CreateModule(privateDeapexerFactory,
+ &props,
+ deapexerProperties,
+ )
+}
+
+func deapexerModuleName(baseModuleName string) string {
+ return baseModuleName + ".deapexer"
+}
+
+func apexSelectorModuleName(baseModuleName string) string {
+ return baseModuleName + ".apex.selector"
+}
+
func prebuiltApexExportedModuleName(ctx android.BottomUpMutatorContext, name string) string {
// The prebuilt_apex should be depending on prebuilt modules but as this runs after
// prebuilt_rename the prebuilt module may or may not be using the prebuilt_ prefixed named. So,
@@ -378,7 +456,7 @@
func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// TODO(jungjw): Check the key validity.
- p.inputApex = p.Prebuilt().SingleSourcePath(ctx)
+ p.inputApex = android.OptionalPathForModuleSrc(ctx, p.selectedApexProperties.Selected_apex).Path()
p.installDir = android.PathForModuleInstall(ctx, "apex")
p.installFilename = p.InstallFilename()
if !strings.HasSuffix(p.installFilename, imageApexSuffix) {