Merge "Add framework for using provider on AndroidMKEntries" into main
This commit is contained in:
@@ -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 {
|
func mergeAconfigFiles(ctx ModuleContext, container string, inputs Paths, generateRule bool) Paths {
|
||||||
inputs = SortedUniquePaths(inputs)
|
inputs = SortedUniquePaths(inputs)
|
||||||
if len(inputs) == 1 {
|
if len(inputs) == 1 {
|
||||||
|
@@ -806,15 +806,21 @@ func translateAndroidMkModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs
|
|||||||
|
|
||||||
// Additional cases here require review for correct license propagation to make.
|
// Additional cases here require review for correct license propagation to make.
|
||||||
var err error
|
var err error
|
||||||
switch x := mod.(type) {
|
|
||||||
case AndroidMkDataProvider:
|
if info, ok := ctx.otherModuleProvider(mod, AndroidMkInfoProvider); ok {
|
||||||
err = translateAndroidModule(ctx, w, moduleInfoJSONs, mod, x)
|
androidMkEntriesInfos := info.(*AndroidMkProviderInfo)
|
||||||
case bootstrap.GoBinaryTool:
|
err = translateAndroidMkEntriesInfoModule(ctx, w, moduleInfoJSONs, mod, androidMkEntriesInfos)
|
||||||
err = translateGoBinaryModule(ctx, w, mod, x)
|
} else {
|
||||||
case AndroidMkEntriesProvider:
|
switch x := mod.(type) {
|
||||||
err = translateAndroidMkEntriesModule(ctx, w, moduleInfoJSONs, mod, x)
|
case AndroidMkDataProvider:
|
||||||
default:
|
err = translateAndroidModule(ctx, w, moduleInfoJSONs, mod, x)
|
||||||
// Not exported to make so no make variables to set.
|
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 {
|
if err != nil {
|
||||||
@@ -1063,3 +1069,564 @@ func AndroidMkEmitAssignList(w io.Writer, varName string, lists ...[]string) {
|
|||||||
}
|
}
|
||||||
fmt.Fprintln(w)
|
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-<product name>.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
|
||||||
|
}
|
||||||
|
@@ -213,6 +213,7 @@ func (v *vbmeta) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||||||
ctx.InstallFile(v.installDir, v.installFileName(), v.output)
|
ctx.InstallFile(v.installDir, v.installFileName(), v.output)
|
||||||
|
|
||||||
ctx.SetOutputFiles([]android.Path{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
|
// 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
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ android.AndroidMkEntriesProvider = (*vbmeta)(nil)
|
func (v *vbmeta) prepareAndroidMKProviderInfo() *android.AndroidMkProviderInfo {
|
||||||
|
providerData := android.AndroidMkProviderInfo{
|
||||||
// Implements android.AndroidMkEntriesProvider
|
PrimaryInfo: android.AndroidMkInfo{
|
||||||
func (v *vbmeta) AndroidMkEntries() []android.AndroidMkEntries {
|
Class: "ETC",
|
||||||
return []android.AndroidMkEntries{android.AndroidMkEntries{
|
OutputFile: android.OptionalPathForPath(v.output),
|
||||||
Class: "ETC",
|
EntryMap: make(map[string][]string),
|
||||||
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())
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}}
|
}
|
||||||
|
providerData.PrimaryInfo.SetString("LOCAL_MODULE_PATH", v.installDir.String())
|
||||||
|
providerData.PrimaryInfo.SetString("LOCAL_INSTALLED_MODULE_STEM", v.installFileName())
|
||||||
|
return &providerData
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Filesystem = (*vbmeta)(nil)
|
var _ Filesystem = (*vbmeta)(nil)
|
||||||
|
Reference in New Issue
Block a user