diff options
Diffstat (limited to 'android/module.go')
| -rw-r--r-- | android/module.go | 606 |
1 files changed, 406 insertions, 200 deletions
diff --git a/android/module.go b/android/module.go index baacfa7e1..481e4107f 100644 --- a/android/module.go +++ b/android/module.go @@ -27,10 +27,12 @@ import ( "github.com/google/blueprint" "github.com/google/blueprint/depset" - "github.com/google/blueprint/gobtools" + "github.com/google/blueprint/pathtools" "github.com/google/blueprint/proptools" ) +//go:generate go run ../../blueprint/gobtools/codegen/gob_gen.go + var ( DeviceSharedLibrary = "shared_library" DeviceStaticLibrary = "static_library" @@ -45,6 +47,14 @@ type Module interface { // For more information, see Module.GenerateBuildActions within Blueprint's module_ctx.go GenerateAndroidBuildActions(ModuleContext) + // CleanupAfterBuildActions is called after ModuleBase.GenerateBuildActions is finished. + // If all interactions with this module are handled via providers instead of direct access + // to the module then it can free memory attached to the module. + // This is a temporary measure to reduce memory usage, eventually blueprint's reference + // to the Module should be dropped after GenerateAndroidBuildActions once all accesses + // can be done through providers. + CleanupAfterBuildActions() + // Add dependencies to the components of a module, i.e. modules that are created // by the module and which are considered to be part of the creating module. // @@ -112,7 +122,7 @@ type Module interface { qualifiedModuleId(ctx BaseModuleContext) qualifiedModuleName // Get information about the properties that can contain visibility rules. - visibilityProperties() []visibilityProperty + visibilityProperties() []*visibilityProperty RequiredModuleNames(ctx ConfigurableEvaluatorContext) []string HostRequiredModuleNames() []string @@ -132,6 +142,8 @@ type Module interface { // If this is true, the module must not read product-specific configurations. UseGenericConfig() bool + + NoFullInstall() bool } // Qualified id for a module @@ -177,6 +189,7 @@ func newPackageId(pkg string) qualifiedModuleName { return qualifiedModuleName{pkg: pkg, name: ""} } +// @auto-generate: gob type Dist struct { // Copy the output of this module to the $DIST_DIR when `dist` is specified on the // command line and any of these targets are also on the command line, or otherwise @@ -413,12 +426,6 @@ type commonProperties struct { // Whether this module is built for non-native architectures (also known as native bridge binary) Native_bridge_supported *bool `android:"arch_variant"` - // init.rc files to be installed if this module is installed - Init_rc proptools.Configurable[[]string] `android:"arch_variant,path"` - - // VINTF manifest fragments to be installed if this module is installed - Vintf_fragments proptools.Configurable[[]string] `android:"path"` - // The OsType of artifacts that this module variant is responsible for creating. // // Set by osMutator @@ -500,6 +507,7 @@ type commonProperties struct { // Name and variant strings stored by mutators to enable Module.String() DebugName string `blueprint:"mutated"` + DebugNamespace string `blueprint:"mutated"` DebugMutators []string `blueprint:"mutated"` DebugVariations []string `blueprint:"mutated"` @@ -511,13 +519,6 @@ type commonProperties struct { // The team (defined by the owner/vendor) who owns the property. Team *string `android:"path"` - // vintf_fragment Modules required from this module. - Vintf_fragment_modules proptools.Configurable[[]string] `android:"path"` - - // List of module names that are prevented from being installed when this module gets - // installed. - Overrides []string - // Set to true if this module must be generic and does not require product-specific information. // To be included in the system image, this property must be set to true. Use_generic_config *bool @@ -539,6 +540,19 @@ type baseProperties struct { // module type. This is used by neverallow to ensure you can't bypass a ModuleType() matcher // just by creating a soong config module type. Soong_config_base_module_type *string `blueprint:"mutated"` + + // init.rc files to be installed if this module is installed + Init_rc proptools.Configurable[[]string] `android:"arch_variant,path"` + + // VINTF manifest fragments to be installed if this module is installed + Vintf_fragments proptools.Configurable[[]string] `android:"path"` + + // vintf_fragment Modules required from this module. + Vintf_fragment_modules proptools.Configurable[[]string] `android:"path"` + + // List of module names that are prevented from being installed when this module gets + // installed. + Overrides []string } type distProperties struct { @@ -840,6 +854,7 @@ func InitCommonOSAndroidMultiTargetsArchModule(m Module, hod HostOrDeviceSupport // // ... // } type ModuleBase struct { + blueprint.ModuleBase // Putting the curiously recurring thing pointing to the thing that contains // the thing pattern to good use. // TODO: remove this @@ -862,13 +877,13 @@ type ModuleBase struct { // Information about all the properties on the module that contains visibility rules that need // checking. - visibilityPropertyInfo []visibilityProperty + visibilityPropertyInfo []*visibilityProperty // The primary visibility property, may be nil, that controls access to the module. - primaryVisibilityProperty visibilityProperty + primaryVisibilityProperty *visibilityProperty // The primary licenses property, may be nil, records license metadata for the module. - primaryLicensesProperty applicableLicensesProperty + primaryLicensesProperty *applicableLicensesProperty noAddressSanitizer bool @@ -882,13 +897,6 @@ type ModuleBase struct { variables map[string]string } -func (m *ModuleBase) AddJSONData(d *map[string]interface{}) { - (*d)["Android"] = map[string]interface{}{ - // Properties set in Blueprint or in blueprint of a defaults modules - "SetProperties": m.propertiesWithValues(), - } -} - type propInfo struct { Name string Type string @@ -1032,6 +1040,9 @@ func (m *ModuleBase) baseOverridablePropertiesDepsMutator(ctx BottomUpMutatorCon // addRequiredDeps adds required, target_required, and host_required as dependencies. func addRequiredDeps(ctx BottomUpMutatorContext) { addDep := func(target Target, depName string) { + if !blueprint.IsValidModuleName(depName) { + ctx.PropertyErrorf("required", "%s is not a valid module", depName) + } if !ctx.OtherModuleExists(depName) { if ctx.Config().AllowMissingDependencies() { return @@ -1118,29 +1129,21 @@ func addVintfFragmentDeps(ctx BottomUpMutatorContext) { return } - deviceConfig := ctx.DeviceConfig() - mod := ctx.Module() - vintfModules := ctx.AddDependency(mod, vintfDepTag, mod.VintfFragmentModuleNames(ctx)...) + ctx.AddDependency(mod, vintfDepTag, mod.VintfFragmentModuleNames(ctx)...) +} - modPartition := mod.PartitionTag(deviceConfig) - for _, vintf := range vintfModules { - if vintf == nil { - // TODO(b/372091092): Remove this. Having it gives us missing dependency errors instead - // of nil pointer dereference errors, but we should resolve the missing dependencies. - continue +func checkVintfFragmentDeps(ctx ModuleContext) { + modPartition := ctx.Module().PartitionTag(ctx.DeviceConfig()) + ctx.VisitDirectDepsProxyWithTag(vintfDepTag, func(vintf ModuleProxy) { + commonInfo := OtherModulePointerProviderOrDefault(ctx, vintf, CommonModuleInfoProvider) + vintfPartition := commonInfo.PartitionTag + if modPartition != vintfPartition { + ctx.ModuleErrorf("Module %q(%q) and Vintf_fragment %q(%q) are installed to different partitions.", + ctx.ModuleName(), modPartition, + vintf.Name(), vintfPartition) } - if vintfModule, ok := vintf.(*VintfFragmentModule); ok { - vintfPartition := vintfModule.PartitionTag(deviceConfig) - if modPartition != vintfPartition { - ctx.ModuleErrorf("Module %q(%q) and Vintf_fragment %q(%q) are installed to different partitions.", - mod.Name(), modPartition, - vintfModule.Name(), vintfPartition) - } - } else { - ctx.ModuleErrorf("Only vintf_fragment type module should be listed in vintf_fragment_modules : %q", vintf.Name()) - } - } + }) } // AddProperties "registers" the provided props @@ -1224,7 +1227,7 @@ func (m *ModuleBase) qualifiedModuleId(ctx BaseModuleContext) qualifiedModuleNam return qualifiedModuleName{pkg: ctx.ModuleDir(), name: ctx.ModuleName()} } -func (m *ModuleBase) visibilityProperties() []visibilityProperty { +func (m *ModuleBase) visibilityProperties() []*visibilityProperty { return m.visibilityPropertyInfo } @@ -1307,6 +1310,10 @@ func (m *ModuleBase) IsCommonOSVariant() bool { return m.commonProperties.CompileOS == CommonOS } +func (m *ModuleBase) NoFullInstall() bool { + return proptools.Bool(m.commonProperties.No_full_install) +} + // supportsTarget returns true if the given Target is supported by the current module. func (m *ModuleBase) supportsTarget(target Target) bool { switch target.Os.Class { @@ -1424,6 +1431,8 @@ func (m *ModuleBase) PartitionTag(config DeviceConfig) string { partition = "vendor_ramdisk" } else if m.InstallInRecovery() { partition = "recovery" + } else if m.InstallInVendorDlkm() { + partition = "vendor_dlkm" } return partition } @@ -1660,45 +1669,54 @@ func (m *ModuleBase) TargetRequiredModuleNames() []string { } func (m *ModuleBase) VintfFragmentModuleNames(ctx ConfigurableEvaluatorContext) []string { - return m.base().commonProperties.Vintf_fragment_modules.GetOrDefault(m.ConfigurableEvaluator(ctx), nil) + return m.base().baseProperties.Vintf_fragment_modules.GetOrDefault(m.ConfigurableEvaluator(ctx), nil) } func (m *ModuleBase) VintfFragments(ctx ConfigurableEvaluatorContext) []string { - return m.base().commonProperties.Vintf_fragments.GetOrDefault(m.ConfigurableEvaluator(ctx), nil) -} - -func (m *ModuleBase) generateVariantTarget(ctx *moduleContext) { - namespacePrefix := ctx.Namespace().id - if namespacePrefix != "" { - namespacePrefix = namespacePrefix + "-" - } - - if !ctx.uncheckedModule { - name := namespacePrefix + ctx.ModuleName() + "-" + ctx.ModuleSubDir() + "-checkbuild" - ctx.Phony(name, ctx.checkbuildFiles...) - ctx.checkbuildTarget = PathForPhony(ctx, name) - } - + return m.base().baseProperties.Vintf_fragments.GetOrDefault(m.ConfigurableEvaluator(ctx), nil) } // generateModuleTarget generates phony targets so that you can do `m <module-name>`. // It will be run on every variant of the module, so it relies on the fact that phony targets // are deduped to merge all the deps from different variants together. -func (m *ModuleBase) generateModuleTarget(ctx *moduleContext) { +func (m *ModuleBase) generateModuleTarget(ctx *moduleContext, testSuiteInstalls []filePair) { var namespacePrefix string nameSpace := ctx.Namespace().Path if nameSpace != "." { namespacePrefix = strings.ReplaceAll(nameSpace, "/", ".") + "-" } + shouldSkipAndroidMk := shouldSkipAndroidMkProcessing(ctx, m) + + phony := func(suffix string, deps Paths) string { + if ctx.Config().KatiEnabled() { + suffix += "-soong" + } + var ret string + // Create a target without the namespace prefix if it's exported to make. One of the + // conditions for being exported to make is that the namespace is in + // PRODUCT_SOONG_NAMESPACES, so historically that would mean that make would create the + // phonies for those modules as if they weren't in any namespace. + if !shouldSkipAndroidMk { + ret = ctx.module.base().BaseModuleName() + suffix + ctx.Phony(ret, deps...) + } + // Create another phony for building with the namespace specified. This can be used + // regardless of if the namespace is in PRODUCT_SOONG_NAMESPACES or not. + if nameSpace != "." { + ctx.Phony(namespacePrefix+ctx.module.base().BaseModuleName()+suffix, deps...) + } + return ret + } var deps Paths var info ModuleBuildTargetsInfo - if len(ctx.installFiles) > 0 { - name := namespacePrefix + ctx.ModuleName() + "-install" + if len(ctx.installFiles) > 0 && !shouldSkipAndroidMk { installFiles := ctx.installFiles.Paths() - ctx.Phony(name, installFiles...) - info.InstallTarget = PathForPhony(ctx, name) + name := phony("-install", installFiles) + if name != "" { + info.InstallTarget = PathForPhony(ctx, name) + } deps = append(deps, installFiles...) } @@ -1706,38 +1724,47 @@ func (m *ModuleBase) generateModuleTarget(ctx *moduleContext) { // not be created if the module is not exported to make. // Those could depend on the build target and fail to compile // for the current build target. - if (!ctx.Config().KatiEnabled() || !shouldSkipAndroidMkProcessing(ctx, m)) && !ctx.uncheckedModule && ctx.checkbuildTarget != nil { - name := namespacePrefix + ctx.ModuleName() + "-checkbuild" - ctx.Phony(name, ctx.checkbuildTarget) - deps = append(deps, ctx.checkbuildTarget) + if !shouldSkipAndroidMk && !ctx.uncheckedModule { + phony("-checkbuild", ctx.checkbuildFiles) + checkbuildTarget := phony("-"+ctx.ModuleSubDir()+"-checkbuild", ctx.checkbuildFiles) + if checkbuildTarget != "" { + info.CheckbuildTarget = PathForPhony(ctx, checkbuildTarget) + } + deps = append(deps, ctx.checkbuildFiles...) } - if outputFiles, err := outputFilesForModule(ctx, ctx.Module(), ""); err == nil && len(outputFiles) > 0 { - name := namespacePrefix + ctx.ModuleName() + "-outputs" - ctx.Phony(name, outputFiles...) + if outputFiles, err := outputFilesForModule(ctx, ctx.Module(), ""); err == nil && len(outputFiles) > 0 && !shouldSkipAndroidMk { + phony("-outputs", outputFiles) deps = append(deps, outputFiles...) } - if len(deps) > 0 { - suffix := "" - if ctx.Config().KatiEnabled() { - suffix = "-soong" + // Act as if you built the required dependencies as well when building the current module + for _, dep := range ctx.GetDirectDepsProxyWithTag(RequiredDepTag) { + if info, ok := OtherModuleProvider(ctx, dep, ModuleBuildTargetsProvider); ok { + deps = append(deps, info.AllDeps...) } + } - ctx.Phony(namespacePrefix+ctx.ModuleName()+suffix, deps...) + for _, p := range testSuiteInstalls { + deps = append(deps, p.dst) + } + + if len(deps) > 0 { + phony("", deps) if ctx.Device() { // Generate a target suffix for use in atest etc. - ctx.Phony(namespacePrefix+ctx.ModuleName()+"-target"+suffix, deps...) + phony("-target", deps) } else { // Generate a host suffix for use in atest etc. - ctx.Phony(namespacePrefix+ctx.ModuleName()+"-host"+suffix, deps...) + phony("-host", deps) if ctx.Target().HostCross { // Generate a host-cross suffix for use in atest etc. - ctx.Phony(namespacePrefix+ctx.ModuleName()+"-host-cross"+suffix, deps...) + phony("-host-cross", deps) } } info.BlueprintDir = ctx.ModuleDir() + info.AllDeps = deps SetProvider(ctx, ModuleBuildTargetsProvider, info) } } @@ -1830,24 +1857,37 @@ func (m *ModuleBase) archModuleContextFactory(ctx archModuleContextFactoryContex } else { primaryArch = target.Arch.ArchType == config.Targets[target.Os][0].Arch.ArchType } + primaryNativeBridgeArch := false + if target.NativeBridge { + for _, t := range config.Targets[target.Os] { + if t.NativeBridge { + if target.Arch.ArchType == t.Arch.ArchType { + primaryNativeBridgeArch = true + } + // Don't consider further nativebridge targets + break + } + } + } return archModuleContext{ - ready: m.commonProperties.ArchReady, - os: m.commonProperties.CompileOS, - target: m.commonProperties.CompileTarget, - targetPrimary: m.commonProperties.CompilePrimary, - multiTargets: m.commonProperties.CompileMultiTargets, - primaryArch: primaryArch, + ready: m.commonProperties.ArchReady, + os: m.commonProperties.CompileOS, + target: m.commonProperties.CompileTarget, + targetPrimary: m.commonProperties.CompilePrimary, + multiTargets: m.commonProperties.CompileMultiTargets, + primaryArch: primaryArch, + primaryNativeBridgeArch: primaryNativeBridgeArch, } } +// @auto-generate: gob type InstallFilesInfo struct { - InstallFiles InstallPaths - CheckbuildFiles Paths - CheckbuildTarget Path - UncheckedModule bool - PackagingSpecs []PackagingSpec + InstallFiles InstallPaths + CheckbuildFiles Paths + UncheckedModule bool + PackagingSpecs []PackagingSpec // katiInstalls tracks the install rules that were created by Soong but are being exported // to Make to convert to ninja rules so that Make can add additional dependencies. KatiInstalls katiInstalls @@ -1882,18 +1922,19 @@ var SourceFilesInfoProvider = blueprint.NewProvider[SourceFilesInfo]() // ModuleBuildTargetsInfo is used by buildTargetSingleton to create checkbuild and // per-directory build targets. +// @auto-generate: gob type ModuleBuildTargetsInfo struct { InstallTarget WritablePath CheckbuildTarget WritablePath BlueprintDir string + AllDeps Paths } var ModuleBuildTargetsProvider = blueprint.NewProvider[ModuleBuildTargetsInfo]() +// @auto-generate: gob type CommonModuleInfo struct { Enabled bool - // Whether the module has been replaced by a prebuilt - ReplacedByPrebuilt bool // The Target of artifacts that this module variant is responsible for creating. Target Target SkipAndroidMkProcessing bool @@ -1901,7 +1942,6 @@ type CommonModuleInfo struct { CanHaveApexVariants bool MinSdkVersion ApiLevelOrPlatform SdkVersion string - NotAvailableForPlatform bool // There some subtle differences between this one and the one above. NotInPlatform bool // UninstallableApexPlatformVariant is set by MakeUninstallable called by the apex @@ -1921,7 +1961,7 @@ type CommonModuleInfo struct { Host bool IsApexModule bool // The primary licenses property, may be nil, records license metadata for the module. - PrimaryLicensesProperty applicableLicensesProperty + PrimaryLicensesProperty *applicableLicensesProperty Owner string Vendor bool Proprietary bool @@ -1929,6 +1969,7 @@ type CommonModuleInfo struct { ProductSpecific bool SystemExtSpecific bool DeviceSpecific bool + UseGenericConfig bool // When set to true, this module is not installed to the full install path (ex: under // out/target/product/<name>/<partition>). It can be installed only to the packaging // modules like android_filesystem. @@ -1943,8 +1984,14 @@ type CommonModuleInfo struct { ExportedToMake bool Team string PartitionTag string + ApexAvailable []string + // This field is different from the above one as it can have different values + // for cc, java library and sdkLibraryXml. + ApexAvailableFor []string + ImageVariation blueprint.Variation } +// @auto-generate: gob type ApiLevelOrPlatform struct { ApiLevel *ApiLevel IsPlatform bool @@ -1952,13 +1999,7 @@ type ApiLevelOrPlatform struct { var CommonModuleInfoProvider = blueprint.NewProvider[*CommonModuleInfo]() -type PrebuiltModuleInfo struct { - SourceExists bool - UsePrebuilt bool -} - -var PrebuiltModuleInfoProvider = blueprint.NewProvider[PrebuiltModuleInfo]() - +// @auto-generate: gob type HostToolProviderInfo struct { HostToolPath OptionalPath } @@ -1994,6 +2035,12 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) phonies: make(map[string]Paths), } + blueprintCtx.RegisterConfigurableEvaluator(ctx) + + if ctx.config.captureBuild { + ctx.config.modulesForTests.Insert(ctx.ModuleName(), ctx.Module()) + } + setContainerInfo(ctx) if ctx.Config().Getenv("DISABLE_CONTAINER_CHECK") != "true" { checkContainerViolations(ctx) @@ -2012,6 +2059,8 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) // TODO: This will be removed once defaults modules handle missing dependency errors blueprintCtx.GetMissingDependencies() + checkVintfFragmentDeps(ctx) + // For the final GenerateAndroidBuildActions pass, require that all visited dependencies Soong modules and // are enabled. Unless the module is a CommonOS variant which may have dependencies on disabled variants // (because the dependencies are added before the modules are disabled). The @@ -2064,7 +2113,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) // so only a single rule is created for each init.rc or vintf fragment file. if !m.InVendorRamdisk() { - ctx.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc.GetOrDefault(ctx, nil)) + ctx.initRcPaths = PathsForModuleSrc(ctx, m.baseProperties.Init_rc.GetOrDefault(ctx, nil)) rcDir := PathForModuleInstall(ctx, "etc", "init") for _, src := range ctx.initRcPaths { installedInitRc := rcDir.Join(ctx, src.Base()) @@ -2080,7 +2129,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) installFiles.InstalledInitRcPaths = ctx.installedInitRcPaths } - ctx.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments.GetOrDefault(ctx, nil)) + ctx.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.baseProperties.Vintf_fragments.GetOrDefault(ctx, nil)) vintfDir := PathForModuleInstall(ctx, "etc", "vintf", "manifest") for _, src := range ctx.vintfFragmentsPaths { installedVintfFragment := vintfDir.Join(ctx, src.Base()) @@ -2120,6 +2169,8 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) return } + m.module.base().hooks.runPostGenerateAndroidBuildActionsHooks(ctx) + if x, ok := m.module.(IDEInfo); ok { var result IdeInfo x.IDEInfo(ctx, &result) @@ -2136,17 +2187,18 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) return } - m.generateVariantTarget(ctx) + testData := FirstUniqueFunc(ctx.testData, func(a, b DataPath) bool { + return a == b + }) installFiles.LicenseMetadataFile = ctx.licenseMetadataFile installFiles.InstallFiles = ctx.installFiles installFiles.CheckbuildFiles = ctx.checkbuildFiles - installFiles.CheckbuildTarget = ctx.checkbuildTarget installFiles.UncheckedModule = ctx.uncheckedModule installFiles.PackagingSpecs = ctx.packagingSpecs installFiles.KatiInstalls = ctx.katiInstalls installFiles.KatiSymlinks = ctx.katiSymlinks - installFiles.TestData = ctx.testData + installFiles.TestData = testData } else if ctx.Config().AllowMissingDependencies() { // If the module is not enabled it will not create any build rules, nothing will call // ctx.GetMissingDependencies(), and blueprint will consider the missing dependencies to be unhandled @@ -2166,18 +2218,27 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) SetProvider(ctx, SourceFilesInfoProvider, SourceFilesInfo{Srcs: sourceFileProducer.Srcs()}) } - m.generateModuleTarget(ctx) - if ctx.Failed() { - return - } - ctx.TransitiveInstallFiles = depset.New[InstallPath](depset.TOPOLOGICAL, ctx.installFiles, dependencyInstallFiles) installFiles.TransitiveInstallFiles = ctx.TransitiveInstallFiles installFiles.TransitivePackagingSpecs = depset.New[PackagingSpec](depset.TOPOLOGICAL, ctx.packagingSpecs, dependencyPackagingSpecs) - SetProvider(ctx, InstallFilesProvider, installFiles) + if m.Enabled(ctx) { + SetProvider(ctx, InstallFilesProvider, installFiles) + } buildLicenseMetadata(ctx, ctx.licenseMetadataFile) + var testSuiteInstalls []filePair + if ctx.testSuiteInfoSet { + testSuiteInstalls = m.setupTestSuites(ctx, ctx.testSuiteInfo) + } + + if m.Enabled(ctx) { + m.generateModuleTarget(ctx, testSuiteInstalls) + } + if ctx.Failed() { + return + } + if len(ctx.moduleInfoJSON) > 0 { for _, moduleInfoJSON := range ctx.moduleInfoJSON { if moduleInfoJSON.Disabled { @@ -2257,7 +2318,9 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) } } - SetProvider(ctx, ModuleInfoJSONProvider, ctx.moduleInfoJSON) + SetProvider(ctx, ModuleInfoJSONProvider, ModuleInfoJSONInfo{ + Data: ctx.moduleInfoJSON, + }) } m.buildParams = ctx.buildParams @@ -2285,7 +2348,6 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) commonData := CommonModuleInfo{ Enabled: m.Enabled(ctx), - ReplacedByPrebuilt: m.commonProperties.ReplacedByPrebuilt, Target: m.commonProperties.CompileTarget, SkipAndroidMkProcessing: shouldSkipAndroidMkProcessing(ctx, m), UninstallableApexPlatformVariant: m.commonProperties.UninstallableApexPlatformVariant, @@ -2300,6 +2362,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) ProductSpecific: Bool(m.commonProperties.Product_specific), SystemExtSpecific: Bool(m.commonProperties.System_ext_specific), DeviceSpecific: Bool(m.commonProperties.Device_specific), + UseGenericConfig: m.module.UseGenericConfig(), NoFullInstall: proptools.Bool(m.commonProperties.No_full_install), InVendorRamdisk: m.InVendorRamdisk(), ExemptFromRequiredApplicableLicensesProperty: exemptFromRequiredApplicableLicensesProperty(m.module), @@ -2311,6 +2374,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) ExportedToMake: m.ExportedToMake(), Team: m.Team(), PartitionTag: m.PartitionTag(ctx.DeviceConfig()), + ImageVariation: m.module.ImageVariation(), } if mm, ok := m.module.(interface { MinSdkVersion(ctx EarlyModuleContext) ApiLevel @@ -2341,11 +2405,12 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) if am, ok := m.module.(ApexModule); ok { commonData.CanHaveApexVariants = am.CanHaveApexVariants() - commonData.NotAvailableForPlatform = am.NotAvailableForPlatform() commonData.NotInPlatform = am.NotInPlatform() commonData.MinSdkVersionSupported = am.MinSdkVersionSupported(ctx) commonData.IsInstallableToApex = am.IsInstallableToApex() commonData.IsApexModule = true + commonData.ApexAvailable = am.apexModuleBase().ApexAvailable() + commonData.ApexAvailableFor = am.ApexAvailableFor() } if _, ok := m.module.(ModuleWithMinSdkVersionCheck); ok { @@ -2359,12 +2424,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) commonData.BaseModuleName = mm.BaseModuleName() } SetProvider(ctx, CommonModuleInfoProvider, &commonData) - if p, ok := m.module.(PrebuiltInterface); ok && p.Prebuilt() != nil { - SetProvider(ctx, PrebuiltModuleInfoProvider, PrebuiltModuleInfo{ - SourceExists: p.Prebuilt().SourceExists(), - UsePrebuilt: p.Prebuilt().UsePrebuilt(), - }) - } + if h, ok := m.module.(HostToolProvider); ok { SetProvider(ctx, HostToolProviderInfoProvider, HostToolProviderInfo{ HostToolPath: h.HostToolPath()}) @@ -2393,6 +2453,185 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) }) } } + + if mm, ok := m.module.(RequiredFilesFromPrebuiltApex); ok { + SetProvider(ctx, RequiredFilesFromPrebuiltApexInfoProvider, RequiredFilesFromPrebuiltApexInfo{ + RequiredFilesFromPrebuiltApex: mm.RequiredFilesFromPrebuiltApex(ctx), + UseProfileGuidedDexpreopt: mm.UseProfileGuidedDexpreopt(), + }) + } + + m.module.CleanupAfterBuildActions() +} + +func (m *ModuleBase) CleanupAfterBuildActions() {} + +func (m *ModuleBase) setupTestSuites(ctx ModuleContext, info TestSuiteInfo) []filePair { + // We skip test suites when using the ndk or aml abis, as the extra archs (x86_64 + arm64) + // both try to install to the same test file. This could be fixed by always using a per-module + // folder and an arch folder, but as you see later in this function we only conditionally use + // those. + if ctx.Config().NdkAbis() || ctx.Config().AmlAbis() || shouldSkipAndroidMkProcessing(ctx, m) || m.IsSkipInstall() { + return nil + } + overriddenBy := "" + if b, ok := ctx.Module().(OverridableModule); ok { + overriddenBy = b.GetOverriddenBy() + } + + // 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(info.TestSuites, "mts-") && !InList("mts", info.TestSuites) { + info.TestSuites = append(info.TestSuites, "mts") + } + if PrefixInList(info.TestSuites, "mcts-") && !InList("mcts", info.TestSuites) { + info.TestSuites = append(info.TestSuites, "mcts") + } + + if len(info.TestSuites) == 0 { + info.TestSuites = []string{"null-suite"} + } + info.TestSuites = SortedUniqueStrings(info.TestSuites) + + name := ctx.ModuleName() + if overriddenBy != "" { + name = overriddenBy + } + name += info.NameSuffix + + type testSuiteInfo struct { + name string + dir WritablePath + includeModuleFolder bool + } + + suites := []testSuiteInfo{{ + dir: PathForModuleInPartitionInstall(ctx, "testcases", name), + includeModuleFolder: true, + }} + for _, suite := range info.TestSuites { + if suiteInfo, ok := ctx.Config().productVariables.CompatibilityTestcases[suite]; ok { + rel, err := filepath.Rel(ctx.Config().OutDir(), suiteInfo.OutDir) + if err != nil { + panic(fmt.Sprintf("Could not make COMPATIBILITY_TESTCASES_OUT_%s (%s) relative to the out dir (%s)", suite, suiteInfo.OutDir, ctx.Config().OutDir())) + } + if suiteInfo.IncludeModuleFolder || info.PerTestcaseDirectory { + rel = filepath.Join(rel, name) + } + suites = append(suites, testSuiteInfo{ + name: suite, + dir: PathForArbitraryOutput(ctx, rel), + includeModuleFolder: suiteInfo.IncludeModuleFolder || info.PerTestcaseDirectory, + }) + } + } + + var archDir string + if info.NeedsArchFolder { + archDir = ctx.Arch().ArchType.Name + if archDir == "common" { + archDir = ctx.DeviceConfig().DeviceArch() + } + if ctx.Target().NativeBridge { + archDir = ctx.Target().NativeBridgeHostArchName + } + } + + var installs []filePair + var oneVariantInstalls []filePair + + for _, suite := range suites { + mainFileName := name + if info.MainFileStem != "" { + mainFileName = info.MainFileStem + } + mainFileName += info.MainFileExt + mainFileInstall := joinWriteablePath(ctx, suite.dir, archDir, mainFileName) + if !suite.includeModuleFolder { + mainFileInstall = joinWriteablePath(ctx, suite.dir, mainFileName) + } + if info.MainFile == nil { + panic("mainfile was nil") + } + + installs = append(installs, filePair{ + src: info.MainFile, + dst: mainFileInstall, + }) + + for _, data := range info.Data { + dataOut := joinWriteablePath(ctx, suite.dir, archDir, data.ToRelativeInstallPath()) + if !suite.includeModuleFolder { + dataOut = joinWriteablePath(ctx, suite.dir, data.ToRelativeInstallPath()) + } + installs = append(installs, filePair{ + src: data.SrcPath, + dst: dataOut, + }) + } + for _, data := range info.NonArchData { + dataOut := joinWriteablePath(ctx, suite.dir, data.ToRelativeInstallPath()) + installs = append(installs, filePair{ + src: data.SrcPath, + dst: dataOut, + }) + } + for _, data := range info.CompatibilitySupportFiles { + dataOut := joinWriteablePath(ctx, suite.dir, data.Rel()) + installs = append(installs, filePair{ + src: data, + dst: dataOut, + }) + } + + if !info.DisableTestConfig { + if info.ConfigFile != nil { + oneVariantInstalls = append(oneVariantInstalls, filePair{ + src: info.ConfigFile, + dst: joinWriteablePath(ctx, suite.dir, name+".config"+info.ConfigFileSuffix), + }) + } else if config := ExistentPathForSource(ctx, ctx.ModuleDir(), "AndroidTest.xml"); config.Valid() { + oneVariantInstalls = append(oneVariantInstalls, filePair{ + src: config.Path(), + dst: joinWriteablePath(ctx, suite.dir, name+".config"), + }) + } + } + + dynamicConfig := ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml") + if dynamicConfig.Valid() { + oneVariantInstalls = append(oneVariantInstalls, filePair{ + src: dynamicConfig.Path(), + dst: joinWriteablePath(ctx, suite.dir, name+".dynamic"), + }) + } + for _, extraTestConfig := range info.ExtraConfigs { + if extraTestConfig == nil { + panic("ExtraTestConfig was nil") + } + oneVariantInstalls = append(oneVariantInstalls, filePair{ + src: extraTestConfig, + dst: joinWriteablePath(ctx, suite.dir, pathtools.ReplaceExtension(extraTestConfig.Base(), "config")), + }) + } + } + + SetProvider(ctx, TestSuiteInfoProvider, info) + SetProvider(ctx, testSuiteInstallsInfoProvider, testSuiteInstallsInfo{installs, oneVariantInstalls}) + + return slices.Concat(installs, oneVariantInstalls) +} + +func joinWriteablePath(ctx PathContext, path WritablePath, toJoin ...string) WritablePath { + switch p := path.(type) { + case InstallPath: + return p.Join(ctx, toJoin...) + case OutputPath: + return p.Join(ctx, toJoin...) + default: + panic("unhandled path type") + } } func SetJarJarPrefixHandler(handler func(ModuleContext)) { @@ -2465,6 +2704,7 @@ func checkDistProperties(ctx *moduleContext, property string, dist *Dist) { } // katiInstall stores a request from Soong to Make to create an install rule. +// @auto-generate: gob type katiInstall struct { from Path to InstallPath @@ -2475,76 +2715,12 @@ type katiInstall struct { absFrom string } -type katiInstallGob struct { - From Path - To InstallPath - ImplicitDeps Paths - OrderOnlyDeps Paths - Executable bool - ExtraFiles *extraFilesZip - AbsFrom string -} - -func (k *katiInstall) ToGob() *katiInstallGob { - return &katiInstallGob{ - From: k.from, - To: k.to, - ImplicitDeps: k.implicitDeps, - OrderOnlyDeps: k.orderOnlyDeps, - Executable: k.executable, - ExtraFiles: k.extraFiles, - AbsFrom: k.absFrom, - } -} - -func (k *katiInstall) FromGob(data *katiInstallGob) { - k.from = data.From - k.to = data.To - k.implicitDeps = data.ImplicitDeps - k.orderOnlyDeps = data.OrderOnlyDeps - k.executable = data.Executable - k.extraFiles = data.ExtraFiles - k.absFrom = data.AbsFrom -} - -func (k *katiInstall) GobEncode() ([]byte, error) { - return gobtools.CustomGobEncode[katiInstallGob](k) -} - -func (k *katiInstall) GobDecode(data []byte) error { - return gobtools.CustomGobDecode[katiInstallGob](data, k) -} - +// @auto-generate: gob type extraFilesZip struct { zip Path dir InstallPath } -type extraFilesZipGob struct { - Zip Path - Dir InstallPath -} - -func (e *extraFilesZip) ToGob() *extraFilesZipGob { - return &extraFilesZipGob{ - Zip: e.zip, - Dir: e.dir, - } -} - -func (e *extraFilesZip) FromGob(data *extraFilesZipGob) { - e.zip = data.Zip - e.dir = data.Dir -} - -func (e *extraFilesZip) GobEncode() ([]byte, error) { - return gobtools.CustomGobEncode[extraFilesZipGob](e) -} - -func (e *extraFilesZip) GobDecode(data []byte) error { - return gobtools.CustomGobDecode[extraFilesZipGob](data, e) -} - type katiInstalls []katiInstall // BuiltInstalled returns the katiInstalls in the form used by $(call copy-many-files) in Make, a @@ -2599,11 +2775,13 @@ func (m *ModuleBase) DecodeMultilib(ctx ConfigContext) (string, string) { } func (m *ModuleBase) Overrides() []string { - return m.commonProperties.Overrides + return m.baseProperties.Overrides } func (m *ModuleBase) UseGenericConfig() bool { - return proptools.Bool(m.commonProperties.Use_generic_config) + // Platform module installed in the device must use generic config by default + defaultUseGenericConfig := m.Platform() && !m.Host() && !m.InstallInRamdisk() && !m.InstallInVendorRamdisk() && !m.InstallInRecovery() + return proptools.BoolDefault(m.commonProperties.Use_generic_config, defaultUseGenericConfig) } type ConfigContext interface { @@ -2613,7 +2791,7 @@ type ConfigContext interface { type ConfigurableEvaluatorContext interface { OtherModuleProviderContext Config() Config - OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{}) + OtherModulePropertyErrorf(module ModuleOrProxy, property string, fmt string, args ...interface{}) HasMutatorFinished(mutatorName string) bool } @@ -2783,6 +2961,16 @@ func ModuleNameWithPossibleOverride(ctx BaseModuleContext) string { return ctx.ModuleName() } +// OtherModuleNameWithPossibleOverride returns the name of the OverrideModule that overrides the +// current variant of the given module, or ctx.ModuleName() if the given module is not an +// OverridableModule or if this variant is not overridden. +func OtherModuleNameWithPossibleOverride(ctx BaseModuleContext, m ModuleOrProxy) string { + if overrideInfo, ok := OtherModuleProvider(ctx, m, OverrideInfoProvider); ok && overrideInfo.OverriddenBy != "" { + return overrideInfo.OverriddenBy + } + return ctx.OtherModuleName(m) +} + // SrcIsModule decodes module references in the format ":unqualified-name" or "//namespace:name" // into the module name, or empty string if the input was not a module reference. func SrcIsModule(s string) (module string) { @@ -2911,7 +3099,7 @@ type SourceFileProducer interface { // OutputFilesForModule returns the output file paths with the given tag. On error, including if the // module produced zero paths, it reports errors to the ctx and returns nil. -func OutputFilesForModule(ctx PathContext, module Module, tag string) Paths { +func OutputFilesForModule(ctx PathContext, module ModuleOrProxy, tag string) Paths { paths, err := outputFilesForModule(ctx, module, tag) if err != nil { reportPathError(ctx, err) @@ -2924,7 +3112,7 @@ func OutputFilesForModule(ctx PathContext, module Module, tag string) Paths { // module produced zero or multiple paths, it reports errors to the ctx and returns nil. // TODO(b/397766191): Change the signature to take ModuleProxy // Please only access the module's internal data through providers. -func OutputFileForModule(ctx PathContext, module Module, tag string) Path { +func OutputFileForModule(ctx PathContext, module ModuleOrProxy, tag string) Path { paths, err := outputFilesForModule(ctx, module, tag) if err != nil { reportPathError(ctx, err) @@ -2933,7 +3121,7 @@ func OutputFileForModule(ctx PathContext, module Module, tag string) Path { if len(paths) == 0 { type addMissingDependenciesIntf interface { AddMissingDependencies([]string) - OtherModuleName(blueprint.Module) string + OtherModuleName(ModuleOrProxy) string } if mctx, ok := ctx.(addMissingDependenciesIntf); ok && ctx.Config().AllowMissingDependencies() { mctx.AddMissingDependencies([]string{mctx.OtherModuleName(module)}) @@ -2957,6 +3145,12 @@ func OutputFileForModule(ctx PathContext, module Module, tag string) Path { return paths[0] } +// OutputFilesForModuleOrErr is the same as OutputFilesForModule except that it returns the +// error instead of reporting it to the context +func OutputFilesForModuleOrErr(ctx PathContext, module ModuleOrProxy, tag string) (Paths, error) { + return outputFilesForModule(ctx, module, tag) +} + type OutputFilesProviderModuleContext interface { OtherModuleProviderContext Module() Module @@ -2965,7 +3159,7 @@ type OutputFilesProviderModuleContext interface { // TODO(b/397766191): Change the signature to take ModuleProxy // Please only access the module's internal data through providers. -func outputFilesForModule(ctx PathContext, module Module, tag string) (Paths, error) { +func outputFilesForModule(ctx PathContext, module ModuleOrProxy, tag string) (Paths, error) { outputFilesFromProvider, err := outputFilesForModuleFromProvider(ctx, module, tag) if outputFilesFromProvider != nil || err != OutputFilesProviderNotSet { return outputFilesFromProvider, err @@ -2995,7 +3189,7 @@ func outputFilesForModule(ctx PathContext, module Module, tag string) (Paths, er // from outputFiles property of module base, to avoid both setting and // reading OutputFilesProvider before GenerateBuildActions is finished. // If a module doesn't have the OutputFilesProvider, nil is returned. -func outputFilesForModuleFromProvider(ctx PathContext, module Module, tag string) (Paths, error) { +func outputFilesForModuleFromProvider(ctx PathContext, module ModuleOrProxy, tag string) (Paths, error) { var outputFiles OutputFilesInfo if mctx, isMctx := ctx.(OutputFilesProviderModuleContext); isMctx { @@ -3029,6 +3223,7 @@ func (o OutputFilesInfo) isEmpty() bool { return o.DefaultOutputFiles == nil && o.TaggedOutputFiles == nil } +// @auto-generate: gob type OutputFilesInfo struct { // default output files when tag is an empty string "" DefaultOutputFiles Paths @@ -3163,9 +3358,10 @@ func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) { hostCross bool } osDeps := map[osAndCross]Paths{} - ctx.VisitAllModules(func(module Module) { - if module.Enabled(ctx) { - key := osAndCross{os: module.Target().Os, hostCross: module.Target().HostCross} + ctx.VisitAllModuleProxies(func(module ModuleProxy) { + info := OtherModuleProviderOrDefault(ctx, module, CommonModuleInfoProvider) + if info.Enabled { + key := osAndCross{os: info.Target.Os, hostCross: info.Target.HostCross} osDeps[key] = append(osDeps[key], OtherModuleProviderOrDefault(ctx, module, InstallFilesProvider).CheckbuildFiles...) } }) @@ -3219,6 +3415,8 @@ type IdeInfo struct { Paths []string `json:"path,omitempty"` Static_libs []string `json:"static_libs,omitempty"` Libs []string `json:"libs,omitempty"` + Asset_dirs []string `json:"asset_dirs,omitempty"` + Resource_dirs []string `json:"resource_dirs,omitempty"` } // Merge merges two IdeInfos and produces a new one, leaving the origional unchanged @@ -3235,6 +3433,8 @@ func (i IdeInfo) Merge(other IdeInfo) IdeInfo { Paths: mergeStringLists(i.Paths, other.Paths), Static_libs: mergeStringLists(i.Static_libs, other.Static_libs), Libs: mergeStringLists(i.Libs, other.Libs), + Asset_dirs: mergeStringLists(i.Asset_dirs, other.Asset_dirs), + Resource_dirs: mergeStringLists(i.Resource_dirs, other.Resource_dirs), } } @@ -3250,3 +3450,9 @@ func CheckBlueprintSyntax(ctx BaseModuleContext, filename string, contents strin bpctx := ctx.blueprintBaseModuleContext() return blueprint.CheckBlueprintSyntax(bpctx.ModuleFactories(), filename, contents) } + +type HideApexVariantFromMakeInfo struct { + HideApexVariantFromMake bool +} + +var HideApexVariantFromMakeProvider = blueprint.NewProvider[HideApexVariantFromMakeInfo]() |
