diff --git a/android/aconfig_providers.go b/android/aconfig_providers.go index 6bfbf3776..cb88e011c 100644 --- a/android/aconfig_providers.go +++ b/android/aconfig_providers.go @@ -187,6 +187,20 @@ func aconfigUpdateAndroidMkEntries(ctx fillInEntriesContext, mod Module, entries } } +func aconfigUpdateAndroidMkInfos(ctx fillInEntriesContext, mod Module, infos *AndroidMkProviderInfo) { + info, ok := OtherModuleProvider(ctx, mod, AconfigPropagatingProviderKey) + if !ok || len(info.AconfigFiles) == 0 { + return + } + // All of the files in the module potentially depend on the aconfig flag values. + infos.PrimaryInfo.AddPaths("LOCAL_ACONFIG_FILES", getAconfigFilePaths(mod.base(), info.AconfigFiles)) + if len(infos.ExtraInfo) > 0 { + for _, ei := range (*infos).ExtraInfo { + ei.AddPaths("LOCAL_ACONFIG_FILES", getAconfigFilePaths(mod.base(), info.AconfigFiles)) + } + } +} + func mergeAconfigFiles(ctx ModuleContext, container string, inputs Paths, generateRule bool) Paths { inputs = SortedUniquePaths(inputs) if len(inputs) == 1 { diff --git a/android/androidmk.go b/android/androidmk.go index fc628cb34..2185e4579 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -806,15 +806,21 @@ func translateAndroidMkModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs // Additional cases here require review for correct license propagation to make. var err error - switch x := mod.(type) { - case AndroidMkDataProvider: - err = translateAndroidModule(ctx, w, moduleInfoJSONs, mod, x) - case bootstrap.GoBinaryTool: - err = translateGoBinaryModule(ctx, w, mod, x) - case AndroidMkEntriesProvider: - err = translateAndroidMkEntriesModule(ctx, w, moduleInfoJSONs, mod, x) - default: - // Not exported to make so no make variables to set. + + if info, ok := ctx.otherModuleProvider(mod, AndroidMkInfoProvider); ok { + androidMkEntriesInfos := info.(*AndroidMkProviderInfo) + err = translateAndroidMkEntriesInfoModule(ctx, w, moduleInfoJSONs, mod, androidMkEntriesInfos) + } else { + switch x := mod.(type) { + case AndroidMkDataProvider: + err = translateAndroidModule(ctx, w, moduleInfoJSONs, mod, x) + case bootstrap.GoBinaryTool: + err = translateGoBinaryModule(ctx, w, mod, x) + case AndroidMkEntriesProvider: + err = translateAndroidMkEntriesModule(ctx, w, moduleInfoJSONs, mod, x) + default: + // Not exported to make so no make variables to set. + } } if err != nil { @@ -1063,3 +1069,564 @@ func AndroidMkEmitAssignList(w io.Writer, varName string, lists ...[]string) { } fmt.Fprintln(w) } + +type AndroidMkProviderInfo struct { + PrimaryInfo AndroidMkInfo + ExtraInfo []AndroidMkInfo +} + +type AndroidMkInfo struct { + // Android.mk class string, e.g. EXECUTABLES, JAVA_LIBRARIES, ETC + Class string + // Optional suffix to append to the module name. Useful when a module wants to return multiple + // AndroidMkEntries objects. For example, when a java_library returns an additional entry for + // its hostdex sub-module, this SubName field is set to "-hostdex" so that it can have a + // different name than the parent's. + SubName string + // If set, this value overrides the base module name. SubName is still appended. + OverrideName string + // Dist files to output + DistFiles TaggedDistFiles + // The output file for Kati to process and/or install. If absent, the module is skipped. + OutputFile OptionalPath + // If true, the module is skipped and does not appear on the final Android-.mk + // file. Useful when a module needs to be skipped conditionally. + Disabled bool + // The postprocessing mk file to include, e.g. $(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk + // If not set, $(BUILD_SYSTEM)/prebuilt.mk is used. + Include string + // Required modules that need to be built and included in the final build output when building + // this module. + Required []string + // Required host modules that need to be built and included in the final build output when + // building this module. + Host_required []string + // Required device modules that need to be built and included in the final build output when + // building this module. + Target_required []string + + HeaderStrings []string + FooterStrings []string + + // A map that holds the up-to-date Make variable values. Can be accessed from tests. + EntryMap map[string][]string + // A list of EntryMap keys in insertion order. This serves a few purposes: + // 1. Prevents churns. Golang map doesn't provide consistent iteration order, so without this, + // the outputted Android-*.mk file may change even though there have been no content changes. + // 2. Allows modules to refer to other variables, like LOCAL_BAR_VAR := $(LOCAL_FOO_VAR), + // without worrying about the variables being mixed up in the actual mk file. + // 3. Makes troubleshooting and spotting errors easier. + EntryOrder []string +} + +// TODO: rename it to AndroidMkEntriesProvider after AndroidMkEntriesProvider interface is gone. +var AndroidMkInfoProvider = blueprint.NewProvider[*AndroidMkProviderInfo]() + +func translateAndroidMkEntriesInfoModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON, + mod blueprint.Module, providerInfo *AndroidMkProviderInfo) error { + if shouldSkipAndroidMkProcessing(ctx, mod.(Module).base()) { + return nil + } + + // Deep copy the provider info since we need to modify the info later + info := deepCopyAndroidMkProviderInfo(providerInfo) + + aconfigUpdateAndroidMkInfos(ctx, mod.(Module), &info) + + // Any new or special cases here need review to verify correct propagation of license information. + info.PrimaryInfo.fillInEntries(ctx, mod) + info.PrimaryInfo.write(w) + if len(info.ExtraInfo) > 0 { + for _, ei := range info.ExtraInfo { + ei.fillInEntries(ctx, mod) + ei.write(w) + } + } + + if !info.PrimaryInfo.disabled() { + if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok { + *moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON) + } + } + + return nil +} + +// Utility funcs to manipulate Android.mk variable entries. + +// SetString sets a Make variable with the given name to the given value. +func (a *AndroidMkInfo) SetString(name, value string) { + if _, ok := a.EntryMap[name]; !ok { + a.EntryOrder = append(a.EntryOrder, name) + } + a.EntryMap[name] = []string{value} +} + +// SetPath sets a Make variable with the given name to the given path string. +func (a *AndroidMkInfo) SetPath(name string, path Path) { + if _, ok := a.EntryMap[name]; !ok { + a.EntryOrder = append(a.EntryOrder, name) + } + a.EntryMap[name] = []string{path.String()} +} + +// SetOptionalPath sets a Make variable with the given name to the given path string if it is valid. +// It is a no-op if the given path is invalid. +func (a *AndroidMkInfo) SetOptionalPath(name string, path OptionalPath) { + if path.Valid() { + a.SetPath(name, path.Path()) + } +} + +// AddPath appends the given path string to a Make variable with the given name. +func (a *AndroidMkInfo) AddPath(name string, path Path) { + if _, ok := a.EntryMap[name]; !ok { + a.EntryOrder = append(a.EntryOrder, name) + } + a.EntryMap[name] = append(a.EntryMap[name], path.String()) +} + +// AddOptionalPath appends the given path string to a Make variable with the given name if it is +// valid. It is a no-op if the given path is invalid. +func (a *AndroidMkInfo) AddOptionalPath(name string, path OptionalPath) { + if path.Valid() { + a.AddPath(name, path.Path()) + } +} + +// SetPaths sets a Make variable with the given name to a slice of the given path strings. +func (a *AndroidMkInfo) SetPaths(name string, paths Paths) { + if _, ok := a.EntryMap[name]; !ok { + a.EntryOrder = append(a.EntryOrder, name) + } + a.EntryMap[name] = paths.Strings() +} + +// SetOptionalPaths sets a Make variable with the given name to a slice of the given path strings +// only if there are a non-zero amount of paths. +func (a *AndroidMkInfo) SetOptionalPaths(name string, paths Paths) { + if len(paths) > 0 { + a.SetPaths(name, paths) + } +} + +// AddPaths appends the given path strings to a Make variable with the given name. +func (a *AndroidMkInfo) AddPaths(name string, paths Paths) { + if _, ok := a.EntryMap[name]; !ok { + a.EntryOrder = append(a.EntryOrder, name) + } + a.EntryMap[name] = append(a.EntryMap[name], paths.Strings()...) +} + +// SetBoolIfTrue sets a Make variable with the given name to true if the given flag is true. +// It is a no-op if the given flag is false. +func (a *AndroidMkInfo) SetBoolIfTrue(name string, flag bool) { + if flag { + if _, ok := a.EntryMap[name]; !ok { + a.EntryOrder = append(a.EntryOrder, name) + } + a.EntryMap[name] = []string{"true"} + } +} + +// SetBool sets a Make variable with the given name to if the given bool flag value. +func (a *AndroidMkInfo) SetBool(name string, flag bool) { + if _, ok := a.EntryMap[name]; !ok { + a.EntryOrder = append(a.EntryOrder, name) + } + if flag { + a.EntryMap[name] = []string{"true"} + } else { + a.EntryMap[name] = []string{"false"} + } +} + +// AddStrings appends the given strings to a Make variable with the given name. +func (a *AndroidMkInfo) AddStrings(name string, value ...string) { + if len(value) == 0 { + return + } + if _, ok := a.EntryMap[name]; !ok { + a.EntryOrder = append(a.EntryOrder, name) + } + a.EntryMap[name] = append(a.EntryMap[name], value...) +} + +// AddCompatibilityTestSuites adds the supplied test suites to the EntryMap, with special handling +// for partial MTS and MCTS test suites. +func (a *AndroidMkInfo) AddCompatibilityTestSuites(suites ...string) { + // M(C)TS supports a full test suite and partial per-module MTS test suites, with naming mts-${MODULE}. + // To reduce repetition, if we find a partial M(C)TS test suite without an full M(C)TS test suite, + // we add the full test suite to our list. + if PrefixInList(suites, "mts-") && !InList("mts", suites) { + suites = append(suites, "mts") + } + if PrefixInList(suites, "mcts-") && !InList("mcts", suites) { + suites = append(suites, "mcts") + } + a.AddStrings("LOCAL_COMPATIBILITY_SUITE", suites...) +} + +func (a *AndroidMkInfo) fillInEntries(ctx fillInEntriesContext, mod blueprint.Module) { + helperInfo := AndroidMkInfo{ + EntryMap: make(map[string][]string), + } + + amod := mod.(Module) + base := amod.base() + name := base.BaseModuleName() + if a.OverrideName != "" { + name = a.OverrideName + } + + if a.Include == "" { + a.Include = "$(BUILD_PREBUILT)" + } + a.Required = append(a.Required, amod.RequiredModuleNames(ctx)...) + a.Required = append(a.Required, amod.VintfFragmentModuleNames(ctx)...) + a.Host_required = append(a.Host_required, amod.HostRequiredModuleNames()...) + a.Target_required = append(a.Target_required, amod.TargetRequiredModuleNames()...) + + for _, distString := range a.GetDistForGoals(ctx, mod) { + a.HeaderStrings = append(a.HeaderStrings, distString) + } + + a.HeaderStrings = append(a.HeaderStrings, fmt.Sprintf("\ninclude $(CLEAR_VARS) # type: %s, name: %s, variant: %s\n", ctx.ModuleType(mod), base.BaseModuleName(), ctx.ModuleSubDir(mod))) + + // Collect make variable assignment entries. + helperInfo.SetString("LOCAL_PATH", ctx.ModuleDir(mod)) + helperInfo.SetString("LOCAL_MODULE", name+a.SubName) + helperInfo.SetString("LOCAL_MODULE_CLASS", a.Class) + helperInfo.SetString("LOCAL_PREBUILT_MODULE_FILE", a.OutputFile.String()) + helperInfo.AddStrings("LOCAL_REQUIRED_MODULES", a.Required...) + helperInfo.AddStrings("LOCAL_HOST_REQUIRED_MODULES", a.Host_required...) + helperInfo.AddStrings("LOCAL_TARGET_REQUIRED_MODULES", a.Target_required...) + helperInfo.AddStrings("LOCAL_SOONG_MODULE_TYPE", ctx.ModuleType(amod)) + + // If the install rule was generated by Soong tell Make about it. + info := OtherModuleProviderOrDefault(ctx, mod, InstallFilesProvider) + if len(info.KatiInstalls) > 0 { + // Assume the primary install file is last since it probably needs to depend on any other + // installed files. If that is not the case we can add a method to specify the primary + // installed file. + helperInfo.SetPath("LOCAL_SOONG_INSTALLED_MODULE", info.KatiInstalls[len(info.KatiInstalls)-1].to) + helperInfo.SetString("LOCAL_SOONG_INSTALL_PAIRS", info.KatiInstalls.BuiltInstalled()) + helperInfo.SetPaths("LOCAL_SOONG_INSTALL_SYMLINKS", info.KatiSymlinks.InstallPaths().Paths()) + } else { + // Soong may not have generated the install rule also when `no_full_install: true`. + // Mark this module as uninstallable in order to prevent Make from creating an + // install rule there. + helperInfo.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", proptools.Bool(base.commonProperties.No_full_install)) + } + + if len(info.TestData) > 0 { + helperInfo.AddStrings("LOCAL_TEST_DATA", androidMkDataPaths(info.TestData)...) + } + + if am, ok := mod.(ApexModule); ok { + helperInfo.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", am.NotAvailableForPlatform()) + } + + archStr := base.Arch().ArchType.String() + host := false + switch base.Os().Class { + case Host: + if base.Target().HostCross { + // Make cannot identify LOCAL_MODULE_HOST_CROSS_ARCH:= common. + if base.Arch().ArchType != Common { + helperInfo.SetString("LOCAL_MODULE_HOST_CROSS_ARCH", archStr) + } + } else { + // Make cannot identify LOCAL_MODULE_HOST_ARCH:= common. + if base.Arch().ArchType != Common { + helperInfo.SetString("LOCAL_MODULE_HOST_ARCH", archStr) + } + } + host = true + case Device: + // Make cannot identify LOCAL_MODULE_TARGET_ARCH:= common. + if base.Arch().ArchType != Common { + if base.Target().NativeBridge { + hostArchStr := base.Target().NativeBridgeHostArchName + if hostArchStr != "" { + helperInfo.SetString("LOCAL_MODULE_TARGET_ARCH", hostArchStr) + } + } else { + helperInfo.SetString("LOCAL_MODULE_TARGET_ARCH", archStr) + } + } + + if !base.InVendorRamdisk() { + helperInfo.AddPaths("LOCAL_FULL_INIT_RC", info.InitRcPaths) + } + if len(info.VintfFragmentsPaths) > 0 { + helperInfo.AddPaths("LOCAL_FULL_VINTF_FRAGMENTS", info.VintfFragmentsPaths) + } + helperInfo.SetBoolIfTrue("LOCAL_PROPRIETARY_MODULE", Bool(base.commonProperties.Proprietary)) + if Bool(base.commonProperties.Vendor) || Bool(base.commonProperties.Soc_specific) { + helperInfo.SetString("LOCAL_VENDOR_MODULE", "true") + } + helperInfo.SetBoolIfTrue("LOCAL_ODM_MODULE", Bool(base.commonProperties.Device_specific)) + helperInfo.SetBoolIfTrue("LOCAL_PRODUCT_MODULE", Bool(base.commonProperties.Product_specific)) + helperInfo.SetBoolIfTrue("LOCAL_SYSTEM_EXT_MODULE", Bool(base.commonProperties.System_ext_specific)) + if base.commonProperties.Owner != nil { + helperInfo.SetString("LOCAL_MODULE_OWNER", *base.commonProperties.Owner) + } + } + + if host { + makeOs := base.Os().String() + if base.Os() == Linux || base.Os() == LinuxBionic || base.Os() == LinuxMusl { + makeOs = "linux" + } + helperInfo.SetString("LOCAL_MODULE_HOST_OS", makeOs) + helperInfo.SetString("LOCAL_IS_HOST_MODULE", "true") + } + + prefix := "" + if base.ArchSpecific() { + switch base.Os().Class { + case Host: + if base.Target().HostCross { + prefix = "HOST_CROSS_" + } else { + prefix = "HOST_" + } + case Device: + prefix = "TARGET_" + + } + + if base.Arch().ArchType != ctx.Config().Targets[base.Os()][0].Arch.ArchType { + prefix = "2ND_" + prefix + } + } + + if licenseMetadata, ok := OtherModuleProvider(ctx, mod, LicenseMetadataProvider); ok { + helperInfo.SetPath("LOCAL_SOONG_LICENSE_METADATA", licenseMetadata.LicenseMetadataPath) + } + + if _, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok { + helperInfo.SetBool("LOCAL_SOONG_MODULE_INFO_JSON", true) + } + + a.mergeEntries(&helperInfo) + + // Write to footer. + a.FooterStrings = append([]string{"include " + a.Include}, a.FooterStrings...) +} + +// This method merges the entries to helperInfo, then replaces a's EntryMap and +// EntryOrder with helperInfo's +func (a *AndroidMkInfo) mergeEntries(helperInfo *AndroidMkInfo) { + for _, extraEntry := range a.EntryOrder { + if v, ok := helperInfo.EntryMap[extraEntry]; ok { + v = append(v, a.EntryMap[extraEntry]...) + } else { + helperInfo.EntryMap[extraEntry] = a.EntryMap[extraEntry] + helperInfo.EntryOrder = append(helperInfo.EntryOrder, extraEntry) + } + } + a.EntryOrder = helperInfo.EntryOrder + a.EntryMap = helperInfo.EntryMap +} + +func (a *AndroidMkInfo) disabled() bool { + return a.Disabled || !a.OutputFile.Valid() +} + +// write flushes the AndroidMkEntries's in-struct data populated by AndroidMkEntries into the +// given Writer object. +func (a *AndroidMkInfo) write(w io.Writer) { + if a.disabled() { + return + } + + combinedHeaderString := strings.Join(a.HeaderStrings, "\n") + combinedFooterString := strings.Join(a.FooterStrings, "\n") + w.Write([]byte(combinedHeaderString)) + for _, name := range a.EntryOrder { + AndroidMkEmitAssignList(w, name, a.EntryMap[name]) + } + w.Write([]byte(combinedFooterString)) +} + +// Compute the list of Make strings to declare phony goals and dist-for-goals +// calls from the module's dist and dists properties. +func (a *AndroidMkInfo) GetDistForGoals(ctx fillInEntriesContext, mod blueprint.Module) []string { + distContributions := a.getDistContributions(ctx, mod) + if distContributions == nil { + return nil + } + + return generateDistContributionsForMake(distContributions) +} + +// Compute the contributions that the module makes to the dist. +func (a *AndroidMkInfo) getDistContributions(ctx fillInEntriesContext, mod blueprint.Module) *distContributions { + amod := mod.(Module).base() + name := amod.BaseModuleName() + + // Collate the set of associated tag/paths available for copying to the dist. + // Start with an empty (nil) set. + var availableTaggedDists TaggedDistFiles + + // Then merge in any that are provided explicitly by the module. + if a.DistFiles != nil { + // Merge the DistFiles into the set. + availableTaggedDists = availableTaggedDists.merge(a.DistFiles) + } + + // If no paths have been provided for the DefaultDistTag and the output file is + // valid then add that as the default dist path. + if _, ok := availableTaggedDists[DefaultDistTag]; !ok && a.OutputFile.Valid() { + availableTaggedDists = availableTaggedDists.addPathsForTag(DefaultDistTag, a.OutputFile.Path()) + } + + info := OtherModuleProviderOrDefault(ctx, mod, InstallFilesProvider) + // If the distFiles created by GenerateTaggedDistFiles contains paths for the + // DefaultDistTag then that takes priority so delete any existing paths. + if _, ok := info.DistFiles[DefaultDistTag]; ok { + delete(availableTaggedDists, DefaultDistTag) + } + + // Finally, merge the distFiles created by GenerateTaggedDistFiles. + availableTaggedDists = availableTaggedDists.merge(info.DistFiles) + + if len(availableTaggedDists) == 0 { + // Nothing dist-able for this module. + return nil + } + + // Collate the contributions this module makes to the dist. + distContributions := &distContributions{} + + if !exemptFromRequiredApplicableLicensesProperty(mod.(Module)) { + distContributions.licenseMetadataFile = info.LicenseMetadataFile + } + + // Iterate over this module's dist structs, merged from the dist and dists properties. + for _, dist := range amod.Dists() { + // Get the list of goals this dist should be enabled for. e.g. sdk, droidcore + goals := strings.Join(dist.Targets, " ") + + // Get the tag representing the output files to be dist'd. e.g. ".jar", ".proguard_map" + var tag string + if dist.Tag == nil { + // If the dist struct does not specify a tag, use the default output files tag. + tag = DefaultDistTag + } else { + tag = *dist.Tag + } + + // Get the paths of the output files to be dist'd, represented by the tag. + // Can be an empty list. + tagPaths := availableTaggedDists[tag] + if len(tagPaths) == 0 { + // Nothing to dist for this tag, continue to the next dist. + continue + } + + if len(tagPaths) > 1 && (dist.Dest != nil || dist.Suffix != nil) { + errorMessage := "%s: Cannot apply dest/suffix for more than one dist " + + "file for %q goals tag %q in module %s. The list of dist files, " + + "which should have a single element, is:\n%s" + panic(fmt.Errorf(errorMessage, mod, goals, tag, name, tagPaths)) + } + + copiesForGoals := distContributions.getCopiesForGoals(goals) + + // Iterate over each path adding a copy instruction to copiesForGoals + for _, path := range tagPaths { + // It's possible that the Path is nil from errant modules. Be defensive here. + if path == nil { + tagName := "default" // for error message readability + if dist.Tag != nil { + tagName = *dist.Tag + } + panic(fmt.Errorf("Dist file should not be nil for the %s tag in %s", tagName, name)) + } + + dest := filepath.Base(path.String()) + + if dist.Dest != nil { + var err error + if dest, err = validateSafePath(*dist.Dest); err != nil { + // This was checked in ModuleBase.GenerateBuildActions + panic(err) + } + } + + ext := filepath.Ext(dest) + suffix := "" + if dist.Suffix != nil { + suffix = *dist.Suffix + } + + productString := "" + if dist.Append_artifact_with_product != nil && *dist.Append_artifact_with_product { + productString = fmt.Sprintf("_%s", ctx.Config().DeviceProduct()) + } + + if suffix != "" || productString != "" { + dest = strings.TrimSuffix(dest, ext) + suffix + productString + ext + } + + if dist.Dir != nil { + var err error + if dest, err = validateSafePath(*dist.Dir, dest); err != nil { + // This was checked in ModuleBase.GenerateBuildActions + panic(err) + } + } + + copiesForGoals.addCopyInstruction(path, dest) + } + } + + return distContributions +} + +func deepCopyAndroidMkProviderInfo(providerInfo *AndroidMkProviderInfo) AndroidMkProviderInfo { + info := AndroidMkProviderInfo{ + PrimaryInfo: deepCopyAndroidMkInfo(&providerInfo.PrimaryInfo), + } + if len(providerInfo.ExtraInfo) > 0 { + for _, i := range providerInfo.ExtraInfo { + info.ExtraInfo = append(info.ExtraInfo, deepCopyAndroidMkInfo(&i)) + } + } + return info +} + +func deepCopyAndroidMkInfo(mkinfo *AndroidMkInfo) AndroidMkInfo { + info := AndroidMkInfo{ + Class: mkinfo.Class, + SubName: mkinfo.SubName, + OverrideName: mkinfo.OverrideName, + // There is no modification on DistFiles or OutputFile, so no need to + // make their deep copy. + DistFiles: mkinfo.DistFiles, + OutputFile: mkinfo.OutputFile, + Disabled: mkinfo.Disabled, + Include: mkinfo.Include, + Required: deepCopyStringSlice(mkinfo.Required), + Host_required: deepCopyStringSlice(mkinfo.Host_required), + Target_required: deepCopyStringSlice(mkinfo.Target_required), + HeaderStrings: deepCopyStringSlice(mkinfo.HeaderStrings), + FooterStrings: deepCopyStringSlice(mkinfo.FooterStrings), + EntryOrder: deepCopyStringSlice(mkinfo.EntryOrder), + } + info.EntryMap = make(map[string][]string) + for k, v := range mkinfo.EntryMap { + info.EntryMap[k] = deepCopyStringSlice(v) + } + + return info +} + +func deepCopyStringSlice(original []string) []string { + result := make([]string, len(original)) + copy(result, original) + return result +} diff --git a/filesystem/vbmeta.go b/filesystem/vbmeta.go index 3a9a64daa..1d647965a 100644 --- a/filesystem/vbmeta.go +++ b/filesystem/vbmeta.go @@ -213,6 +213,7 @@ func (v *vbmeta) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.InstallFile(v.installDir, v.installFileName(), v.output) ctx.SetOutputFiles([]android.Path{v.output}, "") + android.SetProvider(ctx, android.AndroidMkInfoProvider, v.prepareAndroidMKProviderInfo()) } // Returns the embedded shell command that prints the rollback index @@ -265,20 +266,17 @@ func (v *vbmeta) extractPublicKeys(ctx android.ModuleContext) map[string]android return result } -var _ android.AndroidMkEntriesProvider = (*vbmeta)(nil) - -// Implements android.AndroidMkEntriesProvider -func (v *vbmeta) AndroidMkEntries() []android.AndroidMkEntries { - return []android.AndroidMkEntries{android.AndroidMkEntries{ - Class: "ETC", - OutputFile: android.OptionalPathForPath(v.output), - ExtraEntries: []android.AndroidMkExtraEntriesFunc{ - func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { - entries.SetString("LOCAL_MODULE_PATH", v.installDir.String()) - entries.SetString("LOCAL_INSTALLED_MODULE_STEM", v.installFileName()) - }, +func (v *vbmeta) prepareAndroidMKProviderInfo() *android.AndroidMkProviderInfo { + providerData := android.AndroidMkProviderInfo{ + PrimaryInfo: android.AndroidMkInfo{ + Class: "ETC", + OutputFile: android.OptionalPathForPath(v.output), + EntryMap: make(map[string][]string), }, - }} + } + providerData.PrimaryInfo.SetString("LOCAL_MODULE_PATH", v.installDir.String()) + providerData.PrimaryInfo.SetString("LOCAL_INSTALLED_MODULE_STEM", v.installFileName()) + return &providerData } var _ Filesystem = (*vbmeta)(nil)