diff options
109 files changed, 1506 insertions, 711 deletions
diff --git a/TEST_MAPPING b/TEST_MAPPING index 9f386ca49..6eabd7c14 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -3,5 +3,14 @@ { "path": "packages/modules/SdkExtensions" } + ], + + "postsubmit": [ + { + "name": "MicrodroidHostTestCases" + }, + { + "name": "MicrodroidTestApp" + } ] } diff --git a/android/Android.bp b/android/Android.bp index f0be44b5b..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", diff --git a/android/aconfig_providers.go b/android/aconfig_providers.go index 4c1782b8e..7317587fd 100644 --- a/android/aconfig_providers.go +++ b/android/aconfig_providers.go @@ -43,14 +43,6 @@ type AconfigDeclarationsProviderData struct { var AconfigDeclarationsProviderKey = blueprint.NewProvider[AconfigDeclarationsProviderData]() -// This is used to collect the aconfig declarations info on the transitive closure, -// the data is keyed on the container. -type AconfigTransitiveDeclarationsInfo struct { - AconfigFiles map[string]Paths -} - -var AconfigTransitiveDeclarationsInfoProvider = blueprint.NewProvider[AconfigTransitiveDeclarationsInfo]() - type ModeInfo struct { Container string Mode string @@ -80,54 +72,15 @@ func propagateModeInfos(ctx ModuleContext, module Module, to, from map[string]Mo } } -// CollectDependencyAconfigFiles is used by some module types to provide finer dependency graphing than -// we can do in ModuleBase. -func CollectDependencyAconfigFiles(ctx ModuleContext, mergedAconfigFiles *map[string]Paths) { - if *mergedAconfigFiles == nil { - *mergedAconfigFiles = make(map[string]Paths) - } - ctx.VisitDirectDepsIgnoreBlueprint(func(module Module) { - if dep, _ := OtherModuleProvider(ctx, module, AconfigDeclarationsProviderKey); dep.IntermediateCacheOutputPath != nil { - (*mergedAconfigFiles)[dep.Container] = append((*mergedAconfigFiles)[dep.Container], dep.IntermediateCacheOutputPath) - return - } - if dep, ok := OtherModuleProvider(ctx, module, aconfigPropagatingProviderKey); ok { - for container, v := range dep.AconfigFiles { - (*mergedAconfigFiles)[container] = append((*mergedAconfigFiles)[container], v...) - } - } - // We process these last, so that they determine the final value, eliminating any duplicates that we picked up - // from UpdateAndroidBuildActions. - if dep, ok := OtherModuleProvider(ctx, module, AconfigTransitiveDeclarationsInfoProvider); ok { - for container, v := range dep.AconfigFiles { - (*mergedAconfigFiles)[container] = append((*mergedAconfigFiles)[container], v...) - } - } - }) - - for _, container := range SortedKeys(*mergedAconfigFiles) { - aconfigFiles := (*mergedAconfigFiles)[container] - (*mergedAconfigFiles)[container] = mergeAconfigFiles(ctx, container, aconfigFiles, false) - } - - SetProvider(ctx, AconfigTransitiveDeclarationsInfoProvider, AconfigTransitiveDeclarationsInfo{ - AconfigFiles: *mergedAconfigFiles, - }) -} - -func SetAconfigFileMkEntries(m *ModuleBase, entries *AndroidMkEntries, aconfigFiles map[string]Paths) { - setAconfigFileMkEntries(m, entries, aconfigFiles) -} - type aconfigPropagatingDeclarationsInfo struct { AconfigFiles map[string]Paths ModeInfos map[string]ModeInfo } -var aconfigPropagatingProviderKey = blueprint.NewProvider[aconfigPropagatingDeclarationsInfo]() +var AconfigPropagatingProviderKey = blueprint.NewProvider[aconfigPropagatingDeclarationsInfo]() func VerifyAconfigBuildMode(ctx ModuleContext, container string, module blueprint.Module, asError bool) { - if dep, ok := OtherModuleProvider(ctx, module, aconfigPropagatingProviderKey); ok { + if dep, ok := OtherModuleProvider(ctx, module, AconfigPropagatingProviderKey); ok { for k, v := range dep.ModeInfos { msg := fmt.Sprintf("%s/%s depends on %s/%s/%s across containers\n", module.Name(), container, k, v.Container, v.Mode) @@ -159,17 +112,12 @@ func aconfigUpdateAndroidBuildActions(ctx ModuleContext) { if dep, ok := OtherModuleProvider(ctx, module, AconfigDeclarationsProviderKey); ok { mergedAconfigFiles[dep.Container] = append(mergedAconfigFiles[dep.Container], dep.IntermediateCacheOutputPath) } - if dep, ok := OtherModuleProvider(ctx, module, aconfigPropagatingProviderKey); ok { + if dep, ok := OtherModuleProvider(ctx, module, AconfigPropagatingProviderKey); ok { for container, v := range dep.AconfigFiles { mergedAconfigFiles[container] = append(mergedAconfigFiles[container], v...) } propagateModeInfos(ctx, module, mergedModeInfos, dep.ModeInfos) } - if dep, ok := OtherModuleProvider(ctx, module, AconfigTransitiveDeclarationsInfoProvider); ok { - for container, v := range dep.AconfigFiles { - mergedAconfigFiles[container] = append(mergedAconfigFiles[container], v...) - } - } }) // We only need to set the provider if we have aconfig files. if len(mergedAconfigFiles) > 0 { @@ -178,7 +126,7 @@ func aconfigUpdateAndroidBuildActions(ctx ModuleContext) { mergedAconfigFiles[container] = mergeAconfigFiles(ctx, container, aconfigFiles, true) } - SetProvider(ctx, aconfigPropagatingProviderKey, aconfigPropagatingDeclarationsInfo{ + SetProvider(ctx, AconfigPropagatingProviderKey, aconfigPropagatingDeclarationsInfo{ AconfigFiles: mergedAconfigFiles, ModeInfos: mergedModeInfos, }) @@ -186,7 +134,7 @@ func aconfigUpdateAndroidBuildActions(ctx ModuleContext) { } func aconfigUpdateAndroidMkData(ctx fillInEntriesContext, mod Module, data *AndroidMkData) { - info, ok := SingletonModuleProvider(ctx, mod, aconfigPropagatingProviderKey) + info, ok := SingletonModuleProvider(ctx, mod, AconfigPropagatingProviderKey) // If there is no aconfigPropagatingProvider, or there are no AconfigFiles, then we are done. if !ok || len(info.AconfigFiles) == 0 { return @@ -217,7 +165,7 @@ func aconfigUpdateAndroidMkEntries(ctx fillInEntriesContext, mod Module, entries if len(*entries) == 0 { return } - info, ok := SingletonModuleProvider(ctx, mod, aconfigPropagatingProviderKey) + info, ok := SingletonModuleProvider(ctx, mod, AconfigPropagatingProviderKey) if !ok || len(info.AconfigFiles) == 0 { return } @@ -225,7 +173,7 @@ func aconfigUpdateAndroidMkEntries(ctx fillInEntriesContext, mod Module, entries for idx, _ := range *entries { (*entries)[idx].ExtraEntries = append((*entries)[idx].ExtraEntries, func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries) { - setAconfigFileMkEntries(mod.base(), entries, info.AconfigFiles) + entries.AddPaths("LOCAL_ACONFIG_FILES", getAconfigFilePaths(mod.base(), info.AconfigFiles)) }, ) @@ -255,10 +203,6 @@ func mergeAconfigFiles(ctx ModuleContext, container string, inputs Paths, genera return Paths{output} } -func setAconfigFileMkEntries(m *ModuleBase, entries *AndroidMkEntries, aconfigFiles map[string]Paths) { - entries.AddPaths("LOCAL_ACONFIG_FILES", getAconfigFilePaths(m, aconfigFiles)) -} - func getAconfigFilePaths(m *ModuleBase, aconfigFiles map[string]Paths) (paths Paths) { // TODO(b/311155208): The default container here should be system. container := "system" diff --git a/android/androidmk.go b/android/androidmk.go index 53f06091c..66f42f97c 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -855,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 } @@ -945,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 } @@ -967,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? @@ -990,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/apex_contributions.go b/android/apex_contributions.go index f5c50d386..91549e5d8 100644 --- a/android/apex_contributions.go +++ b/android/apex_contributions.go @@ -101,12 +101,12 @@ type apexContributionsDepTag struct { } var ( - acDepTag = apexContributionsDepTag{} + AcDepTag = apexContributionsDepTag{} ) // Creates a dep to each selected apex_contributions func (a *allApexContributions) DepsMutator(ctx BottomUpMutatorContext) { - ctx.AddDependency(ctx.Module(), acDepTag, ctx.Config().AllApexContributions()...) + ctx.AddDependency(ctx.Module(), AcDepTag, ctx.Config().AllApexContributions()...) } // Set PrebuiltSelectionInfoProvider in post deps phase @@ -131,7 +131,7 @@ func (a *allApexContributions) SetPrebuiltSelectionInfoProvider(ctx BaseModuleCo // (e.g. shiba and shiba_fullmte) // Eventually these product variants will have their own release config maps. if !proptools.Bool(ctx.Config().BuildIgnoreApexContributionContents()) { - ctx.VisitDirectDepsWithTag(acDepTag, func(child Module) { + ctx.VisitDirectDepsWithTag(AcDepTag, func(child Module) { if m, ok := child.(*apexContributions); ok { addContentsToProvider(&p, m) } else { 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..550600052 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)}) @@ -536,7 +536,7 @@ func IsMetaDependencyTag(tag blueprint.DependencyTag) bool { return true } else if tag == licensesTag { return true - } else if tag == acDepTag { + } else if tag == AcDepTag { return true } return false diff --git a/android/config.go b/android/config.go index f6711e61f..76c590ad9 100644 --- a/android/config.go +++ b/android/config.go @@ -2109,6 +2109,7 @@ var ( "RELEASE_APEX_CONTRIBUTIONS_NEURALNETWORKS", "RELEASE_APEX_CONTRIBUTIONS_ONDEVICEPERSONALIZATION", "RELEASE_APEX_CONTRIBUTIONS_PERMISSION", + "RELEASE_APEX_CONTRIBUTIONS_PRIMARY_LIBS", "RELEASE_APEX_CONTRIBUTIONS_REMOTEKEYPROVISIONING", "RELEASE_APEX_CONTRIBUTIONS_RESOLV", "RELEASE_APEX_CONTRIBUTIONS_SCHEDULING", 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/deptag.go b/android/deptag.go index c7ba4d36f..77b9d6114 100644 --- a/android/deptag.go +++ b/android/deptag.go @@ -44,6 +44,21 @@ func IsInstallDepNeededTag(tag blueprint.DependencyTag) bool { return false } +// Dependency tags can implement this interface and return true from SkipToTransitiveDeps to +// annotate that this dependency isn't installed, but its transitive dependencies are. This is +// useful when a module is built into another module (ex: static linking) but the module still has +// runtime dependencies. +type SkipToTransitiveDepsTag interface { + SkipToTransitiveDeps() bool +} + +func IsSkipToTransitiveDepsTag(tag blueprint.DependencyTag) bool { + if i, ok := tag.(SkipToTransitiveDepsTag); ok { + return i.SkipToTransitiveDeps() + } + return false +} + type PropagateAconfigValidationDependencyTag interface { PropagateAconfigValidation() bool } 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/filegroup.go b/android/filegroup.go index 86d7b4bbd..a8326d46a 100644 --- a/android/filegroup.go +++ b/android/filegroup.go @@ -56,9 +56,6 @@ type fileGroup struct { DefaultableModuleBase properties fileGroupProperties srcs Paths - - // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo - mergedAconfigFiles map[string]Paths } var _ SourceFileProducer = (*fileGroup)(nil) @@ -97,7 +94,6 @@ func (fg *fileGroup) GenerateAndroidBuildActions(ctx ModuleContext) { fg.srcs = PathsWithModuleSrcSubDir(ctx, fg.srcs, String(fg.properties.Path)) } SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: fg.srcs.Strings()}) - CollectDependencyAconfigFiles(ctx, &fg.mergedAconfigFiles) var aconfigDeclarations []string var intermediateCacheOutputPaths Paths 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 0cb6c96e6..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 } diff --git a/android/makevars.go b/android/makevars.go index 4039e7edb..b6bc14e8f 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, } @@ -472,7 +473,7 @@ func (s *makeVarsSingleton) writeInstalls(installs, symlinks, katiVintfManifestI # Values written by Soong to generate install rules that can be amended by Kati. - +EXTRA_INSTALL_ZIPS := `) preserveSymlinksFlag := "-d" @@ -506,9 +507,12 @@ func (s *makeVarsSingleton) writeInstalls(installs, symlinks, katiVintfManifestI if extraFiles := install.extraFiles; extraFiles != nil { fmt.Fprintf(buf, "\t( unzip -qDD -d '%s' '%s' 2>&1 | grep -v \"zipfile is empty\"; exit $${PIPESTATUS[0]} ) || \\\n", extraFiles.dir.String(), extraFiles.zip.String()) fmt.Fprintf(buf, "\t ( code=$$?; if [ $$code -ne 0 -a $$code -ne 1 ]; then exit $$code; fi )\n") + fmt.Fprintf(buf, "EXTRA_INSTALL_ZIPS += %s:%s\n", extraFiles.dir.String(), extraFiles.zip.String()) } + fmt.Fprintln(buf) } + fmt.Fprintf(buf, ".KATI_READONLY := EXTRA_INSTALL_ZIPS\n") for _, symlink := range symlinks { fmt.Fprintf(buf, "%s:", symlink.to.String()) diff --git a/android/module.go b/android/module.go index f8fec3a89..d7f0537f7 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: @@ -1397,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() { @@ -1473,15 +1470,27 @@ func (m *ModuleBase) computeInstallDeps(ctx ModuleContext) ([]*DepSet[InstallPat var installDeps []*DepSet[InstallPath] var packagingSpecs []*DepSet[PackagingSpec] ctx.VisitDirectDeps(func(dep Module) { - if isInstallDepNeeded(dep, ctx.OtherModuleDependencyTag(dep)) { + depTag := ctx.OtherModuleDependencyTag(dep) + // If this is true, the direct outputs from the module is not gathered, but its + // transitive deps are still gathered. + skipToTransitive := IsSkipToTransitiveDepsTag(depTag) + if isInstallDepNeeded(dep, depTag) || skipToTransitive { // Installation is still handled by Make, so anything hidden from Make is not // installable. if !dep.IsHideFromMake() && !dep.IsSkipInstall() { - installDeps = append(installDeps, dep.base().installFilesDepSet) + if skipToTransitive { + installDeps = append(installDeps, dep.base().installFilesDepSet.transitive...) + } else { + installDeps = append(installDeps, dep.base().installFilesDepSet) + } } // Add packaging deps even when the dependency is not installed so that uninstallable // modules can still be packaged. Often the package will be installed instead. - packagingSpecs = append(packagingSpecs, dep.base().packagingSpecsDepSet) + if skipToTransitive { + packagingSpecs = append(packagingSpecs, dep.base().packagingSpecsDepSet.transitive...) + } else { + packagingSpecs = append(packagingSpecs, dep.base().packagingSpecsDepSet) + } } }) @@ -1648,7 +1657,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...) } }) @@ -1840,7 +1849,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 { @@ -1895,12 +1904,14 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) } } - m.module.GenerateAndroidBuildActions(ctx) + // Call aconfigUpdateAndroidBuildActions to collect merged aconfig files before being used + // in m.module.GenerateAndroidBuildActions + aconfigUpdateAndroidBuildActions(ctx) if ctx.Failed() { return } - aconfigUpdateAndroidBuildActions(ctx) + m.module.GenerateAndroidBuildActions(ctx) if ctx.Failed() { return } @@ -2141,16 +2152,16 @@ 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 { ctx := e.ctx m := e.m switch condition.FunctionName() { - case "release_variable": + case "release_flag": if condition.NumArgs() != 1 { - ctx.OtherModulePropertyErrorf(m, property, "release_variable requires 1 argument, found %d", condition.NumArgs()) + ctx.OtherModulePropertyErrorf(m, property, "release_flag requires 1 argument, found %d", condition.NumArgs()) return proptools.ConfigurableValueUndefined() } if v, ok := ctx.Config().productVariables.BuildFlags[condition.Arg(0)]; ok { @@ -2540,7 +2551,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/mutator.go b/android/mutator.go index 9cfdb60dc..440b9060f 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -678,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 163f7b7a9..21cf38125 100644 --- a/android/override_module.go +++ b/android/override_module.go @@ -28,7 +28,6 @@ package android // module based on it. import ( - "fmt" "sort" "sync" @@ -121,7 +120,7 @@ type OverridableModule interface { addOverride(o OverrideModule) getOverrides() []OverrideModule - override(ctx BaseModuleContext, bm OverridableModule, o OverrideModule) + override(ctx BaseModuleContext, m Module, o OverrideModule) GetOverriddenBy() string GetOverriddenByModuleDir() string @@ -192,14 +191,15 @@ func (b *OverridableModuleBase) setOverridesProperty(overridesProperty *[]string } // Overrides a base module with the given OverrideModule. -func (b *OverridableModuleBase) override(ctx BaseModuleContext, bm OverridableModule, o OverrideModule) { +func (b *OverridableModuleBase) override(ctx BaseModuleContext, m Module, 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.OtherModulePropertyErrorf(bm, propertyErr.Property, "%s", propertyErr.Err.Error()) + ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error()) } else { panic(err) } @@ -210,7 +210,7 @@ func (b *OverridableModuleBase) override(ctx BaseModuleContext, bm OverridableMo // 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.OtherModuleName(bm)) + *b.overridesProperty = append(*b.overridesProperty, ctx.ModuleName()) } 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.Transition("override", &overrideTransitionMutator{}) + ctx.BottomUp("perform_override", performOverrideMutator).Parallel() // overridableModuleDepsMutator calls OverridablePropertiesDepsMutator so that overridable modules can // add deps from overridable properties. ctx.BottomUp("overridable_deps", overridableModuleDepsMutator).Parallel() @@ -262,6 +262,18 @@ 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) @@ -273,13 +285,11 @@ 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(). -type overrideTransitionMutator struct{} - -func (overrideTransitionMutator) Split(ctx BaseModuleContext) []string { +func performOverrideMutator(ctx BottomUpMutatorContext) { if b, ok := ctx.Module().(OverridableModule); ok { overrides := b.getOverrides() if len(overrides) == 0 { - return []string{""} + return } variants := make([]string, len(overrides)+1) // The first variant is for the original, non-overridden, base module. @@ -287,74 +297,32 @@ func (overrideTransitionMutator) Split(ctx BaseModuleContext) []string { for i, o := range overrides { variants[i+1] = o.(Module).Name() } - return variants + 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() + } + } } 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. - 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() - } + ctx.CreateLocalVariations(o.Name()) + // To allow dependencies to be added without having to know the above variation. + ctx.AliasVariation(o.Name()) } } 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_test.go b/android/packaging_test.go index 383343723..4b72c24f9 100644 --- a/android/packaging_test.go +++ b/android/packaging_test.go @@ -25,8 +25,9 @@ import ( type componentTestModule struct { ModuleBase props struct { - Deps []string - Skip_install *bool + Deps []string + Build_only_deps []string + Skip_install *bool } } @@ -36,6 +37,18 @@ type installDepTag struct { InstallAlwaysNeededDependencyTag } +// dep tag for build_only_deps +type buildOnlyDepTag struct { + blueprint.BaseDependencyTag + InstallAlwaysNeededDependencyTag +} + +var _ SkipToTransitiveDepsTag = (*buildOnlyDepTag)(nil) + +func (tag buildOnlyDepTag) SkipToTransitiveDeps() bool { + return true +} + func componentTestModuleFactory() Module { m := &componentTestModule{} m.AddProperties(&m.props) @@ -45,6 +58,7 @@ func componentTestModuleFactory() Module { func (m *componentTestModule) DepsMutator(ctx BottomUpMutatorContext) { ctx.AddDependency(ctx.Module(), installDepTag{}, m.props.Deps...) + ctx.AddDependency(ctx.Module(), buildOnlyDepTag{}, m.props.Build_only_deps...) } func (m *componentTestModule) GenerateAndroidBuildActions(ctx ModuleContext) { @@ -398,3 +412,30 @@ func TestPackagingWithSkipInstallDeps(t *testing.T) { } `, []string{"lib64/foo", "lib64/bar", "lib64/baz"}) } + +func TestPackagingWithSkipToTransitvDeps(t *testing.T) { + // packag -[deps]-> foo -[build_only_deps]-> bar -[deps]-> baz + // bar isn't installed, but it brings baz to its parent. + multiTarget := false + runPackagingTest(t, multiTarget, + ` + component { + name: "foo", + build_only_deps: ["bar"], + } + + component { + name: "bar", + deps: ["baz"], + } + + component { + name: "baz", + } + + package_module { + name: "package", + deps: ["foo"], + } + `, []string{"lib64/foo", "lib64/baz"}) +} diff --git a/android/paths.go b/android/paths.go index 39b660cce..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) @@ -561,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 { diff --git a/android/prebuilt.go b/android/prebuilt.go index 2b7b55b5d..51b86a56f 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) { @@ -437,7 +437,7 @@ func PrebuiltSourceDepsMutator(ctx BottomUpMutatorContext) { // TODO: When all branches contain this singleton module, make this strict // TODO: Add this dependency only for mainline prebuilts and not every prebuilt module if ctx.OtherModuleExists("all_apex_contributions") { - ctx.AddDependency(m, acDepTag, "all_apex_contributions") + ctx.AddDependency(m, AcDepTag, "all_apex_contributions") } } @@ -474,7 +474,7 @@ func PrebuiltSelectModuleMutator(ctx BottomUpMutatorContext) { } // Propagate the provider received from `all_apex_contributions` // to the source module - ctx.VisitDirectDepsWithTag(acDepTag, func(am Module) { + ctx.VisitDirectDepsWithTag(AcDepTag, func(am Module) { psi, _ := OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider) SetProvider(ctx, PrebuiltSelectionInfoProvider, psi) }) @@ -580,7 +580,7 @@ func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) { bmn, _ := m.(baseModuleName) name := bmn.BaseModuleName() psi := PrebuiltSelectionInfoMap{} - ctx.VisitDirectDepsWithTag(acDepTag, func(am Module) { + ctx.VisitDirectDepsWithTag(AcDepTag, func(am Module) { psi, _ = OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider) }) @@ -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/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..6518f4a53 100644 --- a/android/testing.go +++ b/android/testing.go @@ -1122,7 +1122,7 @@ func AndroidMkEntriesForTest(t *testing.T, ctx *TestContext, mod blueprint.Modul entriesList := p.AndroidMkEntries() aconfigUpdateAndroidMkEntries(ctx, mod.(Module), &entriesList) - for i, _ := range entriesList { + for i := range entriesList { entriesList[i].fillInEntries(ctx, mod) } return entriesList @@ -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 2649fbd6f..419bd61de 100644 --- a/android/variable.go +++ b/android/variable.go @@ -58,13 +58,13 @@ 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_low_memory struct { diff --git a/apex/apex.go b/apex/apex.go index ef57d7efc..9a80ec633 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -490,9 +490,6 @@ type apexBundle struct { javaApisUsedByModuleFile android.ModuleOutPath aconfigFiles []android.Path - - // Single aconfig "cache file" merged from this module and all dependencies. - mergedAconfigFiles map[string]android.Paths } // apexFileClass represents a type of file that can be included in APEX. @@ -1077,7 +1074,7 @@ type ApexInfoMutator interface { // specific variant to modules that support the ApexInfoMutator. // It also propagates updatable=true to apps of updatable apexes func apexInfoMutator(mctx android.TopDownMutatorContext) { - if !mctx.Module().Enabled() { + if !mctx.Module().Enabled(mctx) { return } @@ -1094,7 +1091,7 @@ func apexInfoMutator(mctx android.TopDownMutatorContext) { // apexStrictUpdatibilityLintMutator propagates strict_updatability_linting to transitive deps of a mainline module // This check is enforced for updatable modules func apexStrictUpdatibilityLintMutator(mctx android.TopDownMutatorContext) { - if !mctx.Module().Enabled() { + if !mctx.Module().Enabled(mctx) { return } if apex, ok := mctx.Module().(*apexBundle); ok && apex.checkStrictUpdatabilityLinting() { @@ -1121,7 +1118,7 @@ func apexStrictUpdatibilityLintMutator(mctx android.TopDownMutatorContext) { // enforceAppUpdatability propagates updatable=true to apps of updatable apexes func enforceAppUpdatability(mctx android.TopDownMutatorContext) { - if !mctx.Module().Enabled() { + if !mctx.Module().Enabled(mctx) { return } if apex, ok := mctx.Module().(*apexBundle); ok && apex.Updatable() { @@ -1199,7 +1196,7 @@ func (a *apexBundle) checkStrictUpdatabilityLinting() bool { // unique apex variations for this module. See android/apex.go for more about unique apex variant. // TODO(jiyong): move this to android/apex.go? func apexUniqueVariationsMutator(mctx android.BottomUpMutatorContext) { - if !mctx.Module().Enabled() { + if !mctx.Module().Enabled(mctx) { return } if am, ok := mctx.Module().(android.ApexModule); ok { @@ -1211,7 +1208,7 @@ func apexUniqueVariationsMutator(mctx android.BottomUpMutatorContext) { // the apex in order to retrieve its contents later. // TODO(jiyong): move this to android/apex.go? func apexTestForDepsMutator(mctx android.BottomUpMutatorContext) { - if !mctx.Module().Enabled() { + if !mctx.Module().Enabled(mctx) { return } if am, ok := mctx.Module().(android.ApexModule); ok { @@ -1226,7 +1223,7 @@ func apexTestForDepsMutator(mctx android.BottomUpMutatorContext) { // TODO(jiyong): move this to android/apex.go? func apexTestForMutator(mctx android.BottomUpMutatorContext) { - if !mctx.Module().Enabled() { + if !mctx.Module().Enabled(mctx) { return } if _, ok := mctx.Module().(android.ApexModule); ok { @@ -1340,7 +1337,7 @@ func apexModuleTypeRequiresVariant(module ApexInfoMutator) bool { // See android.UpdateDirectlyInAnyApex // TODO(jiyong): move this to android/apex.go? func apexDirectlyInAnyMutator(mctx android.BottomUpMutatorContext) { - if !mctx.Module().Enabled() { + if !mctx.Module().Enabled(mctx) { return } if am, ok := mctx.Module().(android.ApexModule); ok { @@ -1677,7 +1674,13 @@ func apexFileForJavaModuleWithFile(ctx android.BaseModuleContext, module javaMod af.jacocoReportClassesFile = module.JacocoReportClassesFile() af.lintDepSets = module.LintDepSets() af.customStem = module.Stem() + ".jar" - if dexpreopter, ok := module.(java.DexpreopterInterface); ok { + // TODO: b/338641779 - Remove special casing of sdkLibrary once bcpf and sscpf depends + // on the implementation library + if sdkLib, ok := module.(*java.SdkLibrary); ok { + for _, install := range sdkLib.BuiltInstalledForApex() { + af.requiredModuleNames = append(af.requiredModuleNames, install.FullModuleName()) + } + } else if dexpreopter, ok := module.(java.DexpreopterInterface); ok { for _, install := range dexpreopter.DexpreoptBuiltInstalledForApex() { af.requiredModuleNames = append(af.requiredModuleNames, install.FullModuleName()) } @@ -1968,7 +1971,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok { return false } - if mod, ok := child.(android.Module); ok && !mod.Enabled() { + if mod, ok := child.(android.Module); ok && !mod.Enabled(ctx) { return false } depName := ctx.OtherModuleName(child) @@ -2320,7 +2323,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, } func addAconfigFiles(vctx *visitorContext, ctx android.ModuleContext, module blueprint.Module) { - if dep, ok := android.OtherModuleProvider(ctx, module, android.AconfigTransitiveDeclarationsInfoProvider); ok { + if dep, ok := android.OtherModuleProvider(ctx, module, android.AconfigPropagatingProviderKey); ok { if len(dep.AconfigFiles) > 0 && dep.AconfigFiles[ctx.ModuleName()] != nil { vctx.aconfigFiles = append(vctx.aconfigFiles, dep.AconfigFiles[ctx.ModuleName()]...) } @@ -2408,7 +2411,6 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { return } } - android.CollectDependencyAconfigFiles(ctx, &a.mergedAconfigFiles) //////////////////////////////////////////////////////////////////////////////////////////// // 3) some fields in apexBundle struct are configured @@ -2580,9 +2582,6 @@ func BundleFactory() android.Module { type Defaults struct { android.ModuleBase android.DefaultsModuleBase - - // Single aconfig "cache file" merged from this module and all dependencies. - mergedAconfigFiles map[string]android.Paths } // apex_defaults provides defaultable properties to other apex modules. @@ -2605,10 +2604,6 @@ type OverrideApex struct { android.OverrideModuleBase } -func (d *Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) { - android.CollectDependencyAconfigFiles(ctx, &d.mergedAconfigFiles) -} - func (o *OverrideApex) GenerateAndroidBuildActions(_ android.ModuleContext) { // All the overrides happen in the base module. } diff --git a/apex/apex_test.go b/apex/apex_test.go index 0b26f16c6..9a5c2b49b 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -5601,8 +5601,21 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { compile_dex: true, } ` + // This test disables libbar, which causes the ComponentDepsMutator to add + // deps on libbar.stubs and other sub-modules that don't exist. We can + // enable AllowMissingDependencies to work around that, but enabling that + // causes extra checks for missing source files to dex_bootjars, so add those + // to the mock fs as well. + preparer2 := android.GroupFixturePreparers( + preparer, + android.PrepareForTestWithAllowMissingDependencies, + android.FixtureMergeMockFs(map[string][]byte{ + "build/soong/scripts/check_boot_jars/package_allowed_list.txt": nil, + "frameworks/base/config/boot-profile.txt": nil, + }), + ) - ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment) + ctx := testDexpreoptWithApexes(t, bp, "", preparer2, fragment) checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar") @@ -7146,7 +7159,7 @@ func TestJavaSDKLibrary_WithinApex(t *testing.T) { // The bar library should depend on the implementation jar. barLibrary := ctx.ModuleForTests("bar", "android_common_myapex").Rule("javac") - if expected, actual := `^-classpath [^:]*/turbine-combined/foo\.impl\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) { + if expected, actual := `^-classpath [^:]*/turbine-combined/foo\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) { t.Errorf("expected %q, found %#q", expected, actual) } } @@ -7287,7 +7300,7 @@ func TestJavaSDKLibrary_ImportPreferred(t *testing.T) { // The bar library should depend on the implementation jar. barLibrary := ctx.ModuleForTests("bar", "android_common_myapex").Rule("javac") - if expected, actual := `^-classpath [^:]*/turbine-combined/foo\.impl\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) { + if expected, actual := `^-classpath [^:]*/turbine-combined/foo\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) { t.Errorf("expected %q, found %#q", expected, actual) } } @@ -9220,7 +9233,7 @@ func TestPrebuiltStubLibDep(t *testing.T) { continue } mod := ctx.ModuleForTests(modName, variant).Module().(*cc.Module) - if !mod.Enabled() || mod.IsHideFromMake() { + if !mod.Enabled(android.PanickingConfigAndErrorContext(ctx)) || mod.IsHideFromMake() { continue } for _, ent := range android.AndroidMkEntriesForTest(t, ctx, mod) { diff --git a/apex/prebuilt.go b/apex/prebuilt.go index ea847e15c..72a9e5219 100644 --- a/apex/prebuilt.go +++ b/apex/prebuilt.go @@ -503,9 +503,6 @@ type Prebuilt struct { inputApex android.Path provenanceMetaDataFile android.OutputPath - - // Single aconfig "cache file" merged from this module and all dependencies. - mergedAconfigFiles map[string]android.Paths } type ApexFileProperties struct { @@ -881,8 +878,6 @@ func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) { p.installedFile = ctx.InstallFile(p.installDir, p.installFilename, p.inputApex, p.compatSymlinks...) p.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, p.inputApex, p.installedFile) } - - android.CollectDependencyAconfigFiles(ctx, &p.mergedAconfigFiles) } func (p *Prebuilt) ProvenanceMetaDataFile() android.OutputPath { diff --git a/cc/Android.bp b/cc/Android.bp index 9ce89330e..3bbcaa92e 100644 --- a/cc/Android.bp +++ b/cc/Android.bp @@ -51,6 +51,7 @@ bootstrap_go_package { "vndk.go", "vndk_prebuilt.go", + "cmake_snapshot.go", "cmakelists.go", "compdb.go", "compiler.go", @@ -92,6 +93,7 @@ bootstrap_go_package { "binary_test.go", "cc_test.go", "cc_test_only_property_test.go", + "cmake_snapshot_test.go", "compiler_test.go", "gen_test.go", "genrule_test.go", @@ -109,5 +111,12 @@ bootstrap_go_package { "tidy_test.go", "vendor_public_library_test.go", ], + embedSrcs: [ + "cmake_ext_add_aidl_library.txt", + "cmake_ext_append_flags.txt", + "cmake_main.txt", + "cmake_module_aidl.txt", + "cmake_module_cc.txt", + ], pluginFor: ["soong_build"], } diff --git a/cc/androidmk.go b/cc/androidmk.go index 071d829bf..0c6f97c34 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -119,16 +119,13 @@ func (c *Module) AndroidMkEntries() []android.AndroidMkEntries { } else if c.InProduct() { entries.SetBool("LOCAL_IN_PRODUCT", true) } - if c.Properties.IsSdkVariant && c.Properties.SdkAndPlatformVariantVisibleToMake { - // Make the SDK variant uninstallable so that there are not two rules to install - // to the same location. - entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true) + if c.Properties.SdkAndPlatformVariantVisibleToMake { // Add the unsuffixed name to SOONG_SDK_VARIANT_MODULES so that Make can rewrite // dependencies to the .sdk suffix when building a module that uses the SDK. entries.SetString("SOONG_SDK_VARIANT_MODULES", "$(SOONG_SDK_VARIANT_MODULES) $(patsubst %.sdk,%,$(LOCAL_MODULE))") } - android.SetAconfigFileMkEntries(c.AndroidModuleBase(), entries, c.mergedAconfigFiles) + entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", c.IsSkipInstall()) }, }, ExtraFooters: []android.AndroidMkExtraFootersFunc{ @@ -353,6 +353,10 @@ type BaseProperties struct { // for building binaries that are started before APEXes are activated. Bootstrap *bool + // Allows this module to be included in CMake release snapshots to be built outside of Android + // build system and source tree. + Cmake_snapshot_supported *bool + // Even if DeviceConfig().VndkUseCoreVariant() is set, this module must use vendor variant. // see soong/cc/config/vndk.go MustUseVendorVariant bool `blueprint:"mutated"` @@ -588,6 +592,7 @@ type compiler interface { compilerDeps(ctx DepsContext, deps Deps) Deps compilerFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags compilerProps() []interface{} + baseCompilerProps() BaseCompilerProperties appendCflags([]string) appendAsflags([]string) @@ -602,6 +607,7 @@ type linker interface { linkerDeps(ctx DepsContext, deps Deps) Deps linkerFlags(ctx ModuleContext, flags Flags) Flags linkerProps() []interface{} + baseLinkerProps() BaseLinkerProperties useClangLld(actx ModuleContext) bool link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path @@ -907,9 +913,6 @@ type Module struct { hideApexVariantFromMake bool - // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo - mergedAconfigFiles map[string]android.Paths - logtagsPaths android.Paths } @@ -1993,10 +1996,6 @@ func (c *Module) stubLibraryMultipleApexViolation(ctx android.ModuleContext) boo return false } -func (d *Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) { - android.CollectDependencyAconfigFiles(ctx, &d.mergedAconfigFiles) -} - func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { ctx := moduleContextFromAndroidModuleContext(actx, c) @@ -2163,7 +2162,9 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: deps.GeneratedSources.Strings()}) - android.CollectDependencyAconfigFiles(ctx, &c.mergedAconfigFiles) + if Bool(c.Properties.Cmake_snapshot_supported) { + android.SetProvider(ctx, cmakeSnapshotSourcesProvider, android.GlobFiles(ctx, ctx.ModuleDir()+"/**/*", nil)) + } c.maybeInstall(ctx, apexInfo) @@ -2516,7 +2517,7 @@ func (c *Module) shouldUseApiSurface() bool { } func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { - if !c.Enabled() { + if !c.Enabled(actx) { return } @@ -2764,7 +2765,7 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { } func BeginMutator(ctx android.BottomUpMutatorContext) { - if c, ok := ctx.Module().(*Module); ok && c.Enabled() { + if c, ok := ctx.Module().(*Module); ok && c.Enabled(ctx) { c.beginMutator(ctx) } } @@ -4063,9 +4064,6 @@ type Defaults struct { android.ModuleBase android.DefaultsModuleBase android.ApexModuleBase - - // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo - mergedAconfigFiles map[string]android.Paths } // cc_defaults provides a set of properties that can be inherited by other cc diff --git a/cc/cmake_ext_add_aidl_library.txt b/cc/cmake_ext_add_aidl_library.txt new file mode 100644 index 000000000..dcf805a78 --- /dev/null +++ b/cc/cmake_ext_add_aidl_library.txt @@ -0,0 +1,47 @@ +function(add_aidl_library NAME LANG SOURCES AIDLFLAGS) + if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.20") + cmake_policy(SET CMP0116 NEW) + endif() + + set(GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}/.intermediates/${NAME}-source") + set(GEN_SOURCES) + foreach(SOURCE ${SOURCES}) + get_filename_component(SOURCE_WE ${SOURCE} NAME_WE) + get_filename_component(SOURCE_ABSOLUTE ${SOURCE} ABSOLUTE) + get_filename_component(SOURCE_DIR ${SOURCE_ABSOLUTE} DIRECTORY) + set(GEN_SOURCE "${GEN_DIR}/${SOURCE_WE}.cpp") + set(DEPFILE_ARG) + if (NOT ${CMAKE_GENERATOR} MATCHES "Unix Makefiles") + set(DEPFILE_ARG DEPFILE "${GEN_SOURCE}.d") + endif() + add_custom_command( + OUTPUT "${GEN_SOURCE}" + MAIN_DEPENDENCY "${SOURCE_ABSOLUTE}" + ${DEPFILE_ARG} + COMMAND "${AIDL_BIN}" + ARGS + --lang=${LANG} + --include="${SOURCE_DIR}" + --dep="${GEN_SOURCE}.d" + --out="${GEN_DIR}" + --header_out="${GEN_DIR}/include" + --ninja + --structured + --min_sdk_version=current + ${AIDLFLAGS} + "${SOURCE_ABSOLUTE}" + ) + list(APPEND GEN_SOURCES "${GEN_SOURCE}") + endforeach() + + add_library(${NAME} ${GEN_SOURCES}) + + target_include_directories(${NAME} + PUBLIC + "${GEN_DIR}/include" + "${ANDROID_BUILD_TOP}/frameworks/native/libs/binder/ndk/include_${LANG}" + ) + target_link_libraries(${NAME} + libbinder_sdk + ) +endfunction() diff --git a/cc/cmake_ext_append_flags.txt b/cc/cmake_ext_append_flags.txt new file mode 100644 index 000000000..2cfb1aca9 --- /dev/null +++ b/cc/cmake_ext_append_flags.txt @@ -0,0 +1,10 @@ +include(CheckCXXCompilerFlag) + +macro(append_cxx_flags_if_supported VAR) + foreach(FLAG ${ARGN}) + check_cxx_compiler_flag(${FLAG} HAS_FLAG${FLAG}) + if(${HAS_FLAG${FLAG}}) + list(APPEND ${VAR} ${FLAG}) + endif() + endforeach() +endmacro() diff --git a/cc/cmake_main.txt b/cc/cmake_main.txt new file mode 100644 index 000000000..deb1de1f8 --- /dev/null +++ b/cc/cmake_main.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.18) +project(<<.M.Name>> CXX) +set(CMAKE_CXX_STANDARD 20) + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +include(AddAidlLibrary) +include(AppendCxxFlagsIfSupported) + +if (NOT ANDROID_BUILD_TOP) + set(ANDROID_BUILD_TOP "${CMAKE_CURRENT_SOURCE_DIR}") +endif() + +set(PREBUILTS_BIN_DIR "${CMAKE_CURRENT_SOURCE_DIR}/prebuilts/host/linux-x86/bin") +if (NOT AIDL_BIN) + find_program(AIDL_BIN aidl REQUIRED HINTS "${PREBUILTS_BIN_DIR}") +endif() + +<<cflagsList .M.Name "_CFLAGS" .M.Properties.Cflags .M.Properties.Unportable_flags .M.Properties.Cflags_ignored>> + +<<range .Pprop.SystemPackages ->> +find_package(<<.>> REQUIRED) +<<end >> +<<range .Pprop.PregeneratedPackages ->> +add_subdirectory("${ANDROID_BUILD_TOP}/<<.>>" "<<.>>/build" EXCLUDE_FROM_ALL) +<<end>> +add_compile_options(${<<.M.Name>>_CFLAGS}) +<<range $moduleDir, $value := .ModuleDirs ->> +add_subdirectory(<<$moduleDir>>) +<<end>> diff --git a/cc/cmake_module_aidl.txt b/cc/cmake_module_aidl.txt new file mode 100644 index 000000000..4509a88eb --- /dev/null +++ b/cc/cmake_module_aidl.txt @@ -0,0 +1,8 @@ +# <<.M.Name>> + +<<setList .M.Name "_SRCS" "${ANDROID_BUILD_TOP}/" (getCompilerProperties .M).AidlInterface.Sources>> + +<<setList .M.Name "_AIDLFLAGS" "" (getCompilerProperties .M).AidlInterface.Flags>> + +add_aidl_library(<<.M.Name>> <<(getCompilerProperties .M).AidlInterface.Lang>> "${<<.M.Name>>_SRCS}" "${<<.M.Name>>_AIDLFLAGS}") +add_library(android::<<.M.Name>> ALIAS <<.M.Name>>) diff --git a/cc/cmake_module_cc.txt b/cc/cmake_module_cc.txt new file mode 100644 index 000000000..571f27ce5 --- /dev/null +++ b/cc/cmake_module_cc.txt @@ -0,0 +1,35 @@ +<<$srcs := getSources .M>> +<<$includeDirs := getIncludeDirs .Ctx .M>> +<<$cflags := (getCompilerProperties .M).Cflags>> +<<$deps := mapLibraries (concat5 +(getLinkerProperties .M).Whole_static_libs +(getLinkerProperties .M).Static_libs +(getLinkerProperties .M).Shared_libs +(getLinkerProperties .M).Header_libs +(getExtraLibs .M) +) .Pprop.LibraryMapping>> + +# <<.M.Name>> +<<if $srcs>> +<<setList .M.Name "_SRCS" "${ANDROID_BUILD_TOP}/" (toStrings $srcs)>> +add_<<getModuleType .M>>(<<.M.Name>> ${<<.M.Name>>_SRCS}) +<<- else>> +add_<<getModuleType .M>>(<<.M.Name>> INTERFACE) +<<- end>> +add_<<getModuleType .M>>(android::<<.M.Name>> ALIAS <<.M.Name>>) +<<print "">> + +<<- if $includeDirs>> +<<setList .M.Name "_INCLUDES" "${ANDROID_BUILD_TOP}/" $includeDirs>> +target_include_directories(<<.M.Name>> <<if $srcs>>PUBLIC<<else>>INTERFACE<<end>> ${<<.M.Name>>_INCLUDES}) +<<end>> + +<<- if and $srcs $cflags>> +<<cflagsList .M.Name "_CFLAGS" $cflags .Snapshot.Properties.Unportable_flags .Snapshot.Properties.Cflags_ignored>> +target_compile_options(<<.M.Name>> PRIVATE ${<<.M.Name>>_CFLAGS}) +<<end>> + +<<- if $deps>> +<<setList .M.Name "_DEPENDENCIES" "" $deps>> +target_link_libraries(<<.M.Name>> <<if not $srcs>>INTERFACE <<end ->> ${<<.M.Name>>_DEPENDENCIES}) +<<end>> diff --git a/cc/cmake_snapshot.go b/cc/cmake_snapshot.go new file mode 100644 index 000000000..0635a2965 --- /dev/null +++ b/cc/cmake_snapshot.go @@ -0,0 +1,526 @@ +// 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 cc + +import ( + "android/soong/android" + "bytes" + _ "embed" + "fmt" + "path/filepath" + "slices" + "sort" + "strings" + "text/template" + + "github.com/google/blueprint" + "github.com/google/blueprint/proptools" +) + +const veryVerbose bool = false + +//go:embed cmake_main.txt +var templateCmakeMainRaw string +var templateCmakeMain *template.Template = parseTemplate(templateCmakeMainRaw) + +//go:embed cmake_module_cc.txt +var templateCmakeModuleCcRaw string +var templateCmakeModuleCc *template.Template = parseTemplate(templateCmakeModuleCcRaw) + +//go:embed cmake_module_aidl.txt +var templateCmakeModuleAidlRaw string +var templateCmakeModuleAidl *template.Template = parseTemplate(templateCmakeModuleAidlRaw) + +//go:embed cmake_ext_add_aidl_library.txt +var cmakeExtAddAidlLibrary string + +//go:embed cmake_ext_append_flags.txt +var cmakeExtAppendFlags string + +var defaultUnportableFlags []string = []string{ + "-Wno-class-memaccess", + "-Wno-exit-time-destructors", + "-Wno-inconsistent-missing-override", + "-Wreorder-init-list", + "-Wno-reorder-init-list", + "-Wno-restrict", + "-Wno-stringop-overread", + "-Wno-subobject-linkage", +} + +var ignoredSystemLibs []string = []string{ + "libc++", + "libc++_static", + "prebuilt_libclang_rt.builtins", + "prebuilt_libclang_rt.ubsan_minimal", +} + +// Mapping entry between Android's library name and the one used when building outside Android tree. +type LibraryMappingProperty struct { + // Android library name. + Android_name string + + // Library name used when building outside Android. + Mapped_name string + + // If the make file is already present in Android source tree, specify its location. + Package_pregenerated string + + // If the package is expected to be installed on the build host OS, specify its name. + Package_system string +} + +type CmakeSnapshotProperties struct { + // Modules to add to the snapshot package. Their dependencies are pulled in automatically. + Modules []string + + // Host prebuilts to bundle with the snapshot. These are tools needed to build outside Android. + Prebuilts []string + + // Global cflags to add when building outside Android. + Cflags []string + + // Flags to skip when building outside Android. + Cflags_ignored []string + + // Mapping between library names used in Android tree and externally. + Library_mapping []LibraryMappingProperty + + // List of cflags that are not portable between compilers that could potentially be used to + // build a generated package. If left empty, it's initialized with a default list. + Unportable_flags []string + + // Whether to include source code as part of the snapshot package. + Include_sources bool +} + +var cmakeSnapshotSourcesProvider = blueprint.NewProvider[android.Paths]() + +type CmakeSnapshot struct { + android.ModuleBase + + Properties CmakeSnapshotProperties + + zipPath android.WritablePath +} + +type cmakeProcessedProperties struct { + LibraryMapping map[string]LibraryMappingProperty + PregeneratedPackages []string + SystemPackages []string +} + +type cmakeSnapshotDependencyTag struct { + blueprint.BaseDependencyTag + name string +} + +var ( + cmakeSnapshotModuleTag = cmakeSnapshotDependencyTag{name: "cmake-snapshot-module"} + cmakeSnapshotPrebuiltTag = cmakeSnapshotDependencyTag{name: "cmake-snapshot-prebuilt"} +) + +func parseTemplate(templateContents string) *template.Template { + funcMap := template.FuncMap{ + "setList": func(name string, nameSuffix string, itemPrefix string, items []string) string { + var list strings.Builder + list.WriteString("set(" + name + nameSuffix) + templateListBuilder(&list, itemPrefix, items) + return list.String() + }, + "toStrings": func(files android.Paths) []string { + strings := make([]string, len(files)) + for idx, file := range files { + strings[idx] = file.String() + } + return strings + }, + "concat5": func(list1 []string, list2 []string, list3 []string, list4 []string, list5 []string) []string { + return append(append(append(append(list1, list2...), list3...), list4...), list5...) + }, + "cflagsList": func(name string, nameSuffix string, flags []string, + unportableFlags []string, ignoredFlags []string) string { + if len(unportableFlags) == 0 { + unportableFlags = defaultUnportableFlags + } + + var filteredPortable []string + var filteredUnportable []string + for _, flag := range flags { + if slices.Contains(ignoredFlags, flag) { + continue + } else if slices.Contains(unportableFlags, flag) { + filteredUnportable = append(filteredUnportable, flag) + } else { + filteredPortable = append(filteredPortable, flag) + } + } + + var list strings.Builder + + list.WriteString("set(" + name + nameSuffix) + templateListBuilder(&list, "", filteredPortable) + + if len(filteredUnportable) > 0 { + list.WriteString("\nappend_cxx_flags_if_supported(" + name + nameSuffix) + templateListBuilder(&list, "", filteredUnportable) + } + + return list.String() + }, + "getSources": func(m *Module) android.Paths { + return m.compiler.(CompiledInterface).Srcs() + }, + "getModuleType": getModuleType, + "getCompilerProperties": func(m *Module) BaseCompilerProperties { + return m.compiler.baseCompilerProps() + }, + "getLinkerProperties": func(m *Module) BaseLinkerProperties { + return m.linker.baseLinkerProps() + }, + "getExtraLibs": getExtraLibs, + "getIncludeDirs": getIncludeDirs, + "mapLibraries": func(libs []string, mapping map[string]LibraryMappingProperty) []string { + var mappedLibs []string + for _, lib := range libs { + mappedLib, exists := mapping[lib] + if exists { + lib = mappedLib.Mapped_name + } else { + lib = "android::" + lib + } + if lib == "" { + continue + } + mappedLibs = append(mappedLibs, lib) + } + sort.Strings(mappedLibs) + mappedLibs = slices.Compact(mappedLibs) + return mappedLibs + }, + } + + return template.Must(template.New("").Delims("<<", ">>").Funcs(funcMap).Parse(templateContents)) +} + +func sliceWithPrefix(prefix string, slice []string) []string { + output := make([]string, len(slice)) + for i, elem := range slice { + output[i] = prefix + elem + } + return output +} + +func templateListBuilder(builder *strings.Builder, itemPrefix string, items []string) { + if len(items) > 0 { + builder.WriteString("\n") + for _, item := range items { + builder.WriteString(" " + itemPrefix + item + "\n") + } + } + builder.WriteString(")") +} + +func executeTemplate(templ *template.Template, buffer *bytes.Buffer, data any) string { + buffer.Reset() + if err := templ.Execute(buffer, data); err != nil { + panic(err) + } + output := strings.TrimSpace(buffer.String()) + buffer.Reset() + return output +} + +func (m *CmakeSnapshot) DepsMutator(ctx android.BottomUpMutatorContext) { + variations := []blueprint.Variation{ + {"os", "linux_glibc"}, + {"arch", "x86_64"}, + } + ctx.AddVariationDependencies(variations, cmakeSnapshotModuleTag, m.Properties.Modules...) + ctx.AddVariationDependencies(variations, cmakeSnapshotPrebuiltTag, m.Properties.Prebuilts...) +} + +func (m *CmakeSnapshot) GenerateAndroidBuildActions(ctx android.ModuleContext) { + var templateBuffer bytes.Buffer + var pprop cmakeProcessedProperties + m.zipPath = android.PathForModuleOut(ctx, ctx.ModuleName()+".zip") + + // Process Library_mapping for more efficient lookups + pprop.LibraryMapping = map[string]LibraryMappingProperty{} + for _, elem := range m.Properties.Library_mapping { + pprop.LibraryMapping[elem.Android_name] = elem + + if elem.Package_pregenerated != "" { + pprop.PregeneratedPackages = append(pprop.PregeneratedPackages, elem.Package_pregenerated) + } + sort.Strings(pprop.PregeneratedPackages) + pprop.PregeneratedPackages = slices.Compact(pprop.PregeneratedPackages) + + if elem.Package_system != "" { + pprop.SystemPackages = append(pprop.SystemPackages, elem.Package_system) + } + sort.Strings(pprop.SystemPackages) + pprop.SystemPackages = slices.Compact(pprop.SystemPackages) + } + + // Generating CMakeLists.txt rules for all modules in dependency tree + moduleDirs := map[string][]string{} + sourceFiles := map[string]android.Path{} + visitedModules := map[string]bool{} + var pregeneratedModules []*Module + ctx.WalkDeps(func(dep_a android.Module, parent android.Module) bool { + moduleName := ctx.OtherModuleName(dep_a) + dep, ok := dep_a.(*Module) + if !ok { + return false // not a cc module + } + if visited := visitedModules[moduleName]; visited { + return false // visit only once + } + visitedModules[moduleName] = true + if mapping, ok := pprop.LibraryMapping[moduleName]; ok { + if mapping.Package_pregenerated != "" { + pregeneratedModules = append(pregeneratedModules, dep) + } + return false // mapped to system or pregenerated (we'll handle these later) + } + if ctx.OtherModuleDependencyTag(dep) == cmakeSnapshotPrebuiltTag { + return false // we'll handle cmakeSnapshotPrebuiltTag later + } + if slices.Contains(ignoredSystemLibs, moduleName) { + return false // system libs built in-tree for Android + } + if dep.compiler == nil { + return false // unsupported module type (e.g. prebuilt) + } + isAidlModule := dep.compiler.baseCompilerProps().AidlInterface.Lang != "" + + if !proptools.Bool(dep.Properties.Cmake_snapshot_supported) { + ctx.OtherModulePropertyErrorf(dep, "cmake_snapshot_supported", + "CMake snapshots not supported, despite being a dependency for %s", + ctx.OtherModuleName(parent)) + return false + } + + if veryVerbose { + fmt.Println("WalkDeps: " + ctx.OtherModuleName(parent) + " -> " + moduleName) + } + + // Generate CMakeLists.txt fragment for this module + templateToUse := templateCmakeModuleCc + if isAidlModule { + templateToUse = templateCmakeModuleAidl + } + moduleFragment := executeTemplate(templateToUse, &templateBuffer, struct { + Ctx *android.ModuleContext + M *Module + Snapshot *CmakeSnapshot + Pprop *cmakeProcessedProperties + }{ + &ctx, + dep, + m, + &pprop, + }) + moduleDir := ctx.OtherModuleDir(dep) + moduleDirs[moduleDir] = append(moduleDirs[moduleDir], moduleFragment) + + if m.Properties.Include_sources { + files, _ := android.OtherModuleProvider(ctx, dep, cmakeSnapshotSourcesProvider) + for _, file := range files { + sourceFiles[file.String()] = file + } + } + + // if it's AIDL module, no need to dive into their dependencies + return !isAidlModule + }) + + // Enumerate sources for pregenerated modules + if m.Properties.Include_sources { + for _, dep := range pregeneratedModules { + if !proptools.Bool(dep.Properties.Cmake_snapshot_supported) { + ctx.OtherModulePropertyErrorf(dep, "cmake_snapshot_supported", + "Pregenerated CMake snapshots not supported, despite being requested for %s", + ctx.ModuleName()) + continue + } + + files, _ := android.OtherModuleProvider(ctx, dep, cmakeSnapshotSourcesProvider) + for _, file := range files { + sourceFiles[file.String()] = file + } + } + } + + // Merging CMakeLists.txt contents for every module directory + var makefilesList android.Paths + for moduleDir, fragments := range moduleDirs { + moduleCmakePath := android.PathForModuleGen(ctx, moduleDir, "CMakeLists.txt") + makefilesList = append(makefilesList, moduleCmakePath) + sort.Strings(fragments) + android.WriteFileRule(ctx, moduleCmakePath, strings.Join(fragments, "\n\n\n")) + } + + // Generating top-level CMakeLists.txt + mainCmakePath := android.PathForModuleGen(ctx, "CMakeLists.txt") + makefilesList = append(makefilesList, mainCmakePath) + mainContents := executeTemplate(templateCmakeMain, &templateBuffer, struct { + Ctx *android.ModuleContext + M *CmakeSnapshot + ModuleDirs map[string][]string + Pprop *cmakeProcessedProperties + }{ + &ctx, + m, + moduleDirs, + &pprop, + }) + android.WriteFileRule(ctx, mainCmakePath, mainContents) + + // Generating CMake extensions + extPath := android.PathForModuleGen(ctx, "cmake", "AppendCxxFlagsIfSupported.cmake") + makefilesList = append(makefilesList, extPath) + android.WriteFileRuleVerbatim(ctx, extPath, cmakeExtAppendFlags) + extPath = android.PathForModuleGen(ctx, "cmake", "AddAidlLibrary.cmake") + makefilesList = append(makefilesList, extPath) + android.WriteFileRuleVerbatim(ctx, extPath, cmakeExtAddAidlLibrary) + + // Generating the final zip file + zipRule := android.NewRuleBuilder(pctx, ctx) + zipCmd := zipRule.Command(). + BuiltTool("soong_zip"). + FlagWithOutput("-o ", m.zipPath) + + // Packaging all sources into the zip file + if m.Properties.Include_sources { + var sourcesList android.Paths + for _, file := range sourceFiles { + sourcesList = append(sourcesList, file) + } + + sourcesRspFile := android.PathForModuleObj(ctx, ctx.ModuleName()+"_sources.rsp") + zipCmd.FlagWithRspFileInputList("-r ", sourcesRspFile, sourcesList) + } + + // Packaging all make files into the zip file + makefilesRspFile := android.PathForModuleObj(ctx, ctx.ModuleName()+"_makefiles.rsp") + zipCmd. + FlagWithArg("-C ", android.PathForModuleGen(ctx).OutputPath.String()). + FlagWithRspFileInputList("-r ", makefilesRspFile, makefilesList) + + // Packaging all prebuilts into the zip file + if len(m.Properties.Prebuilts) > 0 { + var prebuiltsList android.Paths + + ctx.VisitDirectDepsWithTag(cmakeSnapshotPrebuiltTag, func(dep android.Module) { + for _, file := range dep.FilesToInstall() { + prebuiltsList = append(prebuiltsList, file) + } + }) + + prebuiltsRspFile := android.PathForModuleObj(ctx, ctx.ModuleName()+"_prebuilts.rsp") + zipCmd. + FlagWithArg("-C ", android.PathForArbitraryOutput(ctx).String()). + FlagWithArg("-P ", "prebuilts"). + FlagWithRspFileInputList("-r ", prebuiltsRspFile, prebuiltsList) + } + + // Finish generating the final zip file + zipRule.Build(m.zipPath.String(), "archiving "+ctx.ModuleName()) +} + +func (m *CmakeSnapshot) OutputFiles(tag string) (android.Paths, error) { + switch tag { + case "": + return android.Paths{m.zipPath}, nil + default: + return nil, fmt.Errorf("unsupported module reference tag %q", tag) + } +} + +func (m *CmakeSnapshot) AndroidMkEntries() []android.AndroidMkEntries { + return []android.AndroidMkEntries{{ + Class: "DATA", + OutputFile: android.OptionalPathForPath(m.zipPath), + ExtraEntries: []android.AndroidMkExtraEntriesFunc{ + func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { + entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true) + }, + }, + }} +} + +func getModuleType(m *Module) string { + switch m.linker.(type) { + case *binaryDecorator: + return "executable" + case *libraryDecorator: + return "library" + case *testBinary: + return "executable" + } + panic(fmt.Sprintf("Unexpected module type: %T", m.compiler)) +} + +func getExtraLibs(m *Module) []string { + switch decorator := m.linker.(type) { + case *testBinary: + if decorator.testDecorator.gtest() { + return []string{"libgtest"} + } + } + return nil +} + +func getIncludeDirs(ctx android.ModuleContext, m *Module) []string { + moduleDir := ctx.OtherModuleDir(m) + string(filepath.Separator) + switch decorator := m.compiler.(type) { + case *libraryDecorator: + return sliceWithPrefix(moduleDir, decorator.flagExporter.Properties.Export_include_dirs) + } + return nil +} + +func cmakeSnapshotLoadHook(ctx android.LoadHookContext) { + props := struct { + Target struct { + Darwin struct { + Enabled *bool + } + Windows struct { + Enabled *bool + } + } + }{} + props.Target.Darwin.Enabled = proptools.BoolPtr(false) + props.Target.Windows.Enabled = proptools.BoolPtr(false) + ctx.AppendProperties(&props) +} + +// cmake_snapshot allows defining source packages for release outside of Android build tree. +// As a result of cmake_snapshot module build, a zip file is generated with CMake build definitions +// for selected source modules, their dependencies and optionally also the source code itself. +func CmakeSnapshotFactory() android.Module { + module := &CmakeSnapshot{} + module.AddProperties(&module.Properties) + android.AddLoadHook(module, cmakeSnapshotLoadHook) + android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst) + return module +} + +func init() { + android.InitRegistrationContext.RegisterModuleType("cc_cmake_snapshot", CmakeSnapshotFactory) +} diff --git a/cc/cmake_snapshot_test.go b/cc/cmake_snapshot_test.go new file mode 100644 index 000000000..8fca6c18f --- /dev/null +++ b/cc/cmake_snapshot_test.go @@ -0,0 +1,115 @@ +// 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 cc + +import ( + "runtime" + "strings" + "testing" + + "android/soong/android" +) + +func wasGenerated(t *testing.T, m *android.TestingModule, fileName string, ruleType string) { + t.Helper() + ruleName := "<nil>" + if rule := m.MaybeOutput(fileName).Rule; rule != nil { + ruleName = rule.String() + } + if !strings.HasSuffix(ruleName, ruleType) { + t.Errorf("Main Cmake file wasn't generated properly, expected rule %v, found %v", ruleType, ruleName) + } +} + +func TestEmptyCmakeSnapshot(t *testing.T) { + t.Parallel() + result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, ` + cc_cmake_snapshot { + name: "foo", + modules: [], + prebuilts: ["libc++"], + include_sources: true, + }`) + + if runtime.GOOS != "linux" { + t.Skip("CMake snapshots are only supported on Linux") + } + + snapshotModule := result.ModuleForTests("foo", "linux_glibc_x86_64") + + wasGenerated(t, &snapshotModule, "CMakeLists.txt", "rawFileCopy") + wasGenerated(t, &snapshotModule, "foo.zip", "") +} + +func TestCmakeSnapshotWithBinary(t *testing.T) { + t.Parallel() + xtra := android.FixtureAddTextFile("some/module/Android.bp", ` + cc_binary { + name: "foo_binary", + host_supported: true, + cmake_snapshot_supported: true, + } + `) + result := android.GroupFixturePreparers(PrepareForIntegrationTestWithCc, xtra).RunTestWithBp(t, ` + cc_cmake_snapshot { + name: "foo", + modules: [ + "foo_binary", + ], + include_sources: true, + }`) + + if runtime.GOOS != "linux" { + t.Skip("CMake snapshots are only supported on Linux") + } + + snapshotModule := result.ModuleForTests("foo", "linux_glibc_x86_64") + + wasGenerated(t, &snapshotModule, "some/module/CMakeLists.txt", "rawFileCopy") +} + +func TestCmakeSnapshotAsTestData(t *testing.T) { + t.Parallel() + result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, ` + cc_test { + name: "foo_test", + gtest: false, + srcs: [ + "foo_test.c", + ], + data: [ + ":foo", + ], + target: { + android: {enabled: false}, + }, + } + + cc_cmake_snapshot { + name: "foo", + modules: [], + prebuilts: ["libc++"], + include_sources: true, + }`) + + if runtime.GOOS != "linux" { + t.Skip("CMake snapshots are only supported on Linux") + } + + snapshotModule := result.ModuleForTests("foo", "linux_glibc_x86_64") + + wasGenerated(t, &snapshotModule, "CMakeLists.txt", "rawFileCopy") + wasGenerated(t, &snapshotModule, "foo.zip", "") +} diff --git a/cc/compiler.go b/cc/compiler.go index 9a961cfb9..aee584daf 100644 --- a/cc/compiler.go +++ b/cc/compiler.go @@ -141,6 +141,19 @@ type BaseCompilerProperties struct { Flags []string } + // Populated by aidl_interface CPP backend to let other modules (e.g. cc_cmake_snapshot) + // access actual source files and not generated cpp intermediary sources. + AidlInterface struct { + // list of aidl_interface sources + Sources []string `blueprint:"mutated"` + + // AIDL backend language (e.g. "cpp", "ndk") + Lang string `blueprint:"mutated"` + + // list of flags passed to AIDL generator + Flags []string `blueprint:"mutated"` + } `blueprint:"mutated"` + Renderscript struct { // list of directories that will be added to the llvm-rs-cc include paths Include_dirs []string @@ -265,6 +278,10 @@ func (compiler *baseCompiler) compilerProps() []interface{} { return []interface{}{&compiler.Properties, &compiler.Proto} } +func (compiler *baseCompiler) baseCompilerProps() BaseCompilerProperties { + return compiler.Properties +} + func includeBuildDirectory(prop *bool) bool { return proptools.BoolDefault(prop, true) } diff --git a/cc/fuzz.go b/cc/fuzz.go index 2436f33d2..b3e663962 100644 --- a/cc/fuzz.go +++ b/cc/fuzz.go @@ -433,7 +433,7 @@ func (s *ccRustFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) return } // Discard non-fuzz targets. - if ok := fuzz.IsValid(ccModule.FuzzModuleStruct()); !ok { + if ok := fuzz.IsValid(ctx, ccModule.FuzzModuleStruct()); !ok { return } diff --git a/cc/linker.go b/cc/linker.go index 56a68b2ce..1d0f20547 100644 --- a/cc/linker.go +++ b/cc/linker.go @@ -287,6 +287,10 @@ func (linker *baseLinker) linkerProps() []interface{} { return []interface{}{&linker.Properties, &linker.dynamicProperties} } +func (linker *baseLinker) baseLinkerProps() BaseLinkerProperties { + return linker.Properties +} + func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps { deps.WholeStaticLibs = append(deps.WholeStaticLibs, linker.Properties.Whole_static_libs...) deps.HeaderLibs = append(deps.HeaderLibs, linker.Properties.Header_libs...) diff --git a/cc/llndk_library.go b/cc/llndk_library.go index cd931f634..5b86c6478 100644 --- a/cc/llndk_library.go +++ b/cc/llndk_library.go @@ -186,7 +186,7 @@ func llndkMutator(mctx android.BottomUpMutatorContext) { return } - if shouldSkipLlndkMutator(m) { + if shouldSkipLlndkMutator(mctx, m) { return } @@ -206,8 +206,8 @@ func llndkMutator(mctx android.BottomUpMutatorContext) { } // Check for modules that mustn't be LLNDK -func shouldSkipLlndkMutator(m *Module) bool { - if !m.Enabled() { +func shouldSkipLlndkMutator(mctx android.BottomUpMutatorContext, m *Module) bool { + if !m.Enabled(mctx) { return true } if !m.Device() { diff --git a/cc/makevars.go b/cc/makevars.go index 9251d6a49..51bcbf090 100644 --- a/cc/makevars.go +++ b/cc/makevars.go @@ -279,7 +279,7 @@ func makeVarsToolchain(ctx android.MakeVarsContext, secondPrefix string, sanitizerLibs := android.SortedStringValues(sanitizerVariables) var sanitizerLibStems []string ctx.VisitAllModules(func(m android.Module) { - if !m.Enabled() { + if !m.Enabled(ctx) { return } diff --git a/cc/ndk_abi.go b/cc/ndk_abi.go index 86166dcbb..5beeab1ee 100644 --- a/cc/ndk_abi.go +++ b/cc/ndk_abi.go @@ -40,7 +40,7 @@ type ndkAbiDumpSingleton struct{} func (n *ndkAbiDumpSingleton) GenerateBuildActions(ctx android.SingletonContext) { var depPaths android.Paths ctx.VisitAllModules(func(module android.Module) { - if !module.Enabled() { + if !module.Enabled(ctx) { return } @@ -78,7 +78,7 @@ type ndkAbiDiffSingleton struct{} func (n *ndkAbiDiffSingleton) GenerateBuildActions(ctx android.SingletonContext) { var depPaths android.Paths ctx.VisitAllModules(func(module android.Module) { - if m, ok := module.(android.Module); ok && !m.Enabled() { + if m, ok := module.(android.Module); ok && !m.Enabled(ctx) { return } diff --git a/cc/ndk_library.go b/cc/ndk_library.go index 25231fdf5..f32606814 100644 --- a/cc/ndk_library.go +++ b/cc/ndk_library.go @@ -148,7 +148,7 @@ func ndkLibraryVersions(ctx android.BaseMutatorContext, from android.ApiLevel) [ } func (this *stubDecorator) stubsVersions(ctx android.BaseMutatorContext) []string { - if !ctx.Module().Enabled() { + if !ctx.Module().Enabled(ctx) { return nil } if ctx.Target().NativeBridge == android.NativeBridgeEnabled { diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go index e815172ae..3c48f6881 100644 --- a/cc/ndk_sysroot.go +++ b/cc/ndk_sysroot.go @@ -150,7 +150,7 @@ func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) { var installPaths android.Paths var licensePaths android.Paths ctx.VisitAllModules(func(module android.Module) { - if m, ok := module.(android.Module); ok && !m.Enabled() { + if m, ok := module.(android.Module); ok && !m.Enabled(ctx) { return } diff --git a/cc/sanitize.go b/cc/sanitize.go index 0cb54e5ca..1a94729c6 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -1385,7 +1385,7 @@ func sanitizerRuntimeDepsMutator(mctx android.TopDownMutatorContext) { // Add the dependency to the runtime library for each of the sanitizer variants func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil { - if !c.Enabled() { + if !c.Enabled(mctx) { return } var sanitizers []string @@ -49,15 +49,18 @@ func sdkMutator(ctx android.BottomUpMutatorContext) { modules[1].(*Module).Properties.IsSdkVariant = true if ctx.Config().UnbundledBuildApps() { - // For an unbundled apps build, hide the platform variant from Make. + // For an unbundled apps build, hide the platform variant from Make + // so that other Make modules don't link against it, but against the + // SDK variant. modules[0].(*Module).Properties.HideFromMake = true - modules[0].(*Module).Properties.PreventInstall = true } else { // For a platform build, mark the SDK variant so that it gets a ".sdk" suffix when // exposed to Make. modules[1].(*Module).Properties.SdkAndPlatformVariantVisibleToMake = true - modules[1].(*Module).Properties.PreventInstall = true } + // SDK variant never gets installed because the variant is to be embedded in + // APKs, not to be installed to the platform. + modules[1].(*Module).Properties.PreventInstall = true ctx.AliasVariation("") } else { if isCcModule { diff --git a/cc/testing.go b/cc/testing.go index 4b4e866d4..c3a33cb91 100644 --- a/cc/testing.go +++ b/cc/testing.go @@ -35,6 +35,7 @@ func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) { ctx.RegisterModuleType("prebuilt_build_tool", android.NewPrebuiltBuildTool) ctx.RegisterModuleType("cc_benchmark", BenchmarkFactory) + ctx.RegisterModuleType("cc_cmake_snapshot", CmakeSnapshotFactory) ctx.RegisterModuleType("cc_object", ObjectFactory) ctx.RegisterModuleType("cc_genrule", GenRuleFactory) ctx.RegisterModuleType("ndk_prebuilt_shared_stl", NdkPrebuiltSharedStlFactory) diff --git a/cc/tidy.go b/cc/tidy.go index 76ac7d583..ec1e8a206 100644 --- a/cc/tidy.go +++ b/cc/tidy.go @@ -220,7 +220,7 @@ func collectTidyObjModuleTargets(ctx android.SingletonContext, module android.Mo // (1) Collect all obj/tidy files into OS-specific groups. ctx.VisitAllModuleVariants(module, func(variant android.Module) { - if ctx.Config().KatiEnabled() && android.ShouldSkipAndroidMkProcessing(variant) { + if ctx.Config().KatiEnabled() && android.ShouldSkipAndroidMkProcessing(ctx, variant) { return } if m, ok := variant.(*Module); ok { diff --git a/cc/vndk.go b/cc/vndk.go index 50e6d4b96..548992d37 100644 --- a/cc/vndk.go +++ b/cc/vndk.go @@ -322,8 +322,8 @@ func processVndkLibrary(mctx android.BottomUpMutatorContext, m *Module) { } // Check for modules that mustn't be VNDK -func shouldSkipVndkMutator(m *Module) bool { - if !m.Enabled() { +func shouldSkipVndkMutator(ctx android.ConfigAndErrorContext, m *Module) bool { + if !m.Enabled(ctx) { return true } if !m.Device() { @@ -338,7 +338,7 @@ func shouldSkipVndkMutator(m *Module) bool { } func IsForVndkApex(mctx android.BottomUpMutatorContext, m *Module) bool { - if shouldSkipVndkMutator(m) { + if shouldSkipVndkMutator(mctx, m) { return false } @@ -369,7 +369,7 @@ func VndkMutator(mctx android.BottomUpMutatorContext) { return } - if shouldSkipVndkMutator(m) { + if shouldSkipVndkMutator(mctx, m) { return } @@ -548,6 +548,7 @@ func (txt *vndkLibrariesTxt) SubDir() string { func (txt *vndkLibrariesTxt) OutputFiles(tag string) (android.Paths, error) { return android.Paths{txt.outputFile}, nil } + func getVndkFileName(m *Module) (string, error) { if library, ok := m.linker.(*libraryDecorator); ok { return library.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil diff --git a/cmd/release_config/build_flag/main.go b/cmd/release_config/build_flag/main.go index 56c49d883..cc2b57a27 100644 --- a/cmd/release_config/build_flag/main.go +++ b/cmd/release_config/build_flag/main.go @@ -266,7 +266,7 @@ func SetCommand(configs *rc_lib.ReleaseConfigs, commonFlags Flags, cmd string, a return fmt.Errorf("Unknown build flag %s", name) } if valueDir == "" { - mapDir, err := GetMapDir(*flagArtifact.Traces[len(flagArtifact.Traces)-1].Source) + mapDir, err := configs.GetFlagValueDirectory(release, flagArtifact) if err != nil { return err } diff --git a/cmd/release_config/crunch_flags/main.go b/cmd/release_config/crunch_flags/main.go index 4d763c8d7..cd39ffd11 100644 --- a/cmd/release_config/crunch_flags/main.go +++ b/cmd/release_config/crunch_flags/main.go @@ -137,7 +137,9 @@ func ProcessBuildFlags(dir string, namespaceMap map[string]string) error { workflow := rc_proto.Workflow(rc_proto.Workflow_PREBUILT) switch { case declName == "RELEASE_ACONFIG_VALUE_SETS": - rootAconfigModule = declValue[1 : len(declValue)-1] + if strings.HasPrefix(declValue, "\"") { + rootAconfigModule = declValue[1 : len(declValue)-1] + } continue case strings.HasPrefix(declValue, "\""): // String values mean that the flag workflow is (most likely) either MANUAL or PREBUILT. diff --git a/cmd/release_config/release_config/main.go b/cmd/release_config/release_config/main.go index 101dbe381..54328068a 100644 --- a/cmd/release_config/release_config/main.go +++ b/cmd/release_config/release_config/main.go @@ -83,20 +83,24 @@ func main() { // We were told to guard operation and either we have no build flag, or it is False. // Write an empty file so that release_config.mk will use the old process. os.WriteFile(makefilePath, []byte{}, 0644) - } else if allMake { + return + } + // Write the makefile where release_config.mk is going to look for it. + err = configs.WriteMakefile(makefilePath, targetRelease) + if err != nil { + panic(err) + } + if allMake { // Write one makefile per release config, using the canonical release name. for k, _ := range configs.ReleaseConfigs { - makefilePath = filepath.Join(outputDir, fmt.Sprintf("release_config-%s-%s.mk", product, k)) - err = configs.WriteMakefile(makefilePath, k) - if err != nil { - panic(err) + if k != targetRelease { + makefilePath = filepath.Join(outputDir, fmt.Sprintf("release_config-%s-%s.mk", product, k)) + err = configs.WriteMakefile(makefilePath, k) + if err != nil { + panic(err) + } } } - } else { - err = configs.WriteMakefile(makefilePath, targetRelease) - if err != nil { - panic(err) - } } if json { err = configs.WriteArtifact(outputDir, product, "json") diff --git a/cmd/release_config/release_config_lib/release_config.go b/cmd/release_config/release_config_lib/release_config.go index f25cc6e66..820482239 100644 --- a/cmd/release_config/release_config_lib/release_config.go +++ b/cmd/release_config/release_config_lib/release_config.go @@ -29,7 +29,7 @@ import ( // One directory's contribution to the a release config. type ReleaseConfigContribution struct { - // Paths to files providing this config. + // Path of the file providing this config contribution. path string // The index of the config directory where this release config diff --git a/cmd/release_config/release_config_lib/release_configs.go b/cmd/release_config/release_config_lib/release_configs.go index 34294002c..2487f2e99 100644 --- a/cmd/release_config/release_config_lib/release_configs.go +++ b/cmd/release_config/release_config_lib/release_configs.go @@ -131,6 +131,32 @@ func ReleaseConfigMapFactory(protoPath string) (m *ReleaseConfigMap) { return m } +// Find the top of the release config contribution directory. +// Returns the parent of the flag_declarations and flag_values directories. +func (configs *ReleaseConfigs) GetDirIndex(path string) (int, error) { + for p := path; p != "."; p = filepath.Dir(p) { + if idx, ok := configs.configDirIndexes[p]; ok { + return idx, nil + } + } + return -1, fmt.Errorf("Could not determine release config directory from %s", path) +} + +// Determine the default directory for writing a flag value. +// +// Returns the path of the highest-Indexed one of: +// - Where the flag is declared +// - Where the release config is first declared +// - The last place the value is being written. +func (configs *ReleaseConfigs) GetFlagValueDirectory(config *ReleaseConfig, flag *FlagArtifact) (string, error) { + current, err := configs.GetDirIndex(*flag.Traces[len(flag.Traces)-1].Source) + if err != nil { + return "", err + } + index := max(flag.DeclarationIndex, config.DeclarationIndex, current) + return configs.configDirs[index], nil +} + func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex int) error { if _, err := os.Stat(path); err != nil { return fmt.Errorf("%s does not exist\n", path) @@ -265,6 +291,9 @@ func (configs *ReleaseConfigs) WriteMakefile(outFile, targetRelease string) erro allReleaseNames = append(allReleaseNames, v.Name) allReleaseNames = append(allReleaseNames, v.OtherNames...) } + slices.SortFunc(allReleaseNames, func(a, b string) int { + return cmp.Compare(a, b) + }) config, err := configs.GetReleaseConfig(targetRelease) if err != nil { return err diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go index 025ba27aa..6ab3b8890 100644 --- a/etc/prebuilt_etc.go +++ b/etc/prebuilt_etc.go @@ -158,9 +158,6 @@ type PrebuiltEtc struct { additionalDependencies *android.Paths makeClass string - - // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo - mergedAconfigFiles map[string]android.Paths } type Defaults struct { @@ -421,7 +418,6 @@ func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) { for _, ip := range installs { ip.addInstallRules(ctx) } - android.CollectDependencyAconfigFiles(ctx, &p.mergedAconfigFiles) } type installProperties struct { @@ -486,7 +482,6 @@ func (p *PrebuiltEtc) AndroidMkEntries() []android.AndroidMkEntries { if p.additionalDependencies != nil { entries.AddStrings("LOCAL_ADDITIONAL_DEPENDENCIES", p.additionalDependencies.Strings()...) } - android.SetAconfigFileMkEntries(p.AndroidModuleBase(), entries, p.mergedAconfigFiles) }, }, }} diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go index 47fd8f439..306d65e29 100644 --- a/fuzz/fuzz_common.go +++ b/fuzz/fuzz_common.go @@ -449,10 +449,10 @@ func IsValidFrameworkForModule(targetFramework Framework, lang Lang, moduleFrame } } -func IsValid(fuzzModule FuzzModule) bool { +func IsValid(ctx android.ConfigAndErrorContext, fuzzModule FuzzModule) bool { // Discard ramdisk + vendor_ramdisk + recovery modules, they're duplicates of // fuzz targets we're going to package anyway. - if !fuzzModule.Enabled() || fuzzModule.InRamdisk() || fuzzModule.InVendorRamdisk() || fuzzModule.InRecovery() { + if !fuzzModule.Enabled(ctx) || fuzzModule.InRamdisk() || fuzzModule.InVendorRamdisk() || fuzzModule.InRecovery() { return false } diff --git a/genrule/genrule.go b/genrule/genrule.go index 4ff82e6a6..dd980cbb0 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -180,9 +180,6 @@ type Module struct { subName string subDir string - - // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo - mergedAconfigFiles map[string]android.Paths } type taskFunc func(ctx android.ModuleContext, rawCommand string, srcFiles android.Paths) []generateTask @@ -299,7 +296,7 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) { case android.HostToolProvider: // A HostToolProvider provides the path to a tool, which will be copied // into the sandbox. - if !t.(android.Module).Enabled() { + if !t.(android.Module).Enabled(ctx) { if ctx.Config().AllowMissingDependencies() { ctx.AddMissingDependencies([]string{tool}) } else { @@ -588,24 +585,6 @@ func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) { }) g.outputDeps = android.Paths{phonyFile} } - android.CollectDependencyAconfigFiles(ctx, &g.mergedAconfigFiles) -} - -func (g *Module) AndroidMkEntries() []android.AndroidMkEntries { - ret := android.AndroidMkEntries{ - OutputFile: android.OptionalPathForPath(g.outputFiles[0]), - ExtraEntries: []android.AndroidMkExtraEntriesFunc{ - func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { - android.SetAconfigFileMkEntries(g.AndroidModuleBase(), entries, g.mergedAconfigFiles) - }, - }, - } - - return []android.AndroidMkEntries{ret} -} - -func (g *Module) AndroidModuleBase() *android.ModuleBase { - return &g.ModuleBase } // Collect information for opening IDE project files in java/jdeps.go. diff --git a/java/aar.go b/java/aar.go index 47c64bfe8..07392f6e5 100644 --- a/java/aar.go +++ b/java/aar.go @@ -1014,9 +1014,6 @@ type AARImport struct { usesLibrary classLoaderContexts dexpreopt.ClassLoaderContextMap - - // Single aconfig "cache file" merged from this module and all dependencies. - mergedAconfigFiles map[string]android.Paths } var _ android.OutputFileProducer = (*AARImport)(nil) @@ -1386,7 +1383,6 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { android.SetProvider(ctx, JniPackageProvider, JniPackageInfo{ JniPackages: a.jniPackages, }) - android.CollectDependencyAconfigFiles(ctx, &a.mergedAconfigFiles) } func (a *AARImport) HeaderJars() android.Paths { diff --git a/java/androidmk.go b/java/androidmk.go index 9cd0bafea..43160741b 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -17,7 +17,6 @@ package java import ( "fmt" "io" - "strings" "android/soong/android" @@ -124,7 +123,6 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries { if library.dexpreopter.configPath != nil { entries.SetPath("LOCAL_SOONG_DEXPREOPT_CONFIG", library.dexpreopter.configPath) } - android.SetAconfigFileMkEntries(&library.ModuleBase, entries, library.mergedAconfigFiles) }, }, }) @@ -298,7 +296,6 @@ func (binary *Binary) AndroidMkEntries() []android.AndroidMkEntries { if len(binary.dexpreopter.builtInstalled) > 0 { entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", binary.dexpreopter.builtInstalled) } - android.SetAconfigFileMkEntries(&binary.ModuleBase, entries, binary.mergedAconfigFiles) }, }, ExtraFooters: []android.AndroidMkExtraFootersFunc{ @@ -415,23 +412,6 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries { if app.embeddedJniLibs { jniSymbols := app.JNISymbolsInstalls(app.installPathForJNISymbols.String()) entries.SetString("LOCAL_SOONG_JNI_LIBS_SYMBOLS", jniSymbols.String()) - } else { - for _, jniLib := range app.jniLibs { - entries.AddStrings("LOCAL_SOONG_JNI_LIBS_"+jniLib.target.Arch.ArchType.String(), jniLib.name) - var partitionTag string - - // Mimic the creation of partition_tag in build/make, - // which defaults to an empty string when the partition is system. - // Otherwise, capitalize with a leading _ - if jniLib.partition == "system" { - partitionTag = "" - } else { - split := strings.Split(jniLib.partition, "/") - partitionTag = "_" + strings.ToUpper(split[len(split)-1]) - } - entries.AddStrings("LOCAL_SOONG_JNI_LIBS_PARTITION_"+jniLib.target.Arch.ArchType.String(), - jniLib.name+":"+partitionTag) - } } if len(app.jniCoverageOutputs) > 0 { @@ -450,10 +430,6 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries { entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", app.linter.reports) - if app.Name() != "framework-res" { - android.SetAconfigFileMkEntries(&app.ModuleBase, entries, app.mergedAconfigFiles) - } - entries.AddStrings("LOCAL_SOONG_LOGTAGS_FILES", app.logtagsSrcs.Strings()...) }, }, @@ -531,7 +507,6 @@ func (a *AndroidLibrary) AndroidMkEntries() []android.AndroidMkEntries { entries.SetPath("LOCAL_FULL_MANIFEST_FILE", a.mergedManifestFile) entries.SetPath("LOCAL_SOONG_EXPORT_PROGUARD_FLAGS", a.combinedExportedProguardFlagsFile) entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", true) - android.SetAconfigFileMkEntries(&a.ModuleBase, entries, a.mergedAconfigFiles) }) return entriesList diff --git a/java/androidmk_test.go b/java/androidmk_test.go index 1232cd1ee..875e06f11 100644 --- a/java/androidmk_test.go +++ b/java/androidmk_test.go @@ -19,9 +19,6 @@ import ( "testing" "android/soong/android" - "android/soong/cc" - - "github.com/google/blueprint/proptools" ) func TestRequired(t *testing.T) { @@ -161,8 +158,8 @@ func TestJavaSdkLibrary_RequireXmlPermissionFile(t *testing.T) { moduleName string expected []string }{ - {"foo-shared_library", []string{"foo-shared_library.xml"}}, - {"foo-no_shared_library", nil}, + {"foo-shared_library", []string{"foo-shared_library.impl", "foo-shared_library.xml"}}, + {"foo-no_shared_library", []string{"foo-no_shared_library.impl"}}, } for _, tc := range testCases { mod := result.ModuleForTests(tc.moduleName, "android_common").Module() @@ -255,149 +252,3 @@ func TestGetOverriddenPackages(t *testing.T) { android.AssertDeepEquals(t, "overrides property", expected.overrides, actual) } } - -func TestJniPartition(t *testing.T) { - bp := ` - cc_library { - name: "libjni_system", - system_shared_libs: [], - sdk_version: "current", - stl: "none", - } - - cc_library { - name: "libjni_system_ext", - system_shared_libs: [], - sdk_version: "current", - stl: "none", - system_ext_specific: true, - } - - cc_library { - name: "libjni_odm", - system_shared_libs: [], - sdk_version: "current", - stl: "none", - device_specific: true, - } - - cc_library { - name: "libjni_product", - system_shared_libs: [], - sdk_version: "current", - stl: "none", - product_specific: true, - } - - cc_library { - name: "libjni_vendor", - system_shared_libs: [], - sdk_version: "current", - stl: "none", - soc_specific: true, - } - - android_app { - name: "test_app_system_jni_system", - privileged: true, - platform_apis: true, - certificate: "platform", - jni_libs: ["libjni_system"], - } - - android_app { - name: "test_app_system_jni_system_ext", - privileged: true, - platform_apis: true, - certificate: "platform", - jni_libs: ["libjni_system_ext"], - } - - android_app { - name: "test_app_system_ext_jni_system", - privileged: true, - platform_apis: true, - certificate: "platform", - jni_libs: ["libjni_system"], - system_ext_specific: true - } - - android_app { - name: "test_app_system_ext_jni_system_ext", - sdk_version: "core_platform", - jni_libs: ["libjni_system_ext"], - system_ext_specific: true - } - - android_app { - name: "test_app_product_jni_product", - sdk_version: "core_platform", - jni_libs: ["libjni_product"], - product_specific: true - } - - android_app { - name: "test_app_vendor_jni_odm", - sdk_version: "core_platform", - jni_libs: ["libjni_odm"], - soc_specific: true - } - - android_app { - name: "test_app_odm_jni_vendor", - sdk_version: "core_platform", - jni_libs: ["libjni_vendor"], - device_specific: true - } - android_app { - name: "test_app_system_jni_multiple", - privileged: true, - platform_apis: true, - certificate: "platform", - jni_libs: ["libjni_system", "libjni_system_ext"], - } - android_app { - name: "test_app_vendor_jni_multiple", - sdk_version: "core_platform", - jni_libs: ["libjni_odm", "libjni_vendor"], - soc_specific: true - } - ` - arch := "arm64" - ctx := android.GroupFixturePreparers( - PrepareForTestWithJavaDefaultModules, - cc.PrepareForTestWithCcDefaultModules, - android.PrepareForTestWithAndroidMk, - android.FixtureModifyConfig(func(config android.Config) { - config.TestProductVariables.DeviceArch = proptools.StringPtr(arch) - }), - ). - RunTestWithBp(t, bp) - testCases := []struct { - name string - partitionNames []string - partitionTags []string - }{ - {"test_app_system_jni_system", []string{"libjni_system"}, []string{""}}, - {"test_app_system_jni_system_ext", []string{"libjni_system_ext"}, []string{"_SYSTEM_EXT"}}, - {"test_app_system_ext_jni_system", []string{"libjni_system"}, []string{""}}, - {"test_app_system_ext_jni_system_ext", []string{"libjni_system_ext"}, []string{"_SYSTEM_EXT"}}, - {"test_app_product_jni_product", []string{"libjni_product"}, []string{"_PRODUCT"}}, - {"test_app_vendor_jni_odm", []string{"libjni_odm"}, []string{"_ODM"}}, - {"test_app_odm_jni_vendor", []string{"libjni_vendor"}, []string{"_VENDOR"}}, - {"test_app_system_jni_multiple", []string{"libjni_system", "libjni_system_ext"}, []string{"", "_SYSTEM_EXT"}}, - {"test_app_vendor_jni_multiple", []string{"libjni_odm", "libjni_vendor"}, []string{"_ODM", "_VENDOR"}}, - } - - for _, test := range testCases { - t.Run(test.name, func(t *testing.T) { - mod := ctx.ModuleForTests(test.name, "android_common").Module() - entry := android.AndroidMkEntriesForTest(t, ctx.TestContext, mod)[0] - for i := range test.partitionNames { - actual := entry.EntryMap["LOCAL_SOONG_JNI_LIBS_PARTITION_"+arch][i] - expected := test.partitionNames[i] + ":" + test.partitionTags[i] - android.AssertStringEquals(t, "Expected and actual differ", expected, actual) - } - }) - } -} diff --git a/java/app.go b/java/app.go index 50d1a2f43..254fbf4fd 100644 --- a/java/app.go +++ b/java/app.go @@ -90,20 +90,17 @@ type appProperties struct { Stl *string `android:"arch_variant"` // Store native libraries uncompressed in the APK and set the android:extractNativeLibs="false" manifest - // flag so that they are used from inside the APK at runtime. Defaults to true for android_test modules unless - // sdk_version or min_sdk_version is set to a version that doesn't support it (<23), defaults to true for - // android_app modules that are embedded to APEXes, defaults to false for other module types where the native - // libraries are generally preinstalled outside the APK. + // flag so that they are used from inside the APK at runtime. This property is respected only for + // APKs built using android_test or android_test_helper_app. For other APKs, this property is ignored + // and native libraries are always embedded compressed. Use_embedded_native_libs *bool // Store dex files uncompressed in the APK and set the android:useEmbeddedDex="true" manifest attribute so that // they are used from inside the APK at runtime. Use_embedded_dex *bool - // Forces native libraries to always be packaged into the APK, - // Use_embedded_native_libs still selects whether they are stored uncompressed and aligned or compressed. - // True for android_test* modules. - AlwaysPackageNativeLibs bool `blueprint:"mutated"` + // Allows compressing of embedded native libs. Only for android_test and android_test_helper_app. + AllowCompressingNativeLibs bool `blueprint:"mutated"` // If set, find and merge all NOTICE files that this module and its dependencies have and store // it in the APK as an asset. @@ -403,14 +400,20 @@ func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVer // Returns true if the native libraries should be stored in the APK uncompressed and the // extractNativeLibs application flag should be set to false in the manifest. func (a *AndroidApp) useEmbeddedNativeLibs(ctx android.ModuleContext) bool { + var useEmbedded bool + if a.appProperties.AllowCompressingNativeLibs { + useEmbedded = BoolDefault(a.appProperties.Use_embedded_native_libs, true) + } else { + useEmbedded = true // always uncompress for non-test apps + } + minSdkVersion, err := a.MinSdkVersion(ctx).EffectiveVersion(ctx) if err != nil { ctx.PropertyErrorf("min_sdk_version", "invalid value %q: %s", a.MinSdkVersion(ctx), err) } + supported := minSdkVersion.FinalOrFutureInt() >= 23 - apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) - return (minSdkVersion.FinalOrFutureInt() >= 23 && Bool(a.appProperties.Use_embedded_native_libs)) || - !apexInfo.IsForPlatform() + return useEmbedded && supported } // Returns whether this module should have the dex file stored uncompressed in the APK. @@ -433,9 +436,23 @@ func (a *AndroidApp) shouldUncompressDex(ctx android.ModuleContext) bool { } func (a *AndroidApp) shouldEmbedJnis(ctx android.BaseModuleContext) bool { + // Always! + return true +} + +func (a *AndroidApp) shouldCollectRecursiveNativeDeps(ctx android.ModuleContext) bool { + // JNI libs are always embedded, but whether to embed their transitive dependencies as well + // or not is determined here. For most of the apps built here (using the platform build + // system), we don't need to collect the transitive deps because they will anyway be + // available in the partition image where the app will be installed to. + // + // Collecting transitive dependencies is required only for unbundled apps. apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) - return ctx.Config().UnbundledBuild() || Bool(a.appProperties.Use_embedded_native_libs) || - !apexInfo.IsForPlatform() || a.appProperties.AlwaysPackageNativeLibs + apkInApex := !apexInfo.IsForPlatform() + testApp := a.appProperties.AllowCompressingNativeLibs + unbundledApp := ctx.Config().UnbundledBuild() || apkInApex || testApp + + return a.shouldEmbedJnis(ctx) && unbundledApp } func generateAaptRenamePackageFlags(packageName string, renameResourcesPackage bool) []string { @@ -829,7 +846,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { dexJarFile, packageResources := a.dexBuildActions(ctx) - jniLibs, prebuiltJniPackages, certificates := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis)) + jniLibs, prebuiltJniPackages, certificates := collectAppDeps(ctx, a, a.shouldCollectRecursiveNativeDeps(ctx), !Bool(a.appProperties.Jni_uses_platform_apis)) jniJarFile := a.jniBuildActions(jniLibs, prebuiltJniPackages, ctx) if ctx.Failed() { @@ -1400,8 +1417,7 @@ func AndroidTestFactory() android.Module { module.Module.properties.Instrument = true module.Module.properties.Supports_static_instrumentation = true module.Module.properties.Installable = proptools.BoolPtr(true) - module.appProperties.Use_embedded_native_libs = proptools.BoolPtr(true) - module.appProperties.AlwaysPackageNativeLibs = true + module.appProperties.AllowCompressingNativeLibs = true module.Module.dexpreopter.isTest = true module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true) @@ -1456,8 +1472,7 @@ func AndroidTestHelperAppFactory() android.Module { module.Module.dexProperties.Optimize.EnabledByDefault = true module.Module.properties.Installable = proptools.BoolPtr(true) - module.appProperties.Use_embedded_native_libs = proptools.BoolPtr(true) - module.appProperties.AlwaysPackageNativeLibs = true + module.appProperties.AllowCompressingNativeLibs = true module.Module.dexpreopter.isTest = true module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true) diff --git a/java/app_import.go b/java/app_import.go index bb07c423a..dc8470da7 100644 --- a/java/app_import.go +++ b/java/app_import.go @@ -87,9 +87,6 @@ type AndroidAppImport struct { hideApexVariantFromMake bool provenanceMetaDataFile android.OutputPath - - // Single aconfig "cache file" merged from this module and all dependencies. - mergedAconfigFiles map[string]android.Paths } type AndroidAppImportProperties struct { @@ -416,7 +413,6 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext artifactPath := android.PathForModuleSrc(ctx, *a.properties.Apk) a.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, artifactPath, a.installPath) } - android.CollectDependencyAconfigFiles(ctx, &a.mergedAconfigFiles) providePrebuiltInfo(ctx, prebuiltInfoProps{ diff --git a/java/app_import_test.go b/java/app_import_test.go index 5de50e794..496fc1308 100644 --- a/java/app_import_test.go +++ b/java/app_import_test.go @@ -509,7 +509,7 @@ func TestAndroidAppImport_ArchVariants(t *testing.T) { variant := ctx.ModuleForTests("foo", "android_common") if test.expected == "" { - if variant.Module().Enabled() { + if variant.Module().Enabled(android.PanickingConfigAndErrorContext(ctx)) { t.Error("module should have been disabled, but wasn't") } rule := variant.MaybeRule("genProvenanceMetaData") @@ -586,7 +586,7 @@ func TestAndroidAppImport_SoongConfigVariables(t *testing.T) { variant := ctx.ModuleForTests("foo", "android_common") if test.expected == "" { - if variant.Module().Enabled() { + if variant.Module().Enabled(android.PanickingConfigAndErrorContext(ctx)) { t.Error("module should have been disabled, but wasn't") } rule := variant.MaybeRule("genProvenanceMetaData") @@ -629,7 +629,7 @@ func TestAndroidAppImport_overridesDisabledAndroidApp(t *testing.T) { if !a.prebuilt.UsePrebuilt() { t.Errorf("prebuilt foo module is not active") } - if !a.Enabled() { + if !a.Enabled(android.PanickingConfigAndErrorContext(ctx)) { t.Errorf("prebuilt foo module is disabled") } } diff --git a/java/app_test.go b/java/app_test.go index a7c48a1ed..d6ba0f1dd 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -2013,8 +2013,8 @@ func TestJNIPackaging(t *testing.T) { packaged bool compressed bool }{ - {"app", false, false}, - {"app_noembed", false, false}, + {"app", true, false}, + {"app_noembed", true, false}, {"app_embed", true, false}, {"test", true, false}, {"test_noembed", true, true}, @@ -2043,6 +2043,44 @@ func TestJNIPackaging(t *testing.T) { } } +func TestJNITranstiveDepsInstallation(t *testing.T) { + ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` + android_app { + name: "app", + jni_libs: ["libjni"], + platform_apis: true, + } + + cc_library { + name: "libjni", + shared_libs: ["libplatform"], + system_shared_libs: [], + stl: "none", + required: ["librequired"], + } + + cc_library { + name: "libplatform", + system_shared_libs: [], + stl: "none", + } + + cc_library { + name: "librequired", + system_shared_libs: [], + stl: "none", + } + + `) + + app := ctx.ModuleForTests("app", "android_common") + jniLibZip := app.Output("jnilibs.zip") + android.AssertPathsEndWith(t, "embedd jni lib mismatch", []string{"libjni.so"}, jniLibZip.Implicits) + + install := app.Rule("Cp") + android.AssertPathsEndWith(t, "install dep mismatch", []string{"libplatform.so", "librequired.so"}, install.OrderOnly) +} + func TestJNISDK(t *testing.T) { ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` cc_library { @@ -3319,8 +3357,7 @@ func TestUsesLibraries(t *testing.T) { // These also include explicit `uses_libs`/`optional_uses_libs` entries, as they may be // propagated from dependencies. actualManifestFixerArgs := app.Output("manifest_fixer/AndroidManifest.xml").Args["args"] - expectManifestFixerArgs := `--extract-native-libs=true ` + - `--uses-library foo ` + + expectManifestFixerArgs := `--uses-library foo ` + `--uses-library com.non.sdk.lib ` + `--uses-library qux ` + `--uses-library quuz ` + @@ -4110,7 +4147,7 @@ func TestAppIncludesJniPackages(t *testing.T) { }, { name: "aary-no-use-embedded", - hasPackage: false, + hasPackage: true, }, } diff --git a/java/base.go b/java/base.go index 938ac5e82..0c2867177 100644 --- a/java/base.go +++ b/java/base.go @@ -537,9 +537,6 @@ type Module struct { // or the module should override Stem(). stem string - // Single aconfig "cache file" merged from this module and all dependencies. - mergedAconfigFiles map[string]android.Paths - // Values that will be set in the JarJarProvider data for jarjar repackaging, // and merged with our dependencies' rules. jarjarRenameRules map[string]string @@ -1682,7 +1679,11 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath j.dexJarFile = makeDexJarPathFromPath(dexOutputFile) // Dexpreopting - j.dexpreopt(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), dexOutputFile) + libName := android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()) + if j.SdkLibraryName() != nil && strings.HasSuffix(ctx.ModuleName(), ".impl") { + libName = strings.TrimSuffix(libName, ".impl") + } + j.dexpreopt(ctx, libName, dexOutputFile) outputFile = dexOutputFile } else { @@ -1730,8 +1731,6 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath ctx.CheckbuildFile(outputFile) - android.CollectDependencyAconfigFiles(ctx, &j.mergedAconfigFiles) - android.SetProvider(ctx, JavaInfoProvider, JavaInfo{ HeaderJars: android.PathsIfNonNil(j.headerJarFile), RepackagedHeaderJars: android.PathsIfNonNil(j.repackagedHeaderJarFile), diff --git a/java/boot_jars.go b/java/boot_jars.go index 5d40ec389..6223dede8 100644 --- a/java/boot_jars.go +++ b/java/boot_jars.go @@ -21,8 +21,8 @@ import ( // isActiveModule returns true if the given module should be considered for boot // jars, i.e. if it's enabled and the preferred one in case of source and // prebuilt alternatives. -func isActiveModule(module android.Module) bool { - if !module.Enabled() { +func isActiveModule(ctx android.ConfigAndErrorContext, module android.Module) bool { + if !module.Enabled(ctx) { return false } return android.IsModulePreferred(module) diff --git a/java/bootclasspath.go b/java/bootclasspath.go index c7dc3afae..77ddf5c05 100644 --- a/java/bootclasspath.go +++ b/java/bootclasspath.go @@ -127,7 +127,10 @@ func reportMissingVariationDependency(ctx android.BottomUpMutatorContext, variat // added by addDependencyOntoApexModulePair. func gatherApexModulePairDepsWithTag(ctx android.BaseModuleContext, tag blueprint.DependencyTag) []android.Module { var modules []android.Module - ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) { + isActiveModulePred := func(module android.Module) bool { + return isActiveModule(ctx, module) + } + ctx.VisitDirectDepsIf(isActiveModulePred, func(module android.Module) { t := ctx.OtherModuleDependencyTag(module) if t == tag { modules = append(modules, module) diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index cc3da7656..82a34ca9d 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -474,7 +474,7 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo // Only perform a consistency check if this module is the active module. That will prevent an // unused prebuilt that was created without instrumentation from breaking an instrumentation // build. - if isActiveModule(ctx.Module()) { + if isActiveModule(ctx, ctx.Module()) { b.bootclasspathFragmentPropertyCheck(ctx) } @@ -519,7 +519,7 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo // empty string if this module should not provide a boot image profile. func (b *BootclasspathFragmentModule) getProfileProviderApex(ctx android.BaseModuleContext) string { // Only use the profile from the module that is preferred. - if !isActiveModule(ctx.Module()) { + if !isActiveModule(ctx, ctx.Module()) { return "" } @@ -590,7 +590,7 @@ func (b *BootclasspathFragmentModule) configuredJars(ctx android.ModuleContext) // So ignore it even if it is not in PRODUCT_APEX_BOOT_JARS. // TODO(b/202896428): Add better way to handle this. _, unknown = android.RemoveFromList("android.car-module", unknown) - if isActiveModule(ctx.Module()) && len(unknown) > 0 { + if isActiveModule(ctx, ctx.Module()) && len(unknown) > 0 { ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_BOOT_JARS", unknown) } } diff --git a/java/code_metadata_test.go b/java/code_metadata_test.go index 0ef348afe..99b1f5226 100644 --- a/java/code_metadata_test.go +++ b/java/code_metadata_test.go @@ -7,6 +7,7 @@ import ( "android/soong/android" soongTesting "android/soong/testing" "android/soong/testing/code_metadata_internal_proto" + "google.golang.org/protobuf/proto" ) diff --git a/java/dexpreopt.go b/java/dexpreopt.go index 25e95db14..1acac1b40 100644 --- a/java/dexpreopt.go +++ b/java/dexpreopt.go @@ -196,8 +196,10 @@ func disableSourceApexVariant(ctx android.BaseModuleContext) bool { } apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) psi := android.PrebuiltSelectionInfoMap{} - ctx.VisitDirectDepsWithTag(android.PrebuiltDepTag, func(am android.Module) { - psi, _ = android.OtherModuleProvider(ctx, am, android.PrebuiltSelectionInfoProvider) + ctx.VisitDirectDeps(func(am android.Module) { + if prebuiltSelectionInfo, ok := android.OtherModuleProvider(ctx, am, android.PrebuiltSelectionInfoProvider); ok { + psi = prebuiltSelectionInfo + } }) // Find the apex variant for this module _, apexVariantsWithoutTestApexes, _ := android.ListSetDifference(apexInfo.InApexVariants, apexInfo.TestApexes) diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index f7e3cb93a..7229ca02d 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -562,7 +562,7 @@ func gatherBootclasspathFragments(ctx android.ModuleContext) map[string]android. return ctx.Config().Once(dexBootJarsFragmentsKey, func() interface{} { fragments := make(map[string]android.Module) ctx.WalkDeps(func(child, parent android.Module) bool { - if !isActiveModule(child) { + if !isActiveModule(ctx, child) { return false } tag := ctx.OtherModuleDependencyTag(child) @@ -1125,7 +1125,7 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p image.unstrippedInstalls = unstrippedInstalls // Only set the licenseMetadataFile from the active module. - if isActiveModule(ctx.Module()) { + if isActiveModule(ctx, ctx.Module()) { image.licenseMetadataFile = android.OptionalPathForPath(ctx.LicenseMetadataFile()) } diff --git a/java/droidstubs.go b/java/droidstubs.go index 730be14b0..ca81343f0 100644 --- a/java/droidstubs.go +++ b/java/droidstubs.go @@ -106,9 +106,6 @@ type Droidstubs struct { everythingArtifacts stubsArtifacts exportableArtifacts stubsArtifacts - // Single aconfig "cache file" merged from this module and all dependencies. - mergedAconfigFiles map[string]android.Paths - exportableApiFile android.WritablePath exportableRemovedApiFile android.WritablePath } @@ -1342,7 +1339,6 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) { rule.Build("nullabilityWarningsCheck", "nullability warnings check") } - android.CollectDependencyAconfigFiles(ctx, &d.mergedAconfigFiles) } func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) { diff --git a/java/fuzz.go b/java/fuzz.go index fb31ce794..d37c55804 100644 --- a/java/fuzz.go +++ b/java/fuzz.go @@ -179,7 +179,7 @@ func (s *javaFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { javaFuzzModule.ApexModuleBase, } - if ok := fuzz.IsValid(fuzzModuleValidator); !ok { + if ok := fuzz.IsValid(ctx, fuzzModuleValidator); !ok { return } diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go index ae587eac3..cab5402e9 100644 --- a/java/hiddenapi_modular.go +++ b/java/hiddenapi_modular.go @@ -1428,7 +1428,7 @@ func deferReportingMissingBootDexJar(ctx android.ModuleContext, module android.M // should not contribute to anything. So, rather than have a missing dex jar cause a Soong // failure defer the error reporting to Ninja. Unless the prebuilt build target is explicitly // built Ninja should never use the dex jar file. - if !isActiveModule(module) { + if !isActiveModule(ctx, module) { return true } diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go index 8cb78cd54..7d21b7a61 100644 --- a/java/hiddenapi_singleton.go +++ b/java/hiddenapi_singleton.go @@ -150,6 +150,10 @@ func isModuleInConfiguredList(ctx android.BaseModuleContext, module android.Modu // Strip a prebuilt_ prefix so that this can match a prebuilt module that has not been renamed. name = android.RemoveOptionalPrebuiltPrefix(name) + // Strip the ".impl" suffix, so that the implementation library of the java_sdk_library is + // treated identical to the top level java_sdk_library. + name = strings.TrimSuffix(name, ".impl") + // Ignore any module that is not listed in the boot image configuration. index := configuredBootJars.IndexOfJar(name) if index == -1 { diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go index c1fee2184..330013ee4 100644 --- a/java/hiddenapi_singleton_test.go +++ b/java/hiddenapi_singleton_test.go @@ -303,7 +303,7 @@ func TestHiddenAPIEncoding_JavaSdkLibrary(t *testing.T) { `) checkDexEncoded := func(t *testing.T, name, unencodedDexJar, encodedDexJar string) { - moduleForTests := result.ModuleForTests(name, "android_common") + moduleForTests := result.ModuleForTests(name+".impl", "android_common") encodeDexRule := moduleForTests.Rule("hiddenAPIEncodeDex") actualUnencodedDexJar := encodeDexRule.Input @@ -319,18 +319,8 @@ func TestHiddenAPIEncoding_JavaSdkLibrary(t *testing.T) { // The java_library embedded with the java_sdk_library must be dex encoded. t.Run("foo", func(t *testing.T) { - expectedUnencodedDexJar := "out/soong/.intermediates/foo/android_common/aligned/foo.jar" - expectedEncodedDexJar := "out/soong/.intermediates/foo/android_common/hiddenapi/foo.jar" + expectedUnencodedDexJar := "out/soong/.intermediates/foo.impl/android_common/aligned/foo.jar" + expectedEncodedDexJar := "out/soong/.intermediates/foo.impl/android_common/hiddenapi/foo.jar" checkDexEncoded(t, "foo", expectedUnencodedDexJar, expectedEncodedDexJar) }) - - // The dex jar of the child implementation java_library of the java_sdk_library is not currently - // dex encoded. - t.Run("foo.impl", func(t *testing.T) { - fooImpl := result.ModuleForTests("foo.impl", "android_common") - encodeDexRule := fooImpl.MaybeRule("hiddenAPIEncodeDex") - if encodeDexRule.Rule != nil { - t.Errorf("foo.impl is not expected to be encoded") - } - }) } diff --git a/java/jacoco.go b/java/jacoco.go index a820b3855..696a0cc37 100644 --- a/java/jacoco.go +++ b/java/jacoco.go @@ -53,7 +53,7 @@ func jacocoDepsMutator(ctx android.BottomUpMutatorContext) { } j, ok := ctx.Module().(instrumentable) - if !ctx.Module().Enabled() || !ok { + if !ctx.Module().Enabled(ctx) || !ok { return } diff --git a/java/java.go b/java/java.go index 30581f265..fc7e5c5a3 100644 --- a/java/java.go +++ b/java/java.go @@ -368,6 +368,17 @@ type dependencyTag struct { static bool } +var _ android.SkipToTransitiveDepsTag = (*dependencyTag)(nil) + +func (depTag dependencyTag) SkipToTransitiveDeps() bool { + // jni_libs are not installed because they are always embedded into the app. However, + // transitive deps of jni_libs themselves should be installed along with the app. + if IsJniDepTag(depTag) { + return true + } + return false +} + // installDependencyTag is a dependency tag that is annotated to cause the installed files of the // dependency to be installed when the parent module is installed. type installDependencyTag struct { @@ -674,6 +685,10 @@ type Library struct { var _ android.ApexModule = (*Library)(nil) +func (j *Library) CheckDepsMinSdkVersion(ctx android.ModuleContext) { + CheckMinSdkVersion(ctx, j) +} + // Provides access to the list of permitted packages from apex boot jars. type PermittedPackagesForUpdatableBootJars interface { PermittedPackagesForUpdatableBootJars() []string @@ -902,6 +917,12 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.minSdkVersion = j.MinSdkVersion(ctx) j.maxSdkVersion = j.MaxSdkVersion(ctx) + // Check min_sdk_version of the transitive dependencies if this module is created from + // java_sdk_library. + if j.deviceProperties.Min_sdk_version != nil && j.SdkLibraryName() != nil { + j.CheckDepsMinSdkVersion(ctx) + } + // SdkLibrary.GenerateAndroidBuildActions(ctx) sets the stubsLinkType to Unknown. // If the stubsLinkType has already been set to Unknown, the stubsLinkType should // not be overridden. @@ -932,8 +953,12 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.checkSdkVersions(ctx) j.checkHeadersOnly(ctx) if ctx.Device() { + libName := j.Name() + if j.SdkLibraryName() != nil && strings.HasSuffix(libName, ".impl") { + libName = proptools.String(j.SdkLibraryName()) + } j.dexpreopter.installPath = j.dexpreopter.getInstallPath( - ctx, j.Name(), android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar")) + ctx, libName, android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar")) j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary setUncompressDex(ctx, &j.dexpreopter, &j.dexer) j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex @@ -944,8 +969,24 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { } j.compile(ctx, nil, nil, nil) - exclusivelyForApex := !apexInfo.IsForPlatform() - if (Bool(j.properties.Installable) || ctx.Host()) && !exclusivelyForApex { + // If this module is an impl library created from java_sdk_library, + // install the files under the java_sdk_library module outdir instead of this module outdir. + if j.SdkLibraryName() != nil && strings.HasSuffix(j.Name(), ".impl") { + j.setInstallRules(ctx, proptools.String(j.SdkLibraryName())) + } else { + j.setInstallRules(ctx, ctx.ModuleName()) + } + + android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{ + TestOnly: Bool(j.sourceProperties.Test_only), + TopLevelTarget: j.sourceProperties.Top_level_test_target, + }) +} + +func (j *Library) setInstallRules(ctx android.ModuleContext, installModuleName string) { + apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) + + if (Bool(j.properties.Installable) || ctx.Host()) && apexInfo.IsForPlatform() { var extraInstallDeps android.InstallPaths if j.InstallMixin != nil { extraInstallDeps = j.InstallMixin(ctx, j.outputFile) @@ -962,22 +1003,27 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { if !ctx.Host() { archDir = ctx.DeviceConfig().DeviceArch() } - installDir = android.PathForModuleInstall(ctx, ctx.ModuleName(), archDir) + installDir = android.PathForModuleInstall(ctx, installModuleName, archDir) } else { installDir = android.PathForModuleInstall(ctx, "framework") } j.installFile = ctx.InstallFile(installDir, j.Stem()+".jar", j.outputFile, extraInstallDeps...) } - - android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{ - TestOnly: Bool(j.sourceProperties.Test_only), - TopLevelTarget: j.sourceProperties.Top_level_test_target, - }) } func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) { j.usesLibrary.deps(ctx, false) j.deps(ctx) + + if j.SdkLibraryName() != nil && strings.HasSuffix(j.Name(), ".impl") { + if dexpreopt.IsDex2oatNeeded(ctx) { + dexpreopt.RegisterToolDeps(ctx) + } + prebuiltSdkLibExists := ctx.OtherModuleExists(android.PrebuiltNameFromSource(proptools.String(j.SdkLibraryName()))) + if prebuiltSdkLibExists && ctx.OtherModuleExists("all_apex_contributions") { + ctx.AddDependency(ctx.Module(), android.AcDepTag, "all_apex_contributions") + } + } } const ( diff --git a/java/jdeps.go b/java/jdeps.go index 91f7ce715..340026318 100644 --- a/java/jdeps.go +++ b/java/jdeps.go @@ -48,7 +48,7 @@ func (j *jdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCont moduleInfos := make(map[string]android.IdeInfo) ctx.VisitAllModules(func(module android.Module) { - if !module.Enabled() { + if !module.Enabled(ctx) { return } diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go index 37ff6395c..0d2acaea0 100644 --- a/java/platform_bootclasspath_test.go +++ b/java/platform_bootclasspath_test.go @@ -353,7 +353,7 @@ func TestPlatformBootclasspath_HiddenAPIMonolithicFiles(t *testing.T) { // All the intermediate rules use the same inputs. expectedIntermediateInputs := ` - out/soong/.intermediates/bar/android_common/javac/bar.jar + out/soong/.intermediates/bar.impl/android_common/javac/bar.jar out/soong/.intermediates/foo-hiddenapi-annotations/android_common/javac/foo-hiddenapi-annotations.jar out/soong/.intermediates/foo/android_common/javac/foo.jar ` diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go index 2fc6c02a6..99fa092be 100644 --- a/java/platform_compat_config.go +++ b/java/platform_compat_config.go @@ -19,6 +19,7 @@ import ( "path/filepath" "android/soong/android" + "github.com/google/blueprint" "github.com/google/blueprint/proptools" ) @@ -233,7 +234,7 @@ func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.Singlet var compatConfigMetadata android.Paths ctx.VisitAllModules(func(module android.Module) { - if !module.Enabled() { + if !module.Enabled(ctx) { return } if c, ok := module.(platformCompatConfigMetadataProvider); ok { diff --git a/java/sdk_library.go b/java/sdk_library.go index 113071fbb..677b32a5e 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -950,6 +950,10 @@ type commonToSdkLibraryAndImport struct { // Path to the header jars of the implementation library // This is non-empty only when api_only is false. implLibraryHeaderJars android.Paths + + // The reference to the implementation library created by the source module. + // Is nil if the source module does not exist. + implLibraryModule *Library } func (c *commonToSdkLibraryAndImport) initCommon(module commonSdkLibraryAndImportModule) { @@ -996,6 +1000,10 @@ func (c *commonToSdkLibraryAndImport) generateCommonBuildActions(ctx android.Mod c.doctagPaths = android.PathsForModuleSrc(ctx, c.commonSdkLibraryProperties.Doctag_files) } +func (c *commonToSdkLibraryAndImport) getImplLibraryModule() *Library { + return c.implLibraryModule +} + // Module name of the runtime implementation library func (c *commonToSdkLibraryAndImport) implLibraryModuleName() string { return c.module.RootLibraryName() + ".impl" @@ -1372,6 +1380,8 @@ type SdkLibraryDependency interface { // sharedLibrary returns true if this can be used as a shared library. sharedLibrary() bool + + getImplLibraryModule() *Library } type SdkLibrary struct { @@ -1383,6 +1393,8 @@ type SdkLibrary struct { scopeToProperties map[*apiScope]*ApiScopeProperties commonToSdkLibraryAndImport + + builtInstalledForApex []dexpreopterInstall } var _ SdkLibraryDependency = (*SdkLibrary)(nil) @@ -1391,6 +1403,20 @@ func (module *SdkLibrary) generateTestAndSystemScopesByDefault() bool { return module.sdkLibraryProperties.Generate_system_and_test_apis } +func (module *SdkLibrary) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath { + if module.implLibraryModule != nil { + return module.implLibraryModule.DexJarBuildPath(ctx) + } + return makeUnsetDexJarPath() +} + +func (module *SdkLibrary) DexJarInstallPath() android.Path { + if module.implLibraryModule != nil { + return module.implLibraryModule.DexJarInstallPath() + } + return nil +} + func (module *SdkLibrary) getGeneratedApiScopes(ctx android.EarlyModuleContext) apiScopes { // Check to see if any scopes have been explicitly enabled. If any have then all // must be. @@ -1442,6 +1468,10 @@ func (module *SdkLibrary) getGeneratedApiScopes(ctx android.EarlyModuleContext) var _ android.ModuleWithMinSdkVersionCheck = (*SdkLibrary)(nil) func (module *SdkLibrary) CheckMinSdkVersion(ctx android.ModuleContext) { + CheckMinSdkVersion(ctx, &module.Library) +} + +func CheckMinSdkVersion(ctx android.ModuleContext, module *Library) { android.CheckMinSdkVersion(ctx, module.MinSdkVersion(ctx), func(c android.ModuleContext, do android.PayloadDepsCallback) { ctx.WalkDeps(func(child android.Module, parent android.Module) bool { isExternal := !module.depIsInSameApex(ctx, child) @@ -1538,10 +1568,6 @@ func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { m += "Please see the documentation of the prebuilt_apis module type (and a usage example in prebuilts/sdk) for a convenient way to generate these." ctx.ModuleErrorf(m) } - if module.requiresRuntimeImplementationLibrary() { - // Only add the deps for the library if it is actually going to be built. - module.Library.deps(ctx) - } } func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) { @@ -1550,7 +1576,7 @@ func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) { return paths, err } if module.requiresRuntimeImplementationLibrary() { - return module.Library.OutputFiles(tag) + return module.implLibraryModule.OutputFiles(tag) } if tag == "" { return nil, nil @@ -1565,18 +1591,12 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) // TODO (b/331665856): Implement a principled solution for this. module.HideFromMake() } - if proptools.String(module.deviceProperties.Min_sdk_version) != "" { - module.CheckMinSdkVersion(ctx) - } module.generateCommonBuildActions(ctx) - // Only build an implementation library if required. - if module.requiresRuntimeImplementationLibrary() { - // stubsLinkType must be set before calling Library.GenerateAndroidBuildActions - module.Library.stubsLinkType = Unknown - module.Library.GenerateAndroidBuildActions(ctx) - } + module.stem = proptools.StringDefault(module.overridableProperties.Stem, ctx.ModuleName()) + + module.provideHiddenAPIPropertyInfo(ctx) // Collate the components exported by this module. All scope specific modules are exported but // the impl and xml component modules are not. @@ -1603,10 +1623,40 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) if tag == implLibraryTag { if dep, ok := android.OtherModuleProvider(ctx, to, JavaInfoProvider); ok { module.implLibraryHeaderJars = append(module.implLibraryHeaderJars, dep.HeaderJars...) + module.implLibraryModule = to.(*Library) + android.SetProvider(ctx, JavaInfoProvider, dep) } } }) + apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) + if !apexInfo.IsForPlatform() { + module.hideApexVariantFromMake = true + } + + if module.implLibraryModule != nil { + if ctx.Device() { + module.classesJarPaths = android.Paths{module.implLibraryModule.implementationJarFile} + module.bootDexJarPath = module.implLibraryModule.bootDexJarPath + module.uncompressDexState = module.implLibraryModule.uncompressDexState + module.active = module.implLibraryModule.active + } + + module.outputFile = module.implLibraryModule.outputFile + module.dexJarFile = makeDexJarPathFromPath(module.implLibraryModule.dexJarFile.Path()) + module.headerJarFile = module.implLibraryModule.headerJarFile + module.implementationAndResourcesJar = module.implLibraryModule.implementationAndResourcesJar + module.builtInstalledForApex = module.implLibraryModule.builtInstalledForApex + module.dexpreopter.configPath = module.implLibraryModule.dexpreopter.configPath + module.dexpreopter.outputProfilePathOnHost = module.implLibraryModule.dexpreopter.outputProfilePathOnHost + + if !module.Host() { + module.hostdexInstallFile = module.implLibraryModule.hostdexInstallFile + } + + android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: module.implLibraryModule.uniqueSrcFiles.Strings()}) + } + // Make the set of components exported by this module available for use elsewhere. exportedComponentInfo := android.ExportedComponentsInfo{Components: android.SortedKeys(exportedComponents)} android.SetProvider(ctx, android.ExportedComponentsInfoProvider, exportedComponentInfo) @@ -1636,13 +1686,18 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) android.SetProvider(ctx, android.AdditionalSdkInfoProvider, android.AdditionalSdkInfo{additionalSdkInfo}) } +func (module *SdkLibrary) BuiltInstalledForApex() []dexpreopterInstall { + return module.builtInstalledForApex +} + func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries { if !module.requiresRuntimeImplementationLibrary() { return nil } entriesList := module.Library.AndroidMkEntries() + entries := &entriesList[0] + entries.Required = append(entries.Required, module.implLibraryModuleName()) if module.sharedLibrary() { - entries := &entriesList[0] entries.Required = append(entries.Required, module.xmlPermissionsModuleName()) } return entriesList @@ -1763,20 +1818,21 @@ func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) Libs []string Static_libs []string Apex_available []string + Stem *string }{ Name: proptools.StringPtr(module.implLibraryModuleName()), Visibility: visibility, // Set the instrument property to ensure it is instrumented when instrumentation is required. Instrument: true, - // Set the impl_only libs. Note that the module's "Libs" get appended as well, via the - // addition of &module.properties below. - Libs: module.sdkLibraryProperties.Impl_only_libs, - // Set the impl_only static libs. Note that the module's "static_libs" get appended as well, via the - // addition of &module.properties below. - Static_libs: module.sdkLibraryProperties.Impl_only_static_libs, + + Libs: append(module.properties.Libs, module.sdkLibraryProperties.Impl_only_libs...), + + Static_libs: append(module.properties.Static_libs, module.sdkLibraryProperties.Impl_only_static_libs...), // Pass the apex_available settings down so that the impl library can be statically // embedded within a library that is added to an APEX. Needed for updatable-media. Apex_available: module.ApexAvailable(), + + Stem: proptools.StringPtr(module.Name()), } properties := []interface{}{ @@ -2167,6 +2223,9 @@ func (module *SdkLibrary) DepIsInSameApex(mctx android.BaseModuleContext, dep an if depTag == xmlPermissionsFileTag { return true } + if dep.Name() == module.implLibraryModuleName() { + return true + } return module.Library.DepIsInSameApex(mctx, dep) } @@ -2294,7 +2353,7 @@ func (module *SdkLibrary) getApiDir() string { // once for public API level and once for system API level func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookContext) { // If the module has been disabled then don't create any child modules. - if !module.Enabled() { + if !module.Enabled(mctx) { return } @@ -2592,10 +2651,6 @@ type SdkLibraryImport struct { commonToSdkLibraryAndImport - // The reference to the implementation library created by the source module. - // Is nil if the source module does not exist. - implLibraryModule *Library - // The reference to the xml permissions module created by the source module. // Is nil if the source module does not exist. xmlPermissionsFileModule *sdkLibraryXml @@ -3560,7 +3615,8 @@ func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMembe s.Min_device_sdk = sdk.commonSdkLibraryProperties.Min_device_sdk s.Max_device_sdk = sdk.commonSdkLibraryProperties.Max_device_sdk - if sdk.dexpreopter.dexpreoptProperties.Dex_preopt_result.Profile_guided { + implLibrary := sdk.getImplLibraryModule() + if implLibrary != nil && implLibrary.dexpreopter.dexpreoptProperties.Dex_preopt_result.Profile_guided { s.DexPreoptProfileGuided = proptools.BoolPtr(true) } } diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go index 34c63ac61..d240e701b 100644 --- a/java/sdk_library_test.go +++ b/java/sdk_library_test.go @@ -186,13 +186,13 @@ func TestJavaSdkLibrary(t *testing.T) { // test if quuz have created the api_contribution module result.ModuleForTests(apiScopePublic.stubsSourceModuleName("quuz")+".api.contribution", "") - fooDexJar := result.ModuleForTests("foo", "android_common").Rule("d8") - // tests if kotlinc generated files are NOT excluded from output of foo. - android.AssertStringDoesNotContain(t, "foo dex", fooDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module") + fooImplDexJar := result.ModuleForTests("foo.impl", "android_common").Rule("d8") + // tests if kotlinc generated files are NOT excluded from output of foo.impl. + android.AssertStringDoesNotContain(t, "foo.impl dex", fooImplDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module") - barDexJar := result.ModuleForTests("bar", "android_common").Rule("d8") - // tests if kotlinc generated files are excluded from output of bar. - android.AssertStringDoesContain(t, "bar dex", barDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module") + barImplDexJar := result.ModuleForTests("bar.impl", "android_common").Rule("d8") + // tests if kotlinc generated files are excluded from output of bar.impl. + android.AssertStringDoesContain(t, "bar.impl dex", barImplDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module") } func TestJavaSdkLibrary_UpdatableLibrary(t *testing.T) { @@ -1457,11 +1457,11 @@ func TestSdkLibrary_CheckMinSdkVersion(t *testing.T) { preparer.RunTestWithBp(t, ` java_sdk_library { name: "sdklib", - srcs: ["a.java"], - static_libs: ["util"], - min_sdk_version: "30", + srcs: ["a.java"], + static_libs: ["util"], + min_sdk_version: "30", unsafe_ignore_missing_latest_api: true, - } + } java_library { name: "util", diff --git a/provenance/provenance_singleton.go b/provenance/provenance_singleton.go index 97345afc3..679632c10 100644 --- a/provenance/provenance_singleton.go +++ b/provenance/provenance_singleton.go @@ -18,6 +18,7 @@ package provenance import ( "android/soong/android" + "github.com/google/blueprint" ) @@ -68,6 +69,15 @@ type provenanceInfoSingleton struct { func (p *provenanceInfoSingleton) GenerateBuildActions(context android.SingletonContext) { allMetaDataFiles := make([]android.Path, 0) + moduleFilter := func(module android.Module) bool { + if !module.Enabled(context) || module.IsSkipInstall() { + return false + } + if p, ok := module.(ProvenanceMetadata); ok { + return p.ProvenanceMetaDataFile().String() != "" + } + return false + } context.VisitAllModulesIf(moduleFilter, func(module android.Module) { if p, ok := module.(ProvenanceMetadata); ok { allMetaDataFiles = append(allMetaDataFiles, p.ProvenanceMetaDataFile()) @@ -91,16 +101,6 @@ func (p *provenanceInfoSingleton) GenerateBuildActions(context android.Singleton context.Phony("droidcore", android.PathForPhony(context, "provenance_metadata")) } -func moduleFilter(module android.Module) bool { - if !module.Enabled() || module.IsSkipInstall() { - return false - } - if p, ok := module.(ProvenanceMetadata); ok { - return p.ProvenanceMetaDataFile().String() != "" - } - return false -} - func GenerateArtifactProvenanceMetaData(ctx android.ModuleContext, artifactPath android.Path, installedFile android.InstallPath) android.OutputPath { onDevicePathOfInstalledFile := android.InstallPathToOnDevicePath(ctx, installedFile) artifactMetaDataFile := android.PathForIntermediates(ctx, "provenance_metadata", ctx.ModuleDir(), ctx.ModuleName(), "provenance_metadata.textproto") diff --git a/provenance/tools/Android.bp b/provenance/tools/Android.bp index 0eddd7636..b42e543de 100644 --- a/provenance/tools/Android.bp +++ b/provenance/tools/Android.bp @@ -23,11 +23,6 @@ python_binary_host { srcs: [ "gen_provenance_metadata.py", ], - version: { - py3: { - embedded_launcher: true, - }, - }, libs: [ "provenance_metadata_proto", "libprotobuf-python", diff --git a/python/binary.go b/python/binary.go index c84eeeedb..b935aba45 100644 --- a/python/binary.go +++ b/python/binary.go @@ -71,9 +71,6 @@ type PythonBinaryModule struct { installedDest android.Path androidMkSharedLibs []string - - // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo - mergedAconfigFiles map[string]android.Paths } var _ android.AndroidMkEntriesProvider = (*PythonBinaryModule)(nil) @@ -106,7 +103,6 @@ func (p *PythonBinaryModule) GenerateAndroidBuildActions(ctx android.ModuleConte p.buildBinary(ctx) p.installedDest = ctx.InstallFile(installDir(ctx, "bin", "", ""), p.installSource.Base(), p.installSource) - android.CollectDependencyAconfigFiles(ctx, &p.mergedAconfigFiles) } func (p *PythonBinaryModule) buildBinary(ctx android.ModuleContext) { @@ -170,7 +166,6 @@ func (p *PythonBinaryModule) AndroidMkEntries() []android.AndroidMkEntries { entries.SetString("LOCAL_MODULE_STEM", stem) entries.AddStrings("LOCAL_SHARED_LIBRARIES", p.androidMkSharedLibs...) entries.SetBool("LOCAL_CHECK_ELF_FILES", false) - android.SetAconfigFileMkEntries(&p.ModuleBase, entries, p.mergedAconfigFiles) }) return []android.AndroidMkEntries{entries} diff --git a/python/python.go b/python/python.go index e14fdf333..1ee533fa8 100644 --- a/python/python.go +++ b/python/python.go @@ -506,8 +506,8 @@ func (p *PythonLibraryModule) genModulePathMappings(ctx android.ModuleContext, p } for _, d := range expandedData { - if d.Ext() == pyExt || d.Ext() == protoExt { - ctx.PropertyErrorf("data", "found (.py|.proto) file: %q!", d.String()) + if d.Ext() == pyExt { + ctx.PropertyErrorf("data", "found (.py) file: %q!", d.String()) continue } runfilesPath := filepath.Join(pkgPath, d.Rel()) @@ -523,19 +523,19 @@ func (p *PythonLibraryModule) createSrcsZip(ctx android.ModuleContext, pkgPath s relativeRootMap := make(map[string]android.Paths) var protoSrcs android.Paths addPathMapping := func(path pathMapping) { - // handle proto sources separately - if path.src.Ext() == protoExt { - protoSrcs = append(protoSrcs, path.src) - } else { - relativeRoot := strings.TrimSuffix(path.src.String(), path.src.Rel()) - relativeRootMap[relativeRoot] = append(relativeRootMap[relativeRoot], path.src) - } + relativeRoot := strings.TrimSuffix(path.src.String(), path.src.Rel()) + relativeRootMap[relativeRoot] = append(relativeRootMap[relativeRoot], path.src) } // "srcs" or "data" properties may contain filegroups so it might happen that // the root directory for each source path is different. for _, path := range p.srcsPathMappings { - addPathMapping(path) + // handle proto sources separately + if path.src.Ext() == protoExt { + protoSrcs = append(protoSrcs, path.src) + } else { + addPathMapping(path) + } } for _, path := range p.dataPathMappings { addPathMapping(path) diff --git a/python/python_test.go b/python/python_test.go index c0b7295f9..6a6bd1d91 100644 --- a/python/python_test.go +++ b/python/python_test.go @@ -50,7 +50,7 @@ var ( " Second file: in module %s at path %q." noSrcFileErr = moduleVariantErrTemplate + "doesn't have any source files!" badSrcFileExtErr = moduleVariantErrTemplate + "srcs: found non (.py|.proto) file: %q!" - badDataFileExtErr = moduleVariantErrTemplate + "data: found (.py|.proto) file: %q!" + badDataFileExtErr = moduleVariantErrTemplate + "data: found (.py) file: %q!" bpFile = "Android.bp" data = []struct { diff --git a/python/test.go b/python/test.go index 2b939e7e4..85decf931 100644 --- a/python/test.go +++ b/python/test.go @@ -18,6 +18,7 @@ import ( "fmt" "android/soong/testing" + "github.com/google/blueprint/proptools" "android/soong/android" @@ -151,7 +152,6 @@ func (p *PythonTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext // just use buildBinary() so that the binary is not installed into the location // it would be for regular binaries. p.PythonLibraryModule.GenerateAndroidBuildActions(ctx) - android.CollectDependencyAconfigFiles(ctx, &p.mergedAconfigFiles) p.buildBinary(ctx) var configs []tradefed.Option @@ -227,7 +227,6 @@ func (p *PythonTestModule) AndroidMkEntries() []android.AndroidMkEntries { } entries.SetBoolIfTrue("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", !BoolDefault(p.binaryProperties.Auto_gen_config, true)) - android.SetAconfigFileMkEntries(&p.ModuleBase, entries, p.mergedAconfigFiles) p.testProperties.Test_options.SetAndroidMkEntries(entries) }) diff --git a/python/tests/Android.bp b/python/tests/Android.bp index e5569ba87..056f7eddd 100644 --- a/python/tests/Android.bp +++ b/python/tests/Android.bp @@ -27,9 +27,4 @@ python_test_host { test_options: { unit_test: false, }, - version: { - py3: { - embedded_launcher: true, - }, - }, } diff --git a/python/tests/dont_import_folder_of_entrypoint/Android.bp b/python/tests/dont_import_folder_of_entrypoint/Android.bp index e54e9b2c0..ab2e314be 100644 --- a/python/tests/dont_import_folder_of_entrypoint/Android.bp +++ b/python/tests/dont_import_folder_of_entrypoint/Android.bp @@ -10,17 +10,3 @@ python_test_host { "mypkg/mymodule.py", ], } - -python_test_host { - name: "py_dont_import_folder_of_entrypoint_test_embedded_launcher", - main: "mypkg/main.py", - srcs: [ - "mypkg/main.py", - "mypkg/mymodule.py", - ], - version: { - py3: { - embedded_launcher: true, - }, - }, -} diff --git a/rust/afdo.go b/rust/afdo.go index 6116c5e21..6bd4bae1a 100644 --- a/rust/afdo.go +++ b/rust/afdo.go @@ -39,7 +39,7 @@ func (afdo *afdo) addDep(ctx BaseModuleContext, actx android.BottomUpMutatorCont return } - if mod, ok := ctx.Module().(*Module); ok && mod.Enabled() { + if mod, ok := ctx.Module().(*Module); ok && mod.Enabled(ctx) { fdoProfileName, err := actx.DeviceConfig().AfdoProfile(actx.ModuleName()) if err != nil { ctx.ModuleErrorf("%s", err.Error()) diff --git a/rust/androidmk.go b/rust/androidmk.go index 021dd6067..8de6b6004 100644 --- a/rust/androidmk.go +++ b/rust/androidmk.go @@ -69,7 +69,6 @@ func (mod *Module) AndroidMkEntries() []android.AndroidMkEntries { } else if mod.InProduct() { entries.SetBool("LOCAL_IN_PRODUCT", true) } - android.SetAconfigFileMkEntries(mod.AndroidModuleBase(), entries, mod.mergedAconfigFiles) }, }, } diff --git a/rust/doc.go b/rust/doc.go index 6970d7979..fe205233d 100644 --- a/rust/doc.go +++ b/rust/doc.go @@ -38,7 +38,7 @@ func (n *rustdocSingleton) GenerateBuildActions(ctx android.SingletonContext) { FlagWithArg("-D ", docDir.String()) ctx.VisitAllModules(func(module android.Module) { - if !module.Enabled() { + if !module.Enabled(ctx) { return } diff --git a/rust/library.go b/rust/library.go index 6be4917bf..f58a54fcc 100644 --- a/rust/library.go +++ b/rust/library.go @@ -713,7 +713,7 @@ func LibraryMutator(mctx android.BottomUpMutatorContext) { if sourceVariant { sv := modules[0] for _, v := range modules[1:] { - if !v.Enabled() { + if !v.Enabled(mctx) { continue } mctx.AddInterVariantDependency(sourceDepTag, v, sv) diff --git a/rust/project_json.go b/rust/project_json.go index 05fc09b3a..24dcc89f1 100644 --- a/rust/project_json.go +++ b/rust/project_json.go @@ -119,7 +119,7 @@ func isModuleSupported(ctx android.SingletonContext, module android.Module) (*Mo if !ok { return nil, false } - if !rModule.Enabled() { + if !rModule.Enabled(ctx) { return nil, false } return rModule, true diff --git a/rust/rust.go b/rust/rust.go index c2b61515c..e4bb99cf4 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -172,9 +172,6 @@ type Module struct { apexSdkVersion android.ApiLevel transitiveAndroidMkSharedLibs *android.DepSet[string] - - // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo - mergedAconfigFiles map[string]android.Paths } func (mod *Module) Header() bool { @@ -998,8 +995,6 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { if mod.testModule { android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{}) } - - android.CollectDependencyAconfigFiles(ctx, &mod.mergedAconfigFiles) } func (mod *Module) deps(ctx DepsContext) Deps { @@ -1697,7 +1692,7 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { } func BeginMutator(ctx android.BottomUpMutatorContext) { - if mod, ok := ctx.Module().(*Module); ok && mod.Enabled() { + if mod, ok := ctx.Module().(*Module); ok && mod.Enabled(ctx) { mod.beginMutator(ctx) } } diff --git a/rust/sanitize.go b/rust/sanitize.go index bfd397155..c086880ed 100644 --- a/rust/sanitize.go +++ b/rust/sanitize.go @@ -258,7 +258,7 @@ func (sanitize *sanitize) deps(ctx BaseModuleContext, deps Deps) Deps { func rustSanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { if mod, ok := mctx.Module().(*Module); ok && mod.sanitize != nil { - if !mod.Enabled() { + if !mod.Enabled(mctx) { return } diff --git a/scripts/Android.bp b/scripts/Android.bp index d039a8171..80cd93579 100644 --- a/scripts/Android.bp +++ b/scripts/Android.bp @@ -29,11 +29,6 @@ python_test_host { "manifest_fixer_test.py", "manifest_fixer.py", ], - version: { - py3: { - embedded_launcher: true, - }, - }, libs: [ "manifest_utils", ], @@ -214,11 +209,6 @@ python_binary_host { srcs: [ "conv_linker_config.py", ], - version: { - py3: { - embedded_launcher: true, - }, - }, libs: [ "linker_config_proto", ], @@ -299,20 +289,16 @@ python_binary_host { srcs: [ "merge_directories.py", ], - version: { - py3: { - embedded_launcher: true, - }, - }, } python_binary_host { name: "buildinfo", main: "buildinfo.py", srcs: ["buildinfo.py"], - version: { - py3: { - embedded_launcher: true, - }, - }, +} + +python_binary_host { + name: "extra_install_zips_file_list", + main: "extra_install_zips_file_list.py", + srcs: ["extra_install_zips_file_list.py"], } diff --git a/scripts/extra_install_zips_file_list.py b/scripts/extra_install_zips_file_list.py new file mode 100755 index 000000000..8ea2a4bf0 --- /dev/null +++ b/scripts/extra_install_zips_file_list.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 + +import argparse +import os +import sys +import zipfile +from typing import List + +def list_files_in_zip(zipfile_path: str) -> List[str]: + with zipfile.ZipFile(zipfile_path, 'r') as zf: + return zf.namelist() + +def main(): + parser = argparse.ArgumentParser( + description='Lists paths to all files inside an EXTRA_INSTALL_ZIPS zip file relative to a partition staging directory. ' + 'This script is just a helper because its difficult to implement this logic in make code.' + ) + parser.add_argument('staging_dir', + help='Path to the partition staging directory') + parser.add_argument('extra_install_zips', nargs='*', + help='The value of EXTRA_INSTALL_ZIPS from make. It should be a list of extraction_dir:zip_file pairs.') + args = parser.parse_args() + + staging_dir = args.staging_dir.removesuffix('/') + '/' + + for zip_pair in args.extra_install_zips: + d, z = zip_pair.split(':') + d = d.removesuffix('/') + '/' + + if d.startswith(staging_dir): + d = os.path.relpath(d, staging_dir) + if d == '.': + d = '' + for f in list_files_in_zip(z): + print(os.path.join(d, f)) + + +if __name__ == "__main__": + main() diff --git a/scripts/hiddenapi/Android.bp b/scripts/hiddenapi/Android.bp index 1e89efe93..43edf447c 100644 --- a/scripts/hiddenapi/Android.bp +++ b/scripts/hiddenapi/Android.bp @@ -18,19 +18,9 @@ package { default_applicable_licenses: ["Android-Apache-2.0"], } -python_defaults { - name: "hiddenapi_defaults", - version: { - py3: { - embedded_launcher: true, - }, - }, -} - python_binary_host { name: "analyze_bcpf", main: "analyze_bcpf.py", - defaults: ["hiddenapi_defaults"], srcs: ["analyze_bcpf.py"], // Make sure that the bpmodify tool is built. data: [":bpmodify"], @@ -42,7 +32,6 @@ python_binary_host { python_test_host { name: "analyze_bcpf_test", main: "analyze_bcpf_test.py", - defaults: ["hiddenapi_defaults"], srcs: [ "analyze_bcpf.py", "analyze_bcpf_test.py", @@ -60,21 +49,18 @@ python_test_host { python_binary_host { name: "merge_csv", main: "merge_csv.py", - defaults: ["hiddenapi_defaults"], srcs: ["merge_csv.py"], } python_binary_host { name: "generate_hiddenapi_lists", main: "generate_hiddenapi_lists.py", - defaults: ["hiddenapi_defaults"], srcs: ["generate_hiddenapi_lists.py"], } python_test_host { name: "generate_hiddenapi_lists_test", main: "generate_hiddenapi_lists_test.py", - defaults: ["hiddenapi_defaults"], srcs: [ "generate_hiddenapi_lists.py", "generate_hiddenapi_lists_test.py", @@ -92,7 +78,6 @@ python_library_host { python_test_host { name: "signature_trie_test", main: "signature_trie_test.py", - defaults: ["hiddenapi_defaults"], srcs: ["signature_trie_test.py"], libs: ["signature_trie"], test_options: { @@ -103,7 +88,6 @@ python_test_host { python_binary_host { name: "verify_overlaps", main: "verify_overlaps.py", - defaults: ["hiddenapi_defaults"], srcs: ["verify_overlaps.py"], libs: [ "signature_trie", @@ -113,7 +97,6 @@ python_binary_host { python_test_host { name: "verify_overlaps_test", main: "verify_overlaps_test.py", - defaults: ["hiddenapi_defaults"], srcs: [ "verify_overlaps.py", "verify_overlaps_test.py", @@ -129,14 +112,12 @@ python_test_host { python_binary_host { name: "signature_patterns", main: "signature_patterns.py", - defaults: ["hiddenapi_defaults"], srcs: ["signature_patterns.py"], } python_test_host { name: "signature_patterns_test", main: "signature_patterns_test.py", - defaults: ["hiddenapi_defaults"], srcs: [ "signature_patterns.py", "signature_patterns_test.py", diff --git a/scripts/manifest_fixer.py b/scripts/manifest_fixer.py index 58079aa5d..35d2a1c81 100755 --- a/scripts/manifest_fixer.py +++ b/scripts/manifest_fixer.py @@ -62,8 +62,8 @@ def parse_args(): 'in the manifest.')) parser.add_argument('--extract-native-libs', dest='extract_native_libs', default=None, type=lambda x: (str(x).lower() == 'true'), - help=('specify if the app wants to use embedded native libraries. Must not conflict ' - 'if already declared in the manifest.')) + help=('specify if the app wants to use embedded native libraries. Must not ' + 'be true if manifest says false.')) parser.add_argument('--has-no-code', dest='has_no_code', action='store_true', help=('adds hasCode="false" attribute to application. Ignored if application elem ' 'already has a hasCode attribute.')) @@ -299,7 +299,16 @@ def add_extract_native_libs(doc, extract_native_libs): attr = doc.createAttributeNS(android_ns, 'android:extractNativeLibs') attr.value = value application.setAttributeNode(attr) - elif attr.value != value: + elif attr.value == "false" and value == "true": + # Note that we don't disallow the case of extractNativeLibs="true" in manifest and + # --extract-native-libs="false". This is fine because --extract-native-libs="false" means that + # the build system didn't compress the JNI libs, which is a fine choice for built-in apps. At + # runtime the JNI libs will be extracted to outside of the APK, but everything will still work + # okay. + # + # The opposite (extractNativeLibs="false" && --extract-native-libs="true") should however be + # disallowed because otherwise that would make an ill-formed APK; JNI libs are stored compressed + # but they won't be extracted. There's no way to execute the JNI libs. raise RuntimeError('existing attribute extractNativeLibs="%s" conflicts with --extract-native-libs="%s"' % (attr.value, value)) diff --git a/scripts/manifest_fixer_test.py b/scripts/manifest_fixer_test.py index 0a62b10a4..9fce6b9b8 100755 --- a/scripts/manifest_fixer_test.py +++ b/scripts/manifest_fixer_test.py @@ -479,8 +479,8 @@ class AddExtractNativeLibsTest(unittest.TestCase): self.assert_xml_equal(output, expected) def test_conflict(self): - manifest_input = self.manifest_tmpl % self.extract_native_libs('true') - self.assertRaises(RuntimeError, self.run_test, manifest_input, False) + manifest_input = self.manifest_tmpl % self.extract_native_libs('false') + self.assertRaises(RuntimeError, self.run_test, manifest_input, True) class AddNoCodeApplicationTest(unittest.TestCase): diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go index 8d3bbfa1b..6e2512262 100644 --- a/sdk/bootclasspath_fragment_sdk_test.go +++ b/sdk/bootclasspath_fragment_sdk_test.go @@ -1095,7 +1095,7 @@ func testSnapshotWithBootClasspathFragment_MinSdkVersion(t *testing.T, targetBui bcpf := result.ModuleForTests("mybootclasspathfragment", "android_common") rule := bcpf.Output("out/soong/.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi" + suffix + "/stub-flags.csv") - android.AssertPathsRelativeToTopEquals(t, "stub flags inputs", expectedStubFlagsInputs, rule.Implicits) + android.AssertPathsRelativeToTopEquals(t, "stub flags inputs", android.SortedUniqueStrings(expectedStubFlagsInputs), android.SortedUniquePaths(rule.Implicits)) CheckSnapshot(t, result, "mysdk", "", checkAndroidBpContents(expectedSdkSnapshot), @@ -1153,7 +1153,7 @@ java_sdk_library_import { // of the snapshot. expectedStubFlagsInputs := []string{ "out/soong/.intermediates/mysdklibrary.stubs.exportable/android_common/dex/mysdklibrary.stubs.exportable.jar", - "out/soong/.intermediates/mysdklibrary/android_common/aligned/mysdklibrary.jar", + "out/soong/.intermediates/mysdklibrary.impl/android_common/aligned/mysdklibrary.jar", } testSnapshotWithBootClasspathFragment_MinSdkVersion(t, "S", @@ -1234,9 +1234,9 @@ java_sdk_library_import { // they are both part of the snapshot. expectedStubFlagsInputs := []string{ "out/soong/.intermediates/mynewsdklibrary.stubs.exportable/android_common/dex/mynewsdklibrary.stubs.exportable.jar", - "out/soong/.intermediates/mynewsdklibrary/android_common/aligned/mynewsdklibrary.jar", + "out/soong/.intermediates/mynewsdklibrary.impl/android_common/aligned/mynewsdklibrary.jar", "out/soong/.intermediates/mysdklibrary.stubs.exportable/android_common/dex/mysdklibrary.stubs.exportable.jar", - "out/soong/.intermediates/mysdklibrary/android_common/aligned/mysdklibrary.jar", + "out/soong/.intermediates/mysdklibrary.impl/android_common/aligned/mysdklibrary.jar", } testSnapshotWithBootClasspathFragment_MinSdkVersion(t, "Tiramisu", diff --git a/snapshot/host_fake_snapshot.go b/snapshot/host_fake_snapshot.go index 63cd4e1b6..b416ebdd4 100644 --- a/snapshot/host_fake_snapshot.go +++ b/snapshot/host_fake_snapshot.go @@ -116,7 +116,7 @@ func (c *hostFakeSingleton) GenerateBuildActions(ctx android.SingletonContext) { prebuilts[android.RemoveOptionalPrebuiltPrefix(module.Name())] = true return } - if !module.Enabled() || module.IsHideFromMake() { + if !module.Enabled(ctx) || module.IsHideFromMake() { return } apexInfo, _ := android.SingletonModuleProvider(ctx, module, android.ApexInfoProvider) |