From 11216db1d39041742af6f5e82b3b6442bab3a935 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Mon, 1 Mar 2021 14:14:52 +0000 Subject: [PATCH] Separate apex selection from apex.Prebuilt This dedups the apex selection (which was previously being done by both the apex.Prebuilt module type and the Deapexer module type) by separating it out into its own module. The apex.Prebuilt module retrieves the selected apex from its selected_apex property which is simply initialized with ":". The Deapexer module retrieves the selected apex it should use from its src property which is initialized in the same way. That makes it easy for the Deapexer module to be reused by the apex_set in a similar way. Bug: 181267622 Test: m droid Change-Id: I90cfb55698d35a97dcf28b95afcb1f58584bc90c --- apex/boot_image_test.go | 1 + apex/deapexer.go | 20 ++++--- apex/prebuilt.go | 114 +++++++++++++++++++++++++++++++++------- 3 files changed, 110 insertions(+), 25 deletions(-) diff --git a/apex/boot_image_test.go b/apex/boot_image_test.go index 574166a53..aa0d9c4b9 100644 --- a/apex/boot_image_test.go +++ b/apex/boot_image_test.go @@ -305,6 +305,7 @@ func TestBootImageInPrebuiltArtApex(t *testing.T) { `) 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 e7aa5514a..1db13f916 100644 --- a/apex/deapexer.go +++ b/apex/deapexer.go @@ -49,21 +49,27 @@ type DeapexerProperties struct { 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 ":" + // 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) DepsMutator(ctx android.BottomUpMutatorContext) { } 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 8c7e64c6a..9d84281cb 100644 --- a/apex/prebuilt.go +++ b/apex/prebuilt.go @@ -91,11 +91,40 @@ func (p *prebuiltCommon) checkForceDisable(ctx android.ModuleContext) bool { 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 @@ type ApexFileProperties struct { // 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 @@ func (p *Prebuilt) Name() string { // 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) ApexInfoMutator(mctx android.TopDownMutatorContext) { 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) {