diff options
Diffstat (limited to 'android')
-rw-r--r-- | android/Android.bp | 2 | ||||
-rw-r--r-- | android/androidmk.go | 18 | ||||
-rw-r--r-- | android/arch.go | 4 | ||||
-rw-r--r-- | android/arch_test.go | 4 | ||||
-rw-r--r-- | android/base_module_context.go | 2 | ||||
-rw-r--r-- | android/config.go | 4 | ||||
-rw-r--r-- | android/configurable_properties.go | 28 | ||||
-rw-r--r-- | android/early_module_context.go | 2 | ||||
-rw-r--r-- | android/gen_notice.go | 2 | ||||
-rw-r--r-- | android/license_metadata.go | 6 | ||||
-rw-r--r-- | android/logtags.go | 56 | ||||
-rw-r--r-- | android/makevars.go | 3 | ||||
-rw-r--r-- | android/module.go | 24 | ||||
-rw-r--r-- | android/module_context.go | 21 | ||||
-rw-r--r-- | android/mutator.go | 30 | ||||
-rw-r--r-- | android/override_module.go | 108 | ||||
-rw-r--r-- | android/packaging.go | 29 | ||||
-rw-r--r-- | android/paths.go | 36 | ||||
-rw-r--r-- | android/prebuilt.go | 6 | ||||
-rw-r--r-- | android/prebuilt_test.go | 2 | ||||
-rw-r--r-- | android/register.go | 3 | ||||
-rw-r--r-- | android/sdk_version.go | 7 | ||||
-rw-r--r-- | android/singleton.go | 2 | ||||
-rw-r--r-- | android/testing.go | 18 | ||||
-rw-r--r-- | android/variable.go | 10 |
25 files changed, 327 insertions, 100 deletions
diff --git a/android/Android.bp b/android/Android.bp index f130d3aee..9ce8cdcd2 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -41,6 +41,7 @@ bootstrap_go_package { "buildinfo_prop.go", "config.go", "test_config.go", + "configurable_properties.go", "configured_jars.go", "csuite_config.go", "deapexer.go", @@ -60,6 +61,7 @@ bootstrap_go_package { "license_metadata.go", "license_sdk_member.go", "licenses.go", + "logtags.go", "makevars.go", "metrics.go", "module.go", diff --git a/android/androidmk.go b/android/androidmk.go index 07f7c58d0..66f42f97c 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -36,6 +36,7 @@ import ( "github.com/google/blueprint" "github.com/google/blueprint/bootstrap" "github.com/google/blueprint/pathtools" + "github.com/google/blueprint/proptools" ) func init() { @@ -541,6 +542,11 @@ func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod blueprint a.SetPath("LOCAL_SOONG_INSTALLED_MODULE", base.katiInstalls[len(base.katiInstalls)-1].to) a.SetString("LOCAL_SOONG_INSTALL_PAIRS", base.katiInstalls.BuiltInstalled()) a.SetPaths("LOCAL_SOONG_INSTALL_SYMLINKS", base.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. + a.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", proptools.Bool(base.commonProperties.No_full_install)) } if len(base.testData) > 0 { @@ -849,7 +855,7 @@ func translateAndroidModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs * mod blueprint.Module, provider AndroidMkDataProvider) error { amod := mod.(Module).base() - if shouldSkipAndroidMkProcessing(amod) { + if shouldSkipAndroidMkProcessing(ctx, amod) { return nil } @@ -939,7 +945,7 @@ func WriteAndroidMkData(w io.Writer, data AndroidMkData) { func translateAndroidMkEntriesModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON, mod blueprint.Module, provider AndroidMkEntriesProvider) error { - if shouldSkipAndroidMkProcessing(mod.(Module).base()) { + if shouldSkipAndroidMkProcessing(ctx, mod.(Module).base()) { return nil } @@ -961,11 +967,11 @@ func translateAndroidMkEntriesModule(ctx SingletonContext, w io.Writer, moduleIn return nil } -func ShouldSkipAndroidMkProcessing(module Module) bool { - return shouldSkipAndroidMkProcessing(module.base()) +func ShouldSkipAndroidMkProcessing(ctx ConfigAndErrorContext, module Module) bool { + return shouldSkipAndroidMkProcessing(ctx, module.base()) } -func shouldSkipAndroidMkProcessing(module *ModuleBase) bool { +func shouldSkipAndroidMkProcessing(ctx ConfigAndErrorContext, module *ModuleBase) bool { if !module.commonProperties.NamespaceExportedToMake { // TODO(jeffrygaston) do we want to validate that there are no modules being // exported to Kati that depend on this module? @@ -984,7 +990,7 @@ func shouldSkipAndroidMkProcessing(module *ModuleBase) bool { return true } - return !module.Enabled() || + return !module.Enabled(ctx) || module.commonProperties.HideFromMake || // Make does not understand LinuxBionic module.Os() == LinuxBionic || diff --git a/android/arch.go b/android/arch.go index cd8882bbd..e0c6908c1 100644 --- a/android/arch.go +++ b/android/arch.go @@ -486,7 +486,7 @@ func osMutator(bpctx blueprint.BottomUpMutatorContext) { // dependencies on OsType variants that are explicitly disabled in their // properties. The CommonOS variant will still depend on disabled variants // if they are disabled afterwards, e.g. in archMutator if - if module.Enabled() { + if module.Enabled(mctx) { mctx.AddInterVariantDependency(commonOsToOsSpecificVariantTag, commonOSVariant, module) } } @@ -511,7 +511,7 @@ func GetOsSpecificVariantsOfCommonOSVariant(mctx BaseModuleContext) []Module { var variants []Module mctx.VisitDirectDeps(func(m Module) { if mctx.OtherModuleDependencyTag(m) == commonOsToOsSpecificVariantTag { - if m.Enabled() { + if m.Enabled(mctx) { variants = append(variants, m) } } diff --git a/android/arch_test.go b/android/arch_test.go index 5021a67af..f0a58a90b 100644 --- a/android/arch_test.go +++ b/android/arch_test.go @@ -423,7 +423,7 @@ func TestArchMutator(t *testing.T) { variants := ctx.ModuleVariantsForTests(name) for _, variant := range variants { m := ctx.ModuleForTests(name, variant) - if m.Module().Enabled() { + if m.Module().Enabled(PanickingConfigAndErrorContext(ctx)) { ret = append(ret, variant) } } @@ -533,7 +533,7 @@ func TestArchMutatorNativeBridge(t *testing.T) { variants := ctx.ModuleVariantsForTests(name) for _, variant := range variants { m := ctx.ModuleForTests(name, variant) - if m.Module().Enabled() { + if m.Module().Enabled(PanickingConfigAndErrorContext(ctx)) { ret = append(ret, variant) } } diff --git a/android/base_module_context.go b/android/base_module_context.go index c5fe58578..296352057 100644 --- a/android/base_module_context.go +++ b/android/base_module_context.go @@ -325,7 +325,7 @@ func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag b return nil } - if !aModule.Enabled() { + if !aModule.Enabled(b) { if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependency(aModule) { if b.Config().AllowMissingDependencies() { b.AddMissingDependencies([]string{b.OtherModuleName(aModule)}) diff --git a/android/config.go b/android/config.go index 3ea9d4dfa..f6711e61f 100644 --- a/android/config.go +++ b/android/config.go @@ -818,12 +818,12 @@ func (c *config) GetenvWithDefault(key string, defaultValue string) string { } func (c *config) IsEnvTrue(key string) bool { - value := c.Getenv(key) + value := strings.ToLower(c.Getenv(key)) return value == "1" || value == "y" || value == "yes" || value == "on" || value == "true" } func (c *config) IsEnvFalse(key string) bool { - value := c.Getenv(key) + value := strings.ToLower(c.Getenv(key)) return value == "0" || value == "n" || value == "no" || value == "off" || value == "false" } diff --git a/android/configurable_properties.go b/android/configurable_properties.go new file mode 100644 index 000000000..dad42fa1d --- /dev/null +++ b/android/configurable_properties.go @@ -0,0 +1,28 @@ +package android + +import "github.com/google/blueprint/proptools" + +// CreateSelectOsToBool is a utility function that makes it easy to create a +// Configurable property value that maps from os to a bool. Use an empty string +// to indicate a "default" case. +func CreateSelectOsToBool(cases map[string]*bool) proptools.Configurable[bool] { + var resultCases []proptools.ConfigurableCase[bool] + for pattern, value := range cases { + if pattern == "" { + resultCases = append(resultCases, proptools.NewConfigurableCase( + []proptools.ConfigurablePattern{proptools.NewDefaultConfigurablePattern()}, + value, + )) + } else { + resultCases = append(resultCases, proptools.NewConfigurableCase( + []proptools.ConfigurablePattern{proptools.NewStringConfigurablePattern(pattern)}, + value, + )) + } + } + + return proptools.NewConfigurable( + []proptools.ConfigurableCondition{proptools.NewConfigurableCondition("os", nil)}, + resultCases, + ) +} diff --git a/android/early_module_context.go b/android/early_module_context.go index cf1b5fcab..23f4c90a2 100644 --- a/android/early_module_context.go +++ b/android/early_module_context.go @@ -173,5 +173,5 @@ func (e *earlyModuleContext) Namespace() *Namespace { } func (e *earlyModuleContext) OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{}) { - e.EarlyModuleContext.OtherModulePropertyErrorf(module, property, fmt, args) + e.EarlyModuleContext.OtherModulePropertyErrorf(module, property, fmt, args...) } diff --git a/android/gen_notice.go b/android/gen_notice.go index 1acc638e8..6815f6467 100644 --- a/android/gen_notice.go +++ b/android/gen_notice.go @@ -62,7 +62,7 @@ func (s *genNoticeBuildRules) GenerateBuildActions(ctx SingletonContext) { if mod == nil { continue } - if !mod.Enabled() { // don't depend on variants without build rules + if !mod.Enabled(ctx) { // don't depend on variants without build rules continue } modules = append(modules, mod) diff --git a/android/license_metadata.go b/android/license_metadata.go index eabb1b170..3fea02909 100644 --- a/android/license_metadata.go +++ b/android/license_metadata.go @@ -36,7 +36,7 @@ var ( func buildLicenseMetadata(ctx ModuleContext, licenseMetadataFile WritablePath) { base := ctx.Module().base() - if !base.Enabled() { + if !base.Enabled(ctx) { return } @@ -69,7 +69,7 @@ func buildLicenseMetadata(ctx ModuleContext, licenseMetadataFile WritablePath) { if dep == nil { return } - if !dep.Enabled() { + if !dep.Enabled(ctx) { return } @@ -195,7 +195,7 @@ func isContainerFromFileExtensions(installPaths InstallPaths, builtPaths Paths) for _, path := range paths { switch path.Ext() { - case ".zip", ".tar", ".tgz", ".tar.gz", ".img", ".srcszip", ".apex": + case ".zip", ".tar", ".tgz", ".tar.gz", ".img", ".srcszip", ".apex", ".capex": return true } } diff --git a/android/logtags.go b/android/logtags.go new file mode 100644 index 000000000..d11cccf4f --- /dev/null +++ b/android/logtags.go @@ -0,0 +1,56 @@ +// Copyright 2024 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +import "github.com/google/blueprint" + +func init() { + RegisterParallelSingletonType("logtags", LogtagsSingleton) +} + +type LogtagsInfo struct { + Logtags Paths +} + +var LogtagsProviderKey = blueprint.NewProvider[*LogtagsInfo]() + +func LogtagsSingleton() Singleton { + return &logtagsSingleton{} +} + +type logtagsSingleton struct{} + +func MergedLogtagsPath(ctx PathContext) OutputPath { + return PathForIntermediates(ctx, "all-event-log-tags.txt") +} + +func (l *logtagsSingleton) GenerateBuildActions(ctx SingletonContext) { + var allLogtags Paths + ctx.VisitAllModules(func(module Module) { + if !module.ExportedToMake() { + return + } + if logtagsInfo, ok := SingletonModuleProvider(ctx, module, LogtagsProviderKey); ok { + allLogtags = append(allLogtags, logtagsInfo.Logtags...) + } + }) + + builder := NewRuleBuilder(pctx, ctx) + builder.Command(). + BuiltTool("merge-event-log-tags"). + FlagWithOutput("-o ", MergedLogtagsPath(ctx)). + Inputs(SortedUniquePaths(allLogtags)) + builder.Build("all-event-log-tags.txt", "merge logtags") +} diff --git a/android/makevars.go b/android/makevars.go index 4039e7edb..e73645fdc 100644 --- a/android/makevars.go +++ b/android/makevars.go @@ -98,6 +98,7 @@ type MakeVarsContext interface { BlueprintFile(module blueprint.Module) string ModuleErrorf(module blueprint.Module, format string, args ...interface{}) + OtherModulePropertyErrorf(module Module, property, format string, args ...interface{}) Errorf(format string, args ...interface{}) VisitAllModules(visit func(Module)) @@ -265,7 +266,7 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) { } ctx.VisitAllModules(func(m Module) { - if provider, ok := m.(ModuleMakeVarsProvider); ok && m.Enabled() { + if provider, ok := m.(ModuleMakeVarsProvider); ok && m.Enabled(ctx) { mctx := &makeVarsContext{ SingletonContext: ctx, } diff --git a/android/module.go b/android/module.go index effca0346..40a591007 100644 --- a/android/module.go +++ b/android/module.go @@ -60,7 +60,7 @@ type Module interface { base() *ModuleBase Disable() - Enabled() bool + Enabled(ctx ConfigAndErrorContext) bool Target() Target MultiTargets() []Target @@ -287,7 +287,7 @@ type commonProperties struct { // but are not usually required (e.g. superceded by a prebuilt) should not be // disabled as that will prevent them from being built by the checkbuild target // and so prevent early detection of changes that have broken those modules. - Enabled *bool `android:"arch_variant"` + Enabled proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"` // Controls the visibility of this module to other modules. Allowable values are one or more of // these formats: @@ -484,6 +484,11 @@ type commonProperties struct { // Set by osMutator. CommonOSVariant bool `blueprint:"mutated"` + // 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. + No_full_install *bool + // When HideFromMake is set to true, no entry for this variant will be emitted in the // generated Android.mk file. HideFromMake bool `blueprint:"mutated"` @@ -1392,14 +1397,11 @@ func (m *ModuleBase) PartitionTag(config DeviceConfig) string { return partition } -func (m *ModuleBase) Enabled() bool { +func (m *ModuleBase) Enabled(ctx ConfigAndErrorContext) bool { if m.commonProperties.ForcedDisabled { return false } - if m.commonProperties.Enabled == nil { - return !m.Os().DefaultDisabled - } - return *m.commonProperties.Enabled + return m.commonProperties.Enabled.GetOrDefault(m.ConfigurableEvaluator(ctx), !m.Os().DefaultDisabled) } func (m *ModuleBase) Disable() { @@ -1643,7 +1645,7 @@ 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(a) { + if !ctx.Config().KatiEnabled() || !shouldSkipAndroidMkProcessing(ctx, a) { allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...) } }) @@ -1835,7 +1837,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) checkDistProperties(ctx, fmt.Sprintf("dists[%d]", i), &m.distProperties.Dists[i]) } - if m.Enabled() { + if m.Enabled(ctx) { // ensure all direct android.Module deps are enabled ctx.VisitDirectDepsBlueprint(func(bm blueprint.Module) { if m, ok := bm.(Module); ok { @@ -2136,7 +2138,7 @@ func (m *ModuleBase) ConfigurableEvaluator(ctx ConfigAndErrorContext) proptools. } func (e configurationEvalutor) PropertyErrorf(property string, fmt string, args ...interface{}) { - e.ctx.OtherModulePropertyErrorf(e.m, property, fmt, args) + e.ctx.OtherModulePropertyErrorf(e.m, property, fmt, args...) } func (e configurationEvalutor) EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue { @@ -2535,7 +2537,7 @@ func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) { } osDeps := map[osAndCross]Paths{} ctx.VisitAllModules(func(module Module) { - if module.Enabled() { + if module.Enabled(ctx) { key := osAndCross{os: module.Target().Os, hostCross: module.Target().HostCross} osDeps[key] = append(osDeps[key], module.base().checkbuildFiles...) } diff --git a/android/module_context.go b/android/module_context.go index dea22bab4..605d3baeb 100644 --- a/android/module_context.go +++ b/android/module_context.go @@ -444,6 +444,21 @@ func (m *moduleContext) skipInstall() bool { return false } +// Tells whether this module is installed to the full install path (ex: +// out/target/product/<name>/<partition>) or not. If this returns false, the install build rule is +// not created and this module can only be installed to packaging modules like android_filesystem. +func (m *moduleContext) requiresFullInstall() bool { + if m.skipInstall() { + return false + } + + if proptools.Bool(m.module.base().commonProperties.No_full_install) { + return false + } + + return true +} + func (m *moduleContext) InstallFile(installPath InstallPath, name string, srcPath Path, deps ...InstallPath) InstallPath { return m.installFile(installPath, name, srcPath, deps, false, true, nil) @@ -490,7 +505,7 @@ func (m *moduleContext) installFile(installPath InstallPath, name string, srcPat m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, false) } - if !m.skipInstall() { + if m.requiresFullInstall() { deps = append(deps, InstallPaths(m.module.base().installFilesDepSet.ToList())...) deps = append(deps, m.module.base().installedInitRcPaths...) deps = append(deps, m.module.base().installedVintfFragmentsPaths...) @@ -563,7 +578,7 @@ func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, src if err != nil { panic(fmt.Sprintf("Unable to generate symlink between %q and %q: %s", fullInstallPath.Base(), srcPath.Base(), err)) } - if !m.skipInstall() { + if m.requiresFullInstall() { if m.Config().KatiEnabled() { // When creating the symlink rule in Soong but embedding in Make, write the rule to a @@ -612,7 +627,7 @@ func (m *moduleContext) InstallAbsoluteSymlink(installPath InstallPath, name str fullInstallPath := installPath.Join(m, name) m.module.base().hooks.runInstallHooks(m, nil, fullInstallPath, true) - if !m.skipInstall() { + if m.requiresFullInstall() { if m.Config().KatiEnabled() { // When creating the symlink rule in Soong but embedding in Make, write the rule to a // makefile instead of directly to the ninja file so that main.mk can add the diff --git a/android/mutator.go b/android/mutator.go index 75ba65048..440b9060f 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -293,15 +293,14 @@ type BottomUpMutatorContext interface { // WalkDeps, etc. AddInterVariantDependency(tag blueprint.DependencyTag, from, to blueprint.Module) - // ReplaceDependencies replaces all dependencies on the identical variant of the module with the - // specified name with the current variant of this module. Replacements don't take effect until - // after the mutator pass is finished. + // ReplaceDependencies finds all the variants of the module with the specified name, then + // replaces all dependencies onto those variants with the current variant of this module. + // Replacements don't take effect until after the mutator pass is finished. ReplaceDependencies(string) - // ReplaceDependencies replaces all dependencies on the identical variant of the module with the - // specified name with the current variant of this module as long as the supplied predicate returns - // true. - // + // ReplaceDependenciesIf finds all the variants of the module with the specified name, then + // replaces all dependencies onto those variants with the current variant of this module + // as long as the supplied predicate returns true. // Replacements don't take effect until after the mutator pass is finished. ReplaceDependenciesIf(string, blueprint.ReplaceDependencyPredicate) @@ -595,11 +594,16 @@ func (a *androidTransitionMutator) IncomingTransition(bpctx blueprint.IncomingTr func (a *androidTransitionMutator) Mutate(ctx blueprint.BottomUpMutatorContext, variation string) { if am, ok := ctx.Module().(Module); ok { + if variation != "" { + // TODO: this should really be checking whether the TransitionMutator affected this module, not + // the empty variant, but TransitionMutator has no concept of skipping a module. + base := am.base() + base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, a.name) + base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variation) + } + mctx := bottomUpMutatorContextFactory(ctx, am, a.finalPhase) defer bottomUpMutatorContextPool.Put(mctx) - base := am.base() - base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, a.name) - base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variation) a.mutator.Mutate(mctx, variation) } } @@ -674,13 +678,11 @@ func RegisterComponentsMutator(ctx RegisterMutatorsContext) { // on component modules to be added so that they can depend directly on a prebuilt // module. func componentDepsMutator(ctx BottomUpMutatorContext) { - if m := ctx.Module(); m.Enabled() { - m.ComponentDepsMutator(ctx) - } + ctx.Module().ComponentDepsMutator(ctx) } func depsMutator(ctx BottomUpMutatorContext) { - if m := ctx.Module(); m.Enabled() { + if m := ctx.Module(); m.Enabled(ctx) { m.base().baseDepsMutator(ctx) m.DepsMutator(ctx) } diff --git a/android/override_module.go b/android/override_module.go index 1341f537c..55f384f1f 100644 --- a/android/override_module.go +++ b/android/override_module.go @@ -28,6 +28,7 @@ package android // module based on it. import ( + "fmt" "sort" "sync" @@ -120,7 +121,7 @@ type OverridableModule interface { addOverride(o OverrideModule) getOverrides() []OverrideModule - override(ctx BaseModuleContext, m Module, o OverrideModule) + override(ctx BaseModuleContext, bm OverridableModule, o OverrideModule) GetOverriddenBy() string GetOverriddenByModuleDir() string @@ -191,15 +192,14 @@ func (b *OverridableModuleBase) setOverridesProperty(overridesProperty *[]string } // Overrides a base module with the given OverrideModule. -func (b *OverridableModuleBase) override(ctx BaseModuleContext, m Module, o OverrideModule) { - +func (b *OverridableModuleBase) override(ctx BaseModuleContext, bm OverridableModule, o OverrideModule) { for _, p := range b.overridableProperties { for _, op := range o.getOverridingProperties() { if proptools.TypeEqual(p, op) { err := proptools.ExtendProperties(p, op, nil, proptools.OrderReplace) if err != nil { if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok { - ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error()) + ctx.OtherModulePropertyErrorf(bm, propertyErr.Property, "%s", propertyErr.Err.Error()) } else { panic(err) } @@ -210,7 +210,7 @@ func (b *OverridableModuleBase) override(ctx BaseModuleContext, m Module, o Over // Adds the base module to the overrides property, if exists, of the overriding module. See the // comment on OverridableModuleBase.overridesProperty for details. if b.overridesProperty != nil { - *b.overridesProperty = append(*b.overridesProperty, ctx.ModuleName()) + *b.overridesProperty = append(*b.overridesProperty, ctx.OtherModuleName(bm)) } b.overridableModuleProperties.OverriddenBy = o.Name() b.overridableModuleProperties.OverriddenByModuleDir = o.ModuleDir() @@ -235,7 +235,7 @@ func (b *OverridableModuleBase) OverridablePropertiesDepsMutator(ctx BottomUpMut // to keep them in this order and not put any order mutators between them. func RegisterOverridePostDepsMutators(ctx RegisterMutatorsContext) { ctx.BottomUp("override_deps", overrideModuleDepsMutator).Parallel() - ctx.BottomUp("perform_override", performOverrideMutator).Parallel() + ctx.Transition("override", &overrideTransitionMutator{}) // overridableModuleDepsMutator calls OverridablePropertiesDepsMutator so that overridable modules can // add deps from overridable properties. ctx.BottomUp("overridable_deps", overridableModuleDepsMutator).Parallel() @@ -262,18 +262,6 @@ func overrideModuleDepsMutator(ctx BottomUpMutatorContext) { ctx.PropertyErrorf("base", "%q is not a valid module name", base) return } - // See if there's a prebuilt module that overrides this override module with prefer flag, - // in which case we call HideFromMake on the corresponding variant later. - ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(dep Module) { - prebuilt := GetEmbeddedPrebuilt(dep) - if prebuilt == nil { - panic("PrebuiltDepTag leads to a non-prebuilt module " + dep.Name()) - } - if prebuilt.UsePrebuilt() { - module.setOverriddenByPrebuilt(dep) - return - } - }) baseModule := ctx.AddDependency(ctx.Module(), overrideBaseDepTag, *module.getOverrideModuleProperties().Base)[0] if o, ok := baseModule.(OverridableModule); ok { overrideModule := ctx.Module().(OverrideModule) @@ -285,11 +273,13 @@ func overrideModuleDepsMutator(ctx BottomUpMutatorContext) { // Now, goes through all overridable modules, finds all modules overriding them, creates a local // variant for each of them, and performs the actual overriding operation by calling override(). -func performOverrideMutator(ctx BottomUpMutatorContext) { +type overrideTransitionMutator struct{} + +func (overrideTransitionMutator) Split(ctx BaseModuleContext) []string { if b, ok := ctx.Module().(OverridableModule); ok { overrides := b.getOverrides() if len(overrides) == 0 { - return + return []string{""} } variants := make([]string, len(overrides)+1) // The first variant is for the original, non-overridden, base module. @@ -297,32 +287,74 @@ func performOverrideMutator(ctx BottomUpMutatorContext) { for i, o := range overrides { variants[i+1] = o.(Module).Name() } - mods := ctx.CreateLocalVariations(variants...) - // Make the original variation the default one to depend on if no other override module variant - // is specified. - ctx.AliasVariation(variants[0]) - for i, o := range overrides { - mods[i+1].(OverridableModule).override(ctx, mods[i+1], o) - if prebuilt := o.getOverriddenByPrebuilt(); prebuilt != nil { - // The overriding module itself, too, is overridden by a prebuilt. - // Perform the same check for replacement - checkInvariantsForSourceAndPrebuilt(ctx, mods[i+1], prebuilt) - // Copy the flag and hide it in make - mods[i+1].ReplacedByPrebuilt() - } - } + return variants } else if o, ok := ctx.Module().(OverrideModule); ok { // Create a variant of the overriding module with its own name. This matches the above local // variant name rule for overridden modules, and thus allows ReplaceDependencies to match the // two. - ctx.CreateLocalVariations(o.Name()) - // To allow dependencies to be added without having to know the above variation. - ctx.AliasVariation(o.Name()) + return []string{o.Name()} + } + + return []string{""} +} + +func (overrideTransitionMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string { + if o, ok := ctx.Module().(OverrideModule); ok { + if ctx.DepTag() == overrideBaseDepTag { + return o.Name() + } + } + + // Variations are always local and shouldn't affect the variant used for dependencies + return "" +} + +func (overrideTransitionMutator) IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string { + if _, ok := ctx.Module().(OverridableModule); ok { + return incomingVariation + } else if o, ok := ctx.Module().(OverrideModule); ok { + // To allow dependencies to be added without having to know the variation. + return o.Name() + } + + return "" +} + +func (overrideTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) { + if o, ok := ctx.Module().(OverrideModule); ok { + overridableDeps := ctx.GetDirectDepsWithTag(overrideBaseDepTag) + if len(overridableDeps) > 1 { + panic(fmt.Errorf("expected a single dependency with overrideBaseDepTag, found %q", overridableDeps)) + } else if len(overridableDeps) == 1 { + b := overridableDeps[0].(OverridableModule) + b.override(ctx, b, o) + + checkPrebuiltReplacesOverride(ctx, b) + } + } +} + +func checkPrebuiltReplacesOverride(ctx BottomUpMutatorContext, b OverridableModule) { + // See if there's a prebuilt module that overrides this override module with prefer flag, + // in which case we call HideFromMake on the corresponding variant later. + prebuiltDeps := ctx.GetDirectDepsWithTag(PrebuiltDepTag) + for _, prebuiltDep := range prebuiltDeps { + prebuilt := GetEmbeddedPrebuilt(prebuiltDep) + if prebuilt == nil { + panic("PrebuiltDepTag leads to a non-prebuilt module " + prebuiltDep.Name()) + } + if prebuilt.UsePrebuilt() { + // The overriding module itself, too, is overridden by a prebuilt. + // Perform the same check for replacement + checkInvariantsForSourceAndPrebuilt(ctx, b, prebuiltDep) + // Copy the flag and hide it in make + b.ReplacedByPrebuilt() + } } } func overridableModuleDepsMutator(ctx BottomUpMutatorContext) { - if b, ok := ctx.Module().(OverridableModule); ok && b.Enabled() { + if b, ok := ctx.Module().(OverridableModule); ok && b.Enabled(ctx) { b.OverridablePropertiesDepsMutator(ctx) } } diff --git a/android/packaging.go b/android/packaging.go index 66772183c..fe61da1e9 100644 --- a/android/packaging.go +++ b/android/packaging.go @@ -50,6 +50,25 @@ type PackagingSpec struct { skipInstall bool } +func (p *PackagingSpec) Equals(other *PackagingSpec) bool { + if other == nil { + return false + } + if p.relPathInPackage != other.relPathInPackage { + return false + } + if p.srcPath != other.srcPath || p.symlinkTarget != other.symlinkTarget { + return false + } + if p.executable != other.executable { + return false + } + if p.partition != other.partition { + return false + } + return true +} + // Get file name of installed package func (p *PackagingSpec) FileName() string { if p.relPathInPackage != "" { @@ -243,9 +262,15 @@ func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter continue } } - if _, ok := m[ps.relPathInPackage]; !ok { - m[ps.relPathInPackage] = ps + dstPath := ps.relPathInPackage + if existingPs, ok := m[dstPath]; ok { + if !existingPs.Equals(&ps) { + ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps) + } + continue } + + m[dstPath] = ps } }) return m diff --git a/android/paths.go b/android/paths.go index 2b33f67ce..8d92aa4a9 100644 --- a/android/paths.go +++ b/android/paths.go @@ -60,6 +60,7 @@ type EarlyModulePathContext interface { ModuleDir() string ModuleErrorf(fmt string, args ...interface{}) + OtherModulePropertyErrorf(module Module, property, fmt string, args ...interface{}) } var _ EarlyModulePathContext = ModuleContext(nil) @@ -277,6 +278,7 @@ type WritablePath interface { type genPathProvider interface { genPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleGenPath + genPathWithExtAndTrimExt(ctx ModuleOutPathContext, subdir, ext string, trimExt string) ModuleGenPath } type objPathProvider interface { objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath @@ -295,6 +297,16 @@ func GenPathWithExt(ctx ModuleOutPathContext, subdir string, p Path, ext string) return PathForModuleGen(ctx) } +// GenPathWithExtAndTrimExt derives a new file path in ctx's generated sources directory +// from the current path, but with the new extension and trim the suffix. +func GenPathWithExtAndTrimExt(ctx ModuleOutPathContext, subdir string, p Path, ext string, trimExt string) ModuleGenPath { + if path, ok := p.(genPathProvider); ok { + return path.genPathWithExtAndTrimExt(ctx, subdir, ext, trimExt) + } + ReportPathErrorf(ctx, "Tried to create generated file from unsupported path: %s(%s)", reflect.TypeOf(p).Name(), p) + return PathForModuleGen(ctx) +} + // ObjPathWithExt derives a new file path in ctx's object directory from the // current path, but with the new extension. func ObjPathWithExt(ctx ModuleOutPathContext, subdir string, p Path, ext string) ModuleObjPath { @@ -550,7 +562,7 @@ func getPathsFromModuleDep(ctx ModuleWithDepsPathContext, path, moduleName, tag if module == nil { return nil, missingDependencyError{[]string{moduleName}} } - if aModule, ok := module.(Module); ok && !aModule.Enabled() { + if aModule, ok := module.(Module); ok && !aModule.Enabled(ctx) { return nil, missingDependencyError{[]string{moduleName}} } if outProducer, ok := module.(OutputFileProducer); ok { @@ -1507,6 +1519,17 @@ func (p SourcePath) genPathWithExt(ctx ModuleOutPathContext, subdir, ext string) return PathForModuleGen(ctx, subdir, pathtools.ReplaceExtension(p.path, ext)) } +func (p SourcePath) genPathWithExtAndTrimExt(ctx ModuleOutPathContext, subdir, ext string, trimExt string) ModuleGenPath { + // If Trim_extension being set, force append Output_extension without replace original extension. + if trimExt != "" { + if ext != "" { + return PathForModuleGen(ctx, subdir, strings.TrimSuffix(p.path, trimExt)+"."+ext) + } + return PathForModuleGen(ctx, subdir, strings.TrimSuffix(p.path, trimExt)) + } + return PathForModuleGen(ctx, subdir, pathtools.ReplaceExtension(p.path, ext)) +} + func (p SourcePath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath { return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext)) } @@ -1594,6 +1617,17 @@ func (p ModuleGenPath) genPathWithExt(ctx ModuleOutPathContext, subdir, ext stri return PathForModuleGen(ctx, subdir, pathtools.ReplaceExtension(p.path, ext)) } +func (p ModuleGenPath) genPathWithExtAndTrimExt(ctx ModuleOutPathContext, subdir, ext string, trimExt string) ModuleGenPath { + // If Trim_extension being set, force append Output_extension without replace original extension. + if trimExt != "" { + if ext != "" { + return PathForModuleGen(ctx, subdir, strings.TrimSuffix(p.path, trimExt)+"."+ext) + } + return PathForModuleGen(ctx, subdir, strings.TrimSuffix(p.path, trimExt)) + } + return PathForModuleGen(ctx, subdir, pathtools.ReplaceExtension(p.path, ext)) +} + func (p ModuleGenPath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath { return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext)) } diff --git a/android/prebuilt.go b/android/prebuilt.go index 2b7b55b5d..1f9b33111 100644 --- a/android/prebuilt.go +++ b/android/prebuilt.go @@ -275,7 +275,7 @@ func InitSingleSourcePrebuiltModule(module PrebuiltInterface, srcProps interface srcPropertyName := proptools.PropertyNameForField(srcField) srcsSupplier := func(ctx BaseModuleContext, _ Module) []string { - if !module.Enabled() { + if !module.Enabled(ctx) { return nil } value := srcPropsValue.FieldByIndex(srcFieldIndex) @@ -425,7 +425,7 @@ func PrebuiltSourceDepsMutator(ctx BottomUpMutatorContext) { m := ctx.Module() // If this module is a prebuilt, is enabled and has not been renamed to source then add a // dependency onto the source if it is present. - if p := GetEmbeddedPrebuilt(m); p != nil && m.Enabled() && !p.properties.PrebuiltRenamedToSource { + if p := GetEmbeddedPrebuilt(m); p != nil && m.Enabled(ctx) && !p.properties.PrebuiltRenamedToSource { bmn, _ := m.(baseModuleName) name := bmn.BaseModuleName() if ctx.OtherModuleReverseDependencyVariantExists(name) { @@ -702,7 +702,7 @@ func (p *Prebuilt) usePrebuilt(ctx BaseMutatorContext, source Module, prebuilt M } // If source is not available or is disabled then always use the prebuilt. - if source == nil || !source.Enabled() { + if source == nil || !source.Enabled(ctx) { return true } diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go index 575b9266c..d775ac356 100644 --- a/android/prebuilt_test.go +++ b/android/prebuilt_test.go @@ -351,7 +351,7 @@ func TestPrebuilts(t *testing.T) { } }) - moduleIsDisabled := !foo.Module().Enabled() + moduleIsDisabled := !foo.Module().Enabled(PanickingConfigAndErrorContext(result.TestContext)) deps := foo.Module().(*sourceModule).deps if moduleIsDisabled { if len(deps) > 0 { diff --git a/android/register.go b/android/register.go index d00c15fd0..aeb3b4c1b 100644 --- a/android/register.go +++ b/android/register.go @@ -16,8 +16,9 @@ package android import ( "fmt" - "github.com/google/blueprint" "reflect" + + "github.com/google/blueprint" ) // A sortable component is one whose registration order affects the order in which it is executed diff --git a/android/sdk_version.go b/android/sdk_version.go index b2ff960ee..01b55d0da 100644 --- a/android/sdk_version.go +++ b/android/sdk_version.go @@ -40,9 +40,15 @@ type SdkContext interface { // SdkKind represents a particular category of an SDK spec like public, system, test, etc. type SdkKind int +// These are generally ordered from the narrower sdk version to the wider sdk version, +// but not all entries have a strict subset/superset relationship. +// For example, SdkTest and SdkModule do not have a strict subset/superset relationship but both +// are supersets of SdkSystem. +// The general trend should be kept when an additional sdk kind is added. const ( SdkInvalid SdkKind = iota SdkNone + SdkToolchain // API surface provided by ART to compile other API domains SdkCore SdkCorePlatform SdkIntraCore // API surface provided by one core module to another @@ -53,7 +59,6 @@ const ( SdkModule SdkSystemServer SdkPrivate - SdkToolchain // API surface provided by ART to compile other API domains ) // String returns the string representation of this SdkKind diff --git a/android/singleton.go b/android/singleton.go index 76df1ebba..d364384e2 100644 --- a/android/singleton.go +++ b/android/singleton.go @@ -284,5 +284,5 @@ func (s *singletonContextAdaptor) moduleProvider(module blueprint.Module, provid } func (s *singletonContextAdaptor) OtherModulePropertyErrorf(module Module, property string, format string, args ...interface{}) { - s.blueprintSingletonContext().OtherModulePropertyErrorf(module, property, format, args) + s.blueprintSingletonContext().OtherModulePropertyErrorf(module, property, format, args...) } diff --git a/android/testing.go b/android/testing.go index 7b4411e2f..c692c7295 100644 --- a/android/testing.go +++ b/android/testing.go @@ -1287,3 +1287,21 @@ func EnsureListContainsSuffix(t *testing.T, result []string, expected string) { t.Errorf("%q is not found in %v", expected, result) } } + +type panickingConfigAndErrorContext struct { + ctx *TestContext +} + +func (ctx *panickingConfigAndErrorContext) OtherModulePropertyErrorf(module Module, property, fmt string, args ...interface{}) { + panic(ctx.ctx.PropertyErrorf(module, property, fmt, args...).Error()) +} + +func (ctx *panickingConfigAndErrorContext) Config() Config { + return ctx.ctx.Config() +} + +func PanickingConfigAndErrorContext(ctx *TestContext) ConfigAndErrorContext { + return &panickingConfigAndErrorContext{ + ctx: ctx, + } +} diff --git a/android/variable.go b/android/variable.go index 599f88e3f..419bd61de 100644 --- a/android/variable.go +++ b/android/variable.go @@ -58,16 +58,16 @@ type variableProperties struct { // unbundled_build is a catch-all property to annotate modules that don't build in one or // more unbundled branches, usually due to dependencies missing from the manifest. Unbundled_build struct { - Enabled *bool `android:"arch_variant"` + Enabled proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"` } `android:"arch_variant"` // similar to `Unbundled_build`, but `Always_use_prebuilt_sdks` means that it uses prebuilt // sdk specifically. Always_use_prebuilt_sdks struct { - Enabled *bool `android:"arch_variant"` + Enabled proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"` } `android:"arch_variant"` - Malloc_not_svelte struct { + Malloc_low_memory struct { Cflags []string `android:"arch_variant"` Shared_libs []string `android:"arch_variant"` Whole_static_libs []string `android:"arch_variant"` @@ -278,7 +278,7 @@ type ProductVariables struct { Unbundled_build_image *bool `json:",omitempty"` Always_use_prebuilt_sdks *bool `json:",omitempty"` Skip_boot_jars_check *bool `json:",omitempty"` - Malloc_not_svelte *bool `json:",omitempty"` + Malloc_low_memory *bool `json:",omitempty"` Malloc_zero_contents *bool `json:",omitempty"` Malloc_pattern_fill_contents *bool `json:",omitempty"` Safestack *bool `json:",omitempty"` @@ -612,7 +612,7 @@ func (v *ProductVariables) SetDefaultConfig() { AAPTCharacteristics: stringPtr("nosdcard"), AAPTPrebuiltDPI: []string{"xhdpi", "xxhdpi"}, - Malloc_not_svelte: boolPtr(true), + Malloc_low_memory: boolPtr(false), Malloc_zero_contents: boolPtr(true), Malloc_pattern_fill_contents: boolPtr(false), Safestack: boolPtr(false), |