diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-05-14 23:00:22 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-05-14 23:00:22 +0000 |
commit | 1ed2772ce3f127fca248643918eac16e4e5ba9f2 (patch) | |
tree | 90b65f49651bcc31e220b36d3d845ee7b71d3480 | |
parent | e7f0191beade09938a0c03ae75adaf21f6b00963 (diff) | |
parent | e8cb9178ec8b4faf24ffd3c0f123efa7f7f9fe65 (diff) | |
download | soong-sdk-release.tar.gz |
Snap for 11841552 from e8cb9178ec8b4faf24ffd3c0f123efa7f7f9fe65 to sdk-releasesdk-release
Change-Id: Ib7f6e041dd95f5aca150d0cb1936bc3a5bc85c5c
54 files changed, 1060 insertions, 321 deletions
diff --git a/android/aconfig_providers.go b/android/aconfig_providers.go index 4c1782b8e..ee9891df1 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,15 +126,16 @@ func aconfigUpdateAndroidBuildActions(ctx ModuleContext) { mergedAconfigFiles[container] = mergeAconfigFiles(ctx, container, aconfigFiles, true) } - SetProvider(ctx, aconfigPropagatingProviderKey, aconfigPropagatingDeclarationsInfo{ + SetProvider(ctx, AconfigPropagatingProviderKey, aconfigPropagatingDeclarationsInfo{ AconfigFiles: mergedAconfigFiles, ModeInfos: mergedModeInfos, }) + ctx.Module().base().aconfigFilePaths = getAconfigFilePaths(ctx.Module().base(), mergedAconfigFiles) } } 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 +166,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 +174,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 +204,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/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/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/makevars.go b/android/makevars.go index e73645fdc..f57ac4500 100644 --- a/android/makevars.go +++ b/android/makevars.go @@ -473,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" @@ -507,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:%s\n", install.to.String(), 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 40a591007..d4e4c2dee 100644 --- a/android/module.go +++ b/android/module.go @@ -902,6 +902,9 @@ type ModuleBase struct { installedInitRcPaths InstallPaths installedVintfFragmentsPaths InstallPaths + // Merged Aconfig files for all transitive deps. + aconfigFilePaths Paths + // set of dependency module:location mappings used to populate the license metadata for // apex containers. licenseInstallMap []string @@ -1066,7 +1069,8 @@ func addRequiredDeps(ctx BottomUpMutatorContext) { // TODO(jiyong): the Make-side does this only when the required module is a shared // library or a native test. bothInAndroid := ctx.Device() && target.Os.Class == Device - nativeArch := InList(ctx.Arch().ArchType.Multilib, []string{"lib32", "lib64"}) + nativeArch := InList(ctx.Arch().ArchType.Multilib, []string{"lib32", "lib64"}) && + InList(target.Arch.ArchType.Multilib, []string{"lib32", "lib64"}) sameBitness := ctx.Arch().ArchType.Multilib == target.Arch.ArchType.Multilib if bothInAndroid && nativeArch && !sameBitness { return @@ -1892,12 +1896,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 } @@ -2145,9 +2151,9 @@ func (e configurationEvalutor) EvaluateConfiguration(condition proptools.Configu 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 { diff --git a/android/module_context.go b/android/module_context.go index 605d3baeb..3c1e30a6c 100644 --- a/android/module_context.go +++ b/android/module_context.go @@ -482,6 +482,10 @@ func (m *moduleContext) PackageFile(installPath InstallPath, name string, srcPat return m.packageFile(fullInstallPath, srcPath, false) } +func (m *moduleContext) getAconfigPaths() *Paths { + return &m.module.base().aconfigFilePaths +} + func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, executable bool) PackagingSpec { licenseFiles := m.Module().EffectiveLicenseFiles() spec := PackagingSpec{ @@ -492,6 +496,7 @@ func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, e effectiveLicenseFiles: &licenseFiles, partition: fullInstallPath.partition, skipInstall: m.skipInstall(), + aconfigPaths: m.getAconfigPaths(), } m.packagingSpecs = append(m.packagingSpecs, spec) return spec @@ -616,6 +621,7 @@ func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, src executable: false, partition: fullInstallPath.partition, skipInstall: m.skipInstall(), + aconfigPaths: m.getAconfigPaths(), }) return fullInstallPath @@ -658,6 +664,7 @@ func (m *moduleContext) InstallAbsoluteSymlink(installPath InstallPath, name str executable: false, partition: fullInstallPath.partition, skipInstall: m.skipInstall(), + aconfigPaths: m.getAconfigPaths(), }) return fullInstallPath diff --git a/android/override_module.go b/android/override_module.go index 55f384f1f..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,69 +297,27 @@ 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()) } } diff --git a/android/packaging.go b/android/packaging.go index fe61da1e9..a7260a641 100644 --- a/android/packaging.go +++ b/android/packaging.go @@ -48,6 +48,9 @@ type PackagingSpec struct { // is created via InstallFile or InstallSymlink) or a simple packaging (i.e. created via // PackageFile). skipInstall bool + + // Paths of aconfig files for the built artifact + aconfigPaths *Paths } func (p *PackagingSpec) Equals(other *PackagingSpec) bool { @@ -102,6 +105,11 @@ func (p *PackagingSpec) SkipInstall() bool { return p.skipInstall } +// Paths of aconfig files for the built artifact +func (p *PackagingSpec) GetAconfigPaths() Paths { + return *p.aconfigPaths +} + type PackageModule interface { Module packagingBase() *PackagingBase diff --git a/apex/apex.go b/apex/apex.go index 40eb712ab..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. @@ -2326,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()]...) } @@ -2414,7 +2411,6 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { return } } - android.CollectDependencyAconfigFiles(ctx, &a.mergedAconfigFiles) //////////////////////////////////////////////////////////////////////////////////////////// // 3) some fields in apexBundle struct are configured @@ -2586,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. @@ -2611,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/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 df356df0e..0c6f97c34 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -125,8 +125,6 @@ func (c *Module) AndroidMkEntries() []android.AndroidMkEntries { 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()) }, }, @@ -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) @@ -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 a1b329e2c..aee584daf 100644 --- a/cc/compiler.go +++ b/cc/compiler.go @@ -278,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/library.go b/cc/library.go index 12ecc131a..895b1993c 100644 --- a/cc/library.go +++ b/cc/library.go @@ -1490,6 +1490,11 @@ func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, deps PathD fileName, nameExt, isLlndk) } } + // Ensure that a module tagged with only platformLsdumpTag has ref_dump_dirs. + // Android.bp in vendor projects should be cleaned up before this is enforced for vendorLsdumpTag and productLsdumpTag. + if len(headerAbiChecker.Ref_dump_dirs) == 0 && len(tags) == 1 && tags[0] == platformLsdumpTag { + ctx.ModuleErrorf("header_abi_checker is explicitly enabled, but no ref_dump_dirs are specified.") + } // Check against the opt-in reference dumps. for i, optInDumpDir := range headerAbiChecker.Ref_dump_dirs { optInDumpDirPath := android.PathForModuleSrc(ctx, optInDumpDir) 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/sabi.go b/cc/sabi.go index edd9cfe80..64eab4160 100644 --- a/cc/sabi.go +++ b/cc/sabi.go @@ -43,8 +43,6 @@ func (tag *lsdumpTag) dirName() string { return "platform" case llndkLsdumpTag: return "vndk" - case platformLsdumpTag: - return "platform" default: return "" } @@ -134,10 +132,10 @@ func classifySourceAbiDump(ctx android.BaseModuleContext) []lsdumpTag { if m.isImplementationForLLNDKPublic() { result = append(result, llndkLsdumpTag) } - // APEX and opt-in platform dumps are placed in the same directory. if m.library.hasStubsVariants() { result = append(result, apexLsdumpTag) - } else if headerAbiChecker.enabled() { + } + if headerAbiChecker.enabled() { result = append(result, platformLsdumpTag) } } else if headerAbiChecker.enabled() { diff --git a/cc/test.go b/cc/test.go index 3a1a3af44..a96af31bb 100644 --- a/cc/test.go +++ b/cc/test.go @@ -359,6 +359,12 @@ func (test *testBinary) linkerDeps(ctx DepsContext, deps Deps) Deps { func (test *testBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags { flags = test.binaryDecorator.linkerFlags(ctx, flags) flags = test.testDecorator.linkerFlags(ctx, flags) + + // Add a default rpath to allow tests to dlopen libraries specified in data_libs. + // Host modules already get an rpath specified in linker.go. + if !ctx.Host() { + flags.Global.LdFlags = append(flags.Global.LdFlags, `-Wl,-rpath,\$$ORIGIN`) + } return flags } 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/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_lib/release_configs.go b/cmd/release_config/release_config_lib/release_configs.go index 8a4e2d58b..2487f2e99 100644 --- a/cmd/release_config/release_config_lib/release_configs.go +++ b/cmd/release_config/release_config_lib/release_configs.go @@ -291,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/cmd/soong_build/main.go b/cmd/soong_build/main.go index d64010e66..4490dd2af 100644 --- a/cmd/soong_build/main.go +++ b/cmd/soong_build/main.go @@ -108,7 +108,7 @@ func needToWriteNinjaHint(ctx *android.Context) bool { case "always": return true case "depend": - if _, err := os.Stat(filepath.Join(ctx.Config().OutDir(), ".ninja_log")); errors.Is(err, os.ErrNotExist) { + if _, err := os.Stat(filepath.Join(topDir, ctx.Config().OutDir(), ".ninja_log")); errors.Is(err, os.ErrNotExist) { return true } } 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/filesystem/Android.bp b/filesystem/Android.bp index 854a3661a..a08f7cf17 100644 --- a/filesystem/Android.bp +++ b/filesystem/Android.bp @@ -15,6 +15,7 @@ bootstrap_go_package { "soong-phony", // for testing ], srcs: [ + "aconfig_files.go", "avb_add_hash_footer.go", "avb_gen_vbmeta_image.go", "bootimg.go", diff --git a/filesystem/aconfig_files.go b/filesystem/aconfig_files.go new file mode 100644 index 000000000..44de20237 --- /dev/null +++ b/filesystem/aconfig_files.go @@ -0,0 +1,58 @@ +// Copyright (C) 2024 The Android Open Source Project +// +// 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 filesystem + +import ( + "android/soong/android" + "path/filepath" + "strings" + + "github.com/google/blueprint/proptools" +) + +func (f *filesystem) buildAconfigFlagsFiles(ctx android.ModuleContext, builder *android.RuleBuilder, specs map[string]android.PackagingSpec, dir android.Path) { + if !proptools.Bool(f.properties.Gen_aconfig_flags_pb) { + return + } + + aconfigFlagsBuilderPath := android.PathForModuleOut(ctx, "aconfig_flags_builder.sh") + aconfigToolPath := ctx.Config().HostToolPath(ctx, "aconfig") + cmd := builder.Command().Tool(aconfigFlagsBuilderPath).Implicit(aconfigToolPath) + + installAconfigFlags := filepath.Join(dir.String(), "etc", "aconfig_flags_"+f.partitionName()+".pb") + + var sb strings.Builder + sb.WriteString("set -e\n") + sb.WriteString(aconfigToolPath.String()) + sb.WriteString(" dump-cache --dedup --format protobuf --out ") + sb.WriteString(installAconfigFlags) + sb.WriteString(" \\\n") + + var caches []string + for _, ps := range specs { + cmd.Implicits(ps.GetAconfigPaths()) + caches = append(caches, ps.GetAconfigPaths().Strings()...) + } + caches = android.SortedUniqueStrings(caches) + + for _, cache := range caches { + sb.WriteString(" --cache ") + sb.WriteString(cache) + sb.WriteString(" \\\n") + } + sb.WriteRune('\n') + + android.WriteExecutableFileRuleVerbatim(ctx, aconfigFlagsBuilderPath, sb.String()) +} diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index b342ae930..d8a00e2c9 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -131,6 +131,9 @@ type filesystemProperties struct { // Default is false Build_logtags *bool + // Install aconfig_flags.pb file for the modules installed in this partition. + Gen_aconfig_flags_pb *bool + Fsverity fsverityProperties } @@ -300,6 +303,7 @@ func (f *filesystem) buildImageUsingBuildImage(ctx android.ModuleContext) androi f.addMakeBuiltFiles(ctx, builder, rootDir) f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir) f.buildEventLogtagsFile(ctx, builder, rebasedDir) + f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir) // run host_init_verifier // Ideally we should have a concept of pluggable linters that verify the generated image. @@ -441,6 +445,7 @@ func (f *filesystem) buildCpioImage(ctx android.ModuleContext, compressed bool) f.buildNonDepsFiles(ctx, builder, rootDir) f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir) f.buildEventLogtagsFile(ctx, builder, rebasedDir) + f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir) output := android.PathForModuleOut(ctx, f.installFileName()).OutputPath cmd := builder.Command(). diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go index acd481352..861918f16 100644 --- a/filesystem/filesystem_test.go +++ b/filesystem/filesystem_test.go @@ -465,3 +465,35 @@ func TestPreventDuplicatedEntries(t *testing.T) { } `) } + +func TestTrackPhonyAsRequiredDep(t *testing.T) { + result := fixture.RunTestWithBp(t, ` + android_filesystem { + name: "fs", + deps: ["foo"], + } + + cc_binary { + name: "foo", + required: ["phony"], + } + + phony { + name: "phony", + required: ["libbar"], + } + + cc_library { + name: "libbar", + } + `) + + fs := result.ModuleForTests("fs", "android_common").Module().(*filesystem) + expected := []string{ + "bin/foo", + "lib64/libbar.so", + } + for _, e := range expected { + android.AssertStringListContains(t, "missing entry", fs.entries, e) + } +} diff --git a/genrule/genrule.go b/genrule/genrule.go index 67b96ca92..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 @@ -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..4f740b231 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -124,7 +124,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 +297,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{ @@ -450,10 +448,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 +525,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/app.go b/java/app.go index 50d1a2f43..f05b8a7cd 100644 --- a/java/app.go +++ b/java/app.go @@ -521,7 +521,7 @@ func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) { } // Use non final ids if we are doing optimized shrinking and are using R8. - nonFinalIds := Bool(a.dexProperties.Optimize.Optimized_shrink_resources) && a.dexer.effectiveOptimizeEnabled() + nonFinalIds := a.dexProperties.optimizedResourceShrinkingEnabled(ctx) && a.dexer.effectiveOptimizeEnabled() a.aapt.buildActions(ctx, aaptBuildActionOptions{ sdkContext: android.SdkContext(a), @@ -552,7 +552,7 @@ func (a *AndroidApp) proguardBuildActions(ctx android.ModuleContext) { staticLibProguardFlagFiles = android.FirstUniquePaths(staticLibProguardFlagFiles) a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, staticLibProguardFlagFiles...) - if !Bool(a.dexProperties.Optimize.Optimized_shrink_resources) { + if !(a.dexProperties.optimizedResourceShrinkingEnabled(ctx)) { // When using the optimized shrinking the R8 enqueuer will traverse the xml files that become // live for code references and (transitively) mark these as live. // In this case we explicitly don't wan't the aapt2 generated keep files (which would keep the now @@ -591,7 +591,7 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) (android.Path, a var packageResources = a.exportPackage if ctx.ModuleName() != "framework-res" { - if a.dexProperties.resourceShrinkingEnabled() { + if a.dexProperties.resourceShrinkingEnabled(ctx) { protoFile := android.PathForModuleOut(ctx, packageResources.Base()+".proto.apk") aapt2Convert(ctx, protoFile, packageResources, "proto") a.dexer.resourcesInput = android.OptionalPathForPath(protoFile) @@ -614,7 +614,7 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) (android.Path, a } a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars) - if a.dexProperties.resourceShrinkingEnabled() { + if a.dexProperties.resourceShrinkingEnabled(ctx) { binaryResources := android.PathForModuleOut(ctx, packageResources.Base()+".binary.out.apk") aapt2Convert(ctx, binaryResources, a.dexer.resourcesOutput.Path(), "binary") packageResources = binaryResources 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/base.go b/java/base.go index 06c18ca43..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 @@ -1734,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/dex.go b/java/dex.go index 6caaa7f48..8cfffaf1f 100644 --- a/java/dex.go +++ b/java/dex.go @@ -111,8 +111,12 @@ func (d *dexer) effectiveOptimizeEnabled() bool { return BoolDefault(d.dexProperties.Optimize.Enabled, d.dexProperties.Optimize.EnabledByDefault) } -func (d *DexProperties) resourceShrinkingEnabled() bool { - return BoolDefault(d.Optimize.Optimized_shrink_resources, Bool(d.Optimize.Shrink_resources)) +func (d *DexProperties) resourceShrinkingEnabled(ctx android.ModuleContext) bool { + return !ctx.Config().Eng() && BoolDefault(d.Optimize.Optimized_shrink_resources, Bool(d.Optimize.Shrink_resources)) +} + +func (d *DexProperties) optimizedResourceShrinkingEnabled(ctx android.ModuleContext) bool { + return d.resourceShrinkingEnabled(ctx) && Bool(d.Optimize.Optimized_shrink_resources) } var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8", 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/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/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/rust.go b/rust/rust.go index de049f77f..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 { 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..148d6ccd9 --- /dev/null +++ b/scripts/extra_install_zips_file_list.py @@ -0,0 +1,42 @@ +#!/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 primary_file:extraction_dir:zip_file trios. ' + 'The primary file will be ignored by this script, you should ensure that ' + 'the list of trios given to this script is already filtered by relevant primary files.') + args = parser.parse_args() + + staging_dir = args.staging_dir.removesuffix('/') + '/' + + for zip_trio in args.extra_install_zips: + _, d, z = zip_trio.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", |