diff options
159 files changed, 3596 insertions, 1344 deletions
diff --git a/Android.bp b/Android.bp index 337545bce..713459112 100644 --- a/Android.bp +++ b/Android.bp @@ -176,6 +176,12 @@ build_prop { footer_files: [ ":applied_backported_fixes", ], + dist: { + targets: [ + "droidcore-unbundled", + "sdk", + ], + }, // Currently, only microdroid, Ravenwood, and cf system image can refer to system-build.prop visibility: [ "//build/soong/fsgen", @@ -191,6 +197,10 @@ build_prop { system_ext_specific: true, product_config: ":product_config", relative_install_path: "etc", // system_ext/etc/build.prop + dist: { + targets: ["droidcore-unbundled"], + dest: "build.prop-system_ext", + }, visibility: [ "//build/make/target/product/gsi", "//build/soong/fsgen", @@ -203,6 +213,10 @@ build_prop { product_specific: true, product_config: ":product_config", relative_install_path: "etc", // product/etc/build.prop + dist: { + targets: ["droidcore-unbundled"], + dest: "build.prop-product", + }, visibility: [ "//build/make/target/product/gsi", "//build/soong/fsgen", @@ -215,6 +229,10 @@ build_prop { device_specific: true, product_config: ":product_config", relative_install_path: "etc", // odm/etc/build.prop + dist: { + targets: ["droidcore-unbundled"], + dest: "build.prop-odm", + }, visibility: ["//build/soong/fsgen"], } @@ -251,6 +269,10 @@ build_prop { ramdisk: true, product_config: ":product_config", relative_install_path: "etc/ramdisk", // ramdisk/system/etc/ramdisk/build.prop + dist: { + targets: ["droidcore-unbundled"], + dest: "build.prop-ramdisk", + }, visibility: ["//visibility:private"], } diff --git a/aconfig/aconfig_declarations.go b/aconfig/aconfig_declarations.go index 9a9e5686a..b06839831 100644 --- a/aconfig/aconfig_declarations.go +++ b/aconfig/aconfig_declarations.go @@ -47,7 +47,7 @@ type DeclarationsModule struct { // are from RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS. ReleaseConfigValues []AconfigReleaseConfigValue - // Container(system/vendor/apex) that this module belongs to + // Container(system/system_ext/vendor/apex) that this module belongs to Container string // The flags will only be repackaged if this prop is true. @@ -88,13 +88,6 @@ func (module *DeclarationsModule) DepsMutator(ctx android.BottomUpMutatorContext ctx.PropertyErrorf("container", "missing container property") } - // treating system_ext as system partition as we are combining them as one container - // TODO remove this logic once we start enforcing that system_ext cannot be specified as - // container in the container field. - if module.properties.Container == "system_ext" { - module.properties.Container = "system" - } - // Add a dependency on the aconfig_value_sets defined in // RELEASE_ACONFIG_VALUE_SETS, and add any aconfig_values that // match our package. diff --git a/aconfig/all_aconfig_declarations.go b/aconfig/all_aconfig_declarations.go index 3d07e16dc..f3c68c37a 100644 --- a/aconfig/all_aconfig_declarations.go +++ b/aconfig/all_aconfig_declarations.go @@ -95,11 +95,44 @@ func GenerateFinalizedFlagsForApiSurface(ctx android.ModuleContext, outputPath a }) } +func GenerateExportedFlagCheck(ctx android.ModuleContext, outputPath android.WritablePath, + parsedFlagsFile android.Path, apiSurface ApiSurfaceContributorProperties) { + + apiSignatureFiles := android.Paths{} + for _, apiSignatureFile := range apiSurface.Api_signature_files.GetOrDefault(ctx, nil) { + if path := android.PathForModuleSrc(ctx, apiSignatureFile); path != nil { + apiSignatureFiles = append(apiSignatureFiles, path) + } + } + finalizedFlagsFile := android.PathForModuleSrc(ctx, apiSurface.Finalized_flags_file) + + ctx.Build(pctx, android.BuildParams{ + Rule: ExportedFlagCheckRule, + Inputs: append(apiSignatureFiles, finalizedFlagsFile, parsedFlagsFile), + Output: outputPath, + Args: map[string]string{ + "api_signature_files": android.JoinPathsWithPrefix(apiSignatureFiles, "--api-signature-file "), + "finalized_flags_file": "--finalized-flags-file " + finalizedFlagsFile.String(), + "parsed_flags_file": "--parsed-flags-file " + parsedFlagsFile.String(), + }, + }) +} + func (this *allAconfigDeclarationsSingleton) GenerateAndroidBuildActions(ctx android.ModuleContext) { parsedFlagsFile := android.PathForIntermediates(ctx, "all_aconfig_declarations.pb") this.finalizedFlags = android.PathForIntermediates(ctx, "finalized-flags.txt") GenerateFinalizedFlagsForApiSurface(ctx, this.finalizedFlags, parsedFlagsFile, this.properties) - ctx.Phony("all_aconfig_declarations", this.finalizedFlags) + + depsFiles := android.Paths{this.finalizedFlags} + if checkExportedFlag, ok := ctx.Config().GetBuildFlag("RELEASE_EXPORTED_FLAG_CHECK"); ok { + if checkExportedFlag == "true" { + invalidExportedFlags := android.PathForIntermediates(ctx, "invalid_exported_flags.txt") + GenerateExportedFlagCheck(ctx, invalidExportedFlags, parsedFlagsFile, this.properties) + depsFiles = append(depsFiles, invalidExportedFlags) + } + } + + ctx.Phony("all_aconfig_declarations", depsFiles...) android.SetProvider(ctx, allAconfigDeclarationsInfoProvider, allAconfigDeclarationsInfo{ parsedFlagsFile: parsedFlagsFile, @@ -111,7 +144,7 @@ func (this *allAconfigDeclarationsSingleton) GenerateSingletonBuildActions(ctx a // Find all of the aconfig_declarations modules var packages = make(map[string]int) var cacheFiles android.Paths - ctx.VisitAllModules(func(module android.Module) { + ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { decl, ok := android.OtherModuleProvider(ctx, module, android.AconfigReleaseDeclarationsProviderKey) if !ok { return diff --git a/aconfig/build_flags/build_flags_singleton.go b/aconfig/build_flags/build_flags_singleton.go index e375d9c70..3a06e72d6 100644 --- a/aconfig/build_flags/build_flags_singleton.go +++ b/aconfig/build_flags/build_flags_singleton.go @@ -15,8 +15,9 @@ package build_flags import ( - "android/soong/android" "fmt" + + "android/soong/android" ) // A singleton module that collects all of the build flags declared in the @@ -42,7 +43,7 @@ func (this *allBuildFlagDeclarationsSingleton) GenerateBuildActions(ctx android. var flagsFiles android.Paths // Find all of the release_config_contribution modules var contributionDirs android.Paths - ctx.VisitAllModules(func(module android.Module) { + ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { decl, ok := android.OtherModuleProvider(ctx, module, BuildFlagDeclarationsProviderKey) if ok { flagsFiles = append(flagsFiles, decl.IntermediateCacheOutputPath) diff --git a/aconfig/codegen/java_aconfig_library_test.go b/aconfig/codegen/java_aconfig_library_test.go index 8854369e2..b9455f77d 100644 --- a/aconfig/codegen/java_aconfig_library_test.go +++ b/aconfig/codegen/java_aconfig_library_test.go @@ -260,7 +260,7 @@ func TestMkEntriesMatchedContainer(t *testing.T) { aconfig_declarations { name: "my_aconfig_declarations_bar", package: "com.example.package.bar", - container: "vendor", + container: "system_ext", srcs: ["bar.aconfig"], } diff --git a/aconfig/exported_java_aconfig_library.go b/aconfig/exported_java_aconfig_library.go index 63d824a88..ffb2a0cbe 100644 --- a/aconfig/exported_java_aconfig_library.go +++ b/aconfig/exported_java_aconfig_library.go @@ -15,8 +15,9 @@ package aconfig import ( - "android/soong/android" "strconv" + + "android/soong/android" ) func ExportedJavaDeclarationsLibraryFactory() android.Singleton { @@ -30,7 +31,7 @@ type exportedJavaDeclarationsLibrarySingleton struct { func (this *exportedJavaDeclarationsLibrarySingleton) GenerateBuildActions(ctx android.SingletonContext) { // Find all of the aconfig_declarations modules var cacheFiles android.Paths - ctx.VisitAllModules(func(module android.Module) { + ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { decl, ok := android.OtherModuleProvider(ctx, module, android.AconfigDeclarationsProviderKey) if !ok { return diff --git a/aconfig/init.go b/aconfig/init.go index b2fe5a309..d8d547022 100644 --- a/aconfig/init.go +++ b/aconfig/init.go @@ -77,6 +77,13 @@ var ( "${record-finalized-flags}", }, }, "api_signature_files", "finalized_flags_file", "parsed_flags_file") + ExportedFlagCheckRule = pctx.AndroidStaticRule("ExportedFlagCheckRule", + blueprint.RuleParams{ + Command: `${exported-flag-check} ${parsed_flags_file} ${finalized_flags_file} ${api_signature_files} > ${out}`, + CommandDeps: []string{ + "${exported-flag-check}", + }, + }, "api_signature_files", "finalized_flags_file", "parsed_flags_file") CreateStorageRule = pctx.AndroidStaticRule("aconfig_create_storage", blueprint.RuleParams{ @@ -124,6 +131,7 @@ func init() { pctx.HostBinToolVariable("aconfig", "aconfig") pctx.HostBinToolVariable("soong_zip", "soong_zip") pctx.HostBinToolVariable("record-finalized-flags", "record-finalized-flags") + pctx.HostBinToolVariable("exported-flag-check", "exported-flag-check") } func RegisterBuildComponents(ctx android.RegistrationContext) { diff --git a/android/Android.bp b/android/Android.bp index 1cc7ffe1d..4b75148fc 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -97,6 +97,7 @@ bootstrap_go_package { "product_packages_file.go", "proto.go", "provider.go", + "provider_keys.go", "raw_files.go", "recovery_build_prop.go", "register.go", @@ -170,3 +171,7 @@ bootstrap_go_package { // Used by plugins visibility: ["//visibility:public"], } + +otatools_package_filegroup { + name: "otatools_package_filegroup", +} diff --git a/android/aconfig_providers.go b/android/aconfig_providers.go index 205b85590..bb73f0bdd 100644 --- a/android/aconfig_providers.go +++ b/android/aconfig_providers.go @@ -238,8 +238,7 @@ func getContainer(m Module) string { } else if base.ProductSpecific() { container = "product" } else if base.SystemExtSpecific() { - // system_ext and system partitions should be treated as one container - container = "system" + container = "system_ext" } return container @@ -249,14 +248,13 @@ func getContainer(m Module) string { // Please only access the module's internal data through providers. func getContainerUsingProviders(ctx OtherModuleProviderContext, m Module) string { container := "system" - commonInfo, _ := OtherModuleProvider(ctx, m, CommonModuleInfoKey) + commonInfo := OtherModulePointerProviderOrDefault(ctx, m, CommonModuleInfoProvider) if commonInfo.Vendor || commonInfo.Proprietary || commonInfo.SocSpecific { container = "vendor" } else if commonInfo.ProductSpecific { container = "product" } else if commonInfo.SystemExtSpecific { - // system_ext and system partitions should be treated as one container - container = "system" + container = "system_ext" } return container diff --git a/android/all_teams.go b/android/all_teams.go index 3b20107b9..18a050f5d 100644 --- a/android/all_teams.go +++ b/android/all_teams.go @@ -78,19 +78,19 @@ func (t *allTeamsSingleton) GenerateBuildActions(ctx SingletonContext) { t.teams = make(map[string]teamProperties) t.teams_for_mods = make(map[string]moduleTeamAndTestInfo) - ctx.VisitAllModules(func(module Module) { + ctx.VisitAllModuleProxies(func(module ModuleProxy) { bpFile := ctx.BlueprintFile(module) // Package Modules and Team Modules are stored in a map so we can look them up by name for // modules without a team. - if pack, ok := module.(*packageModule); ok { + if pack, ok := OtherModuleProvider(ctx, module, PackageInfoProvider); ok { // Packages don't have names, use the blueprint file as the key. we can't get qualifiedModuleId in t context. pkgKey := bpFile - t.packages[pkgKey] = pack.properties + t.packages[pkgKey] = pack.Properties return } - if team, ok := module.(*teamModule); ok { - t.teams[team.Name()] = team.properties + if team, ok := OtherModuleProvider(ctx, module, TeamInfoProvider); ok { + t.teams[module.Name()] = team.Properties return } @@ -116,7 +116,7 @@ func (t *allTeamsSingleton) GenerateBuildActions(ctx SingletonContext) { testOnly: testModInfo.TestOnly, topLevelTestTarget: testModInfo.TopLevelTarget, kind: ctx.ModuleType(module), - teamName: module.base().Team(), + teamName: OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider).Team, } t.teams_for_mods[module.Name()] = entry diff --git a/android/androidmk.go b/android/androidmk.go index 5cb5a66bc..784559312 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -78,6 +78,12 @@ type AndroidMkData struct { Entries AndroidMkEntries } +type AndroidMkDataInfo struct { + Class string +} + +var AndroidMkDataInfoProvider = blueprint.NewProvider[AndroidMkDataInfo]() + type AndroidMkExtraFunc func(w io.Writer, outputFile Path) // Interface for modules to declare their Android.mk outputs. Note that every module needs to @@ -349,30 +355,15 @@ func (d *distCopies) Strings() (ret []string) { return } -// Compute the contributions that the module makes to the dist. -func (a *AndroidMkEntries) getDistContributions(mod Module) *distContributions { +// This gets the dist contributuions from the given module that were specified in the Android.bp +// file using the dist: property. It does not include contribututions that the module's +// implementation may have defined with ctx.DistForGoals(), for that, see DistProvider. +func getDistContributions(ctx ConfigAndOtherModuleProviderContext, mod Module) *distContributions { amod := mod.base() name := amod.BaseModuleName() - // Collate the set of associated tag/paths available for copying to the dist. - // Start with an empty (nil) set. - var availableTaggedDists TaggedDistFiles - - // If no paths have been provided for the DefaultDistTag and the output file is - // valid then add that as the default dist path. - if a.OutputFile.Valid() { - availableTaggedDists = availableTaggedDists.addPathsForTag(DefaultDistTag, a.OutputFile.Path()) - } - - info := OtherModuleProviderOrDefault(a.entryContext, mod, InstallFilesProvider) - // If the distFiles created by GenerateTaggedDistFiles contains paths for the - // DefaultDistTag then that takes priority so delete any existing paths. - if _, ok := info.DistFiles[DefaultDistTag]; ok { - delete(availableTaggedDists, DefaultDistTag) - } - - // Finally, merge the distFiles created by GenerateTaggedDistFiles. - availableTaggedDists = availableTaggedDists.merge(info.DistFiles) + info := OtherModuleProviderOrDefault(ctx, mod, InstallFilesProvider) + availableTaggedDists := info.DistFiles if len(availableTaggedDists) == 0 { // Nothing dist-able for this module. @@ -446,7 +437,7 @@ func (a *AndroidMkEntries) getDistContributions(mod Module) *distContributions { productString := "" if dist.Append_artifact_with_product != nil && *dist.Append_artifact_with_product { - productString = fmt.Sprintf("_%s", a.entryContext.Config().DeviceProduct()) + productString = fmt.Sprintf("_%s", ctx.Config().DeviceProduct()) } if suffix != "" || productString != "" { @@ -494,7 +485,7 @@ func generateDistContributionsForMake(distContributions *distContributions) []st // Compute the list of Make strings to declare phony goals and dist-for-goals // calls from the module's dist and dists properties. func (a *AndroidMkEntries) GetDistForGoals(mod Module) []string { - distContributions := a.getDistContributions(mod) + distContributions := getDistContributions(a.entryContext, mod) if distContributions == nil { return nil } @@ -537,6 +528,14 @@ func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod Module) { fmt.Fprintf(&a.header, "\ninclude $(CLEAR_VARS) # type: %s, name: %s, variant: %s\n", ctx.ModuleType(mod), base.BaseModuleName(), ctx.ModuleSubDir(mod)) + // Add the TestSuites from the provider to LOCAL_SOONG_PROVIDER_TEST_SUITES. + // LOCAL_SOONG_PROVIDER_TEST_SUITES will be compared against LOCAL_COMPATIBILITY_SUITES + // in make and enforced they're the same, to ensure we've successfully translated all + // LOCAL_COMPATIBILITY_SUITES usages to the provider. + if testSuiteInfo, ok := OtherModuleProvider(ctx, mod, TestSuiteInfoProvider); ok { + a.AddStrings("LOCAL_SOONG_PROVIDER_TEST_SUITES", testSuiteInfo.TestSuites...) + } + // Collect make variable assignment entries. a.SetString("LOCAL_PATH", ctx.ModuleDir(mod)) a.SetString("LOCAL_MODULE", name+a.SubName) @@ -889,32 +888,23 @@ func getSoongOnlyDataFromMods(ctx fillInEntriesContext, mods []Module) ([]distCo } } - commonInfo, _ := OtherModuleProvider(ctx, mod, CommonModuleInfoKey) + commonInfo := OtherModulePointerProviderOrDefault(ctx, mod, CommonModuleInfoProvider) if commonInfo.SkipAndroidMkProcessing { continue } if info, ok := OtherModuleProvider(ctx, mod, AndroidMkInfoProvider); ok { // Deep copy the provider info since we need to modify the info later info := deepCopyAndroidMkProviderInfo(info) - info.PrimaryInfo.fillInEntries(ctx, mod, &commonInfo) + info.PrimaryInfo.fillInEntries(ctx, mod, commonInfo) if info.PrimaryInfo.disabled() { continue } if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok { moduleInfoJSONs = append(moduleInfoJSONs, moduleInfoJSON...) } - if contribution := info.PrimaryInfo.getDistContributions(ctx, mod, &commonInfo); contribution != nil { + if contribution := getDistContributions(ctx, mod); contribution != nil { allDistContributions = append(allDistContributions, *contribution) } - for _, ei := range info.ExtraInfo { - ei.fillInEntries(ctx, mod, &commonInfo) - if ei.disabled() { - continue - } - if contribution := ei.getDistContributions(ctx, mod, &commonInfo); contribution != nil { - allDistContributions = append(allDistContributions, *contribution) - } - } } else { if x, ok := mod.(AndroidMkDataProvider); ok { data := x.AndroidMk() @@ -930,7 +920,7 @@ func getSoongOnlyDataFromMods(ctx fillInEntriesContext, mods []Module) ([]distCo if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok { moduleInfoJSONs = append(moduleInfoJSONs, moduleInfoJSON...) } - if contribution := data.Entries.getDistContributions(mod); contribution != nil { + if contribution := getDistContributions(ctx, mod); contribution != nil { allDistContributions = append(allDistContributions, *contribution) } } @@ -944,7 +934,7 @@ func getSoongOnlyDataFromMods(ctx fillInEntriesContext, mods []Module) ([]distCo if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok { moduleInfoJSONs = append(moduleInfoJSONs, moduleInfoJSON...) } - if contribution := entries.getDistContributions(mod); contribution != nil { + if contribution := getDistContributions(ctx, mod); contribution != nil { allDistContributions = append(allDistContributions, *contribution) } } @@ -1330,7 +1320,7 @@ var AndroidMkInfoProvider = blueprint.NewProvider[*AndroidMkProviderInfo]() // Please only access the module's internal data through providers. func translateAndroidMkEntriesInfoModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON, mod Module, providerInfo *AndroidMkProviderInfo) error { - commonInfo, _ := OtherModuleProvider(ctx, mod, CommonModuleInfoKey) + commonInfo := OtherModulePointerProviderOrDefault(ctx, mod, CommonModuleInfoProvider) if commonInfo.SkipAndroidMkProcessing { return nil } @@ -1341,11 +1331,11 @@ func translateAndroidMkEntriesInfoModule(ctx SingletonContext, w io.Writer, modu aconfigUpdateAndroidMkInfos(ctx, mod, &info) // Any new or special cases here need review to verify correct propagation of license information. - info.PrimaryInfo.fillInEntries(ctx, mod, &commonInfo) + info.PrimaryInfo.fillInEntries(ctx, mod, commonInfo) info.PrimaryInfo.write(w) if len(info.ExtraInfo) > 0 { for _, ei := range info.ExtraInfo { - ei.fillInEntries(ctx, mod, &commonInfo) + ei.fillInEntries(ctx, mod, commonInfo) ei.write(w) } } @@ -1494,12 +1484,17 @@ func (a *AndroidMkInfo) fillInEntries(ctx fillInEntriesContext, mod Module, comm a.Host_required = append(a.Host_required, commonInfo.HostRequiredModuleNames...) a.Target_required = append(a.Target_required, commonInfo.TargetRequiredModuleNames...) - for _, distString := range a.GetDistForGoals(ctx, mod, commonInfo) { - a.HeaderStrings = append(a.HeaderStrings, distString) - } - + a.HeaderStrings = append(a.HeaderStrings, a.GetDistForGoals(ctx, mod, commonInfo)...) a.HeaderStrings = append(a.HeaderStrings, fmt.Sprintf("\ninclude $(CLEAR_VARS) # type: %s, name: %s, variant: %s", ctx.ModuleType(mod), commonInfo.BaseModuleName, ctx.ModuleSubDir(mod))) + // Add the TestSuites from the provider to LOCAL_SOONG_PROVIDER_TEST_SUITES. + // LOCAL_SOONG_PROVIDER_TEST_SUITES will be compared against LOCAL_COMPATIBILITY_SUITES + // in make and enforced they're the same, to ensure we've successfully translated all + // LOCAL_COMPATIBILITY_SUITES usages to the provider. + if testSuiteInfo, ok := OtherModuleProvider(ctx, mod, TestSuiteInfoProvider); ok { + helperInfo.AddStrings("LOCAL_SOONG_PROVIDER_TEST_SUITES", testSuiteInfo.TestSuites...) + } + // Collect make variable assignment entries. helperInfo.SetString("LOCAL_PATH", ctx.ModuleDir(mod)) helperInfo.SetString("LOCAL_MODULE", name+a.SubName) @@ -1653,7 +1648,7 @@ func (a *AndroidMkInfo) write(w io.Writer) { // TODO(b/397766191): Change the signature to take ModuleProxy // Please only access the module's internal data through providers. func (a *AndroidMkInfo) GetDistForGoals(ctx fillInEntriesContext, mod Module, commonInfo *CommonModuleInfo) []string { - distContributions := a.getDistContributions(ctx, mod, commonInfo) + distContributions := getDistContributions(ctx, mod) if distContributions == nil { return nil } @@ -1661,127 +1656,6 @@ func (a *AndroidMkInfo) GetDistForGoals(ctx fillInEntriesContext, mod Module, co return generateDistContributionsForMake(distContributions) } -// Compute the contributions that the module makes to the dist. -// TODO(b/397766191): Change the signature to take ModuleProxy -// Please only access the module's internal data through providers. -func (a *AndroidMkInfo) getDistContributions(ctx fillInEntriesContext, mod Module, - commonInfo *CommonModuleInfo) *distContributions { - name := commonInfo.BaseModuleName - - // Collate the set of associated tag/paths available for copying to the dist. - // Start with an empty (nil) set. - var availableTaggedDists TaggedDistFiles - - // If no paths have been provided for the DefaultDistTag and the output file is - // valid then add that as the default dist path. - if a.OutputFile.Valid() { - availableTaggedDists = availableTaggedDists.addPathsForTag(DefaultDistTag, a.OutputFile.Path()) - } - - info := OtherModuleProviderOrDefault(ctx, mod, InstallFilesProvider) - // If the distFiles created by GenerateTaggedDistFiles contains paths for the - // DefaultDistTag then that takes priority so delete any existing paths. - if _, ok := info.DistFiles[DefaultDistTag]; ok { - delete(availableTaggedDists, DefaultDistTag) - } - - // Finally, merge the distFiles created by GenerateTaggedDistFiles. - availableTaggedDists = availableTaggedDists.merge(info.DistFiles) - - if len(availableTaggedDists) == 0 { - // Nothing dist-able for this module. - return nil - } - - // Collate the contributions this module makes to the dist. - distContributions := &distContributions{} - - if !commonInfo.ExemptFromRequiredApplicableLicensesProperty { - distContributions.licenseMetadataFile = info.LicenseMetadataFile - } - - // Iterate over this module's dist structs, merged from the dist and dists properties. - for _, dist := range commonInfo.Dists { - // Get the list of goals this dist should be enabled for. e.g. sdk, droidcore - goals := strings.Join(dist.Targets, " ") - - // Get the tag representing the output files to be dist'd. e.g. ".jar", ".proguard_map" - var tag string - if dist.Tag == nil { - // If the dist struct does not specify a tag, use the default output files tag. - tag = DefaultDistTag - } else { - tag = *dist.Tag - } - - // Get the paths of the output files to be dist'd, represented by the tag. - // Can be an empty list. - tagPaths := availableTaggedDists[tag] - if len(tagPaths) == 0 { - // Nothing to dist for this tag, continue to the next dist. - continue - } - - if len(tagPaths) > 1 && (dist.Dest != nil || dist.Suffix != nil) { - errorMessage := "%s: Cannot apply dest/suffix for more than one dist " + - "file for %q goals tag %q in module %s. The list of dist files, " + - "which should have a single element, is:\n%s" - panic(fmt.Errorf(errorMessage, mod, goals, tag, name, tagPaths)) - } - - copiesForGoals := distContributions.getCopiesForGoals(goals) - - // Iterate over each path adding a copy instruction to copiesForGoals - for _, path := range tagPaths { - // It's possible that the Path is nil from errant modules. Be defensive here. - if path == nil { - tagName := "default" // for error message readability - if dist.Tag != nil { - tagName = *dist.Tag - } - panic(fmt.Errorf("Dist file should not be nil for the %s tag in %s", tagName, name)) - } - - dest := filepath.Base(path.String()) - - if dist.Dest != nil { - var err error - if dest, err = validateSafePath(*dist.Dest); err != nil { - // This was checked in ModuleBase.GenerateBuildActions - panic(err) - } - } - - ext := filepath.Ext(dest) - suffix := "" - if dist.Suffix != nil { - suffix = *dist.Suffix - } - - productString := "" - if dist.Append_artifact_with_product != nil && *dist.Append_artifact_with_product { - productString = fmt.Sprintf("_%s", ctx.Config().DeviceProduct()) - } - - if suffix != "" || productString != "" { - dest = strings.TrimSuffix(dest, ext) + suffix + productString + ext - } - - if dist.Dir != nil { - var err error - if dest, err = validateSafePath(*dist.Dir, dest); err != nil { - // This was checked in ModuleBase.GenerateBuildActions - panic(err) - } - } - - copiesForGoals.addCopyInstruction(path, dest) - } - } - - return distContributions -} - func deepCopyAndroidMkProviderInfo(providerInfo *AndroidMkProviderInfo) AndroidMkProviderInfo { info := AndroidMkProviderInfo{ PrimaryInfo: deepCopyAndroidMkInfo(&providerInfo.PrimaryInfo), diff --git a/android/androidmk_test.go b/android/androidmk_test.go index 4cdd6a37b..cd61133ef 100644 --- a/android/androidmk_test.go +++ b/android/androidmk_test.go @@ -346,7 +346,7 @@ func TestGetDistContributions(t *testing.T) { if len(entries) != 1 { t.Errorf("Expected a single AndroidMk entry, got %d", len(entries)) } - distContributions := entries[0].getDistContributions(module) + distContributions := getDistContributions(ctx, module) if err := compareContributions(expectedContributions, distContributions); err != nil { t.Errorf("%s\nExpected Contributions\n%sActualContributions\n%s", @@ -648,8 +648,8 @@ func TestGetDistContributions(t *testing.T) { default_dist_files: "none", dist_output_file: false, dists: [ - // The following is silently ignored because there is not default file - // in either the dist files or the output file. + // The following will dist one.out because there's no default dist file provided + // (default_dist_files: "none") and one.out is the outputfile for the "" tag. { targets: ["my_goal"], }, @@ -664,6 +664,12 @@ func TestGetDistContributions(t *testing.T) { { goals: "my_goal", copies: []distCopy{ + distCopyForTest("one.out", "one.out"), + }, + }, + { + goals: "my_goal", + copies: []distCopy{ distCopyForTest("two.out", "two.out"), distCopyForTest("three/four.out", "four.out"), }, diff --git a/android/apex.go b/android/apex.go index 91fa2c718..57baff5cf 100644 --- a/android/apex.go +++ b/android/apex.go @@ -196,7 +196,7 @@ func IsDepInSameApex(ctx BaseModuleContext, module, dep Module) bool { return false } - if !ctx.EqualModules(ctx.Module(), module) { + if !EqualModules(ctx.Module(), module) { if moduleInfo, ok := OtherModuleProvider(ctx, module, DepInSameApexInfoProvider); ok { if !moduleInfo.Checker.OutgoingDepIsInSameApex(depTag) { return false @@ -646,6 +646,13 @@ type ApexBundleDepsInfoIntf interface { FullListPath() Path } +type ApexBundleDepsData struct { + Updatable bool + FlatListPath Path +} + +var ApexBundleDepsDataProvider = blueprint.NewProvider[ApexBundleDepsData]() + func (d *ApexBundleDepsInfo) FlatListPath() Path { return d.flatListPath } @@ -688,7 +695,7 @@ func (d *ApexBundleDepsInfo) BuildDepsInfoLists(ctx ModuleContext, minSdkVersion // Function called while walking an APEX's payload dependencies. // // Return true if the `to` module should be visited, false otherwise. -type PayloadDepsCallback func(ctx BaseModuleContext, from Module, to ApexModule, externalDep bool) bool +type PayloadDepsCallback func(ctx BaseModuleContext, from, to ModuleProxy, externalDep bool) bool type WalkPayloadDepsFunc func(ctx BaseModuleContext, do PayloadDepsCallback) // ModuleWithMinSdkVersionCheck represents a module that implements min_sdk_version checks @@ -716,7 +723,7 @@ func CheckMinSdkVersion(ctx ModuleContext, minSdkVersion ApiLevel, walk WalkPayl return } - walk(ctx, func(ctx BaseModuleContext, from Module, to ApexModule, externalDep bool) bool { + walk(ctx, func(ctx BaseModuleContext, from, to ModuleProxy, externalDep bool) bool { if externalDep { // external deps are outside the payload boundary, which is "stable" // interface. We don't have to check min_sdk_version for external @@ -726,7 +733,7 @@ func CheckMinSdkVersion(ctx ModuleContext, minSdkVersion ApiLevel, walk WalkPayl if !IsDepInSameApex(ctx, from, to) { return false } - if info, ok := OtherModuleProvider(ctx, to, CommonModuleInfoKey); ok && info.ModuleWithMinSdkVersionCheck { + if info, ok := OtherModuleProvider(ctx, to, CommonModuleInfoProvider); ok && info.ModuleWithMinSdkVersionCheck { if info.MinSdkVersion.ApiLevel == nil || !info.MinSdkVersion.ApiLevel.Specified() { // This dependency performs its own min_sdk_version check, just make sure it sets min_sdk_version // to trigger the check. @@ -758,7 +765,7 @@ type MinSdkVersionFromValueContext interface { // implementing this interface should provide an implementation. A module supports an sdk // version when the module's min_sdk_version is equal to or less than the given sdk version. func ShouldSupportSdkVersion(ctx BaseModuleContext, module Module, sdkVersion ApiLevel) error { - info, ok := OtherModuleProvider(ctx, module, CommonModuleInfoKey) + info, ok := OtherModuleProvider(ctx, module, CommonModuleInfoProvider) if !ok || info.MinSdkVersionSupported.IsNone() { return fmt.Errorf("min_sdk_version is not specified") } diff --git a/android/api_levels.go b/android/api_levels.go index c042eebee..c83fae878 100644 --- a/android/api_levels.go +++ b/android/api_levels.go @@ -19,6 +19,8 @@ import ( "fmt" "strconv" "strings" + + "github.com/google/blueprint/gobtools" ) func init() { @@ -52,6 +54,34 @@ type ApiLevel struct { isPreview bool } +type apiLevelGob struct { + Value string + Number int + IsPreview bool +} + +func (a *ApiLevel) ToGob() *apiLevelGob { + return &apiLevelGob{ + Value: a.value, + Number: a.number, + IsPreview: a.isPreview, + } +} + +func (a *ApiLevel) FromGob(data *apiLevelGob) { + a.value = data.Value + a.number = data.Number + a.isPreview = data.IsPreview +} + +func (a ApiLevel) GobEncode() ([]byte, error) { + return gobtools.CustomGobEncode[apiLevelGob](&a) +} + +func (a *ApiLevel) GobDecode(data []byte) error { + return gobtools.CustomGobDecode[apiLevelGob](data, a) +} + func (this ApiLevel) FinalInt() int { if this.IsInvalid() { panic(fmt.Errorf("%v is not a recognized api_level\n", this)) diff --git a/android/arch.go b/android/arch.go index 3cd6e4b7a..d6b297119 100644 --- a/android/arch.go +++ b/android/arch.go @@ -1553,7 +1553,7 @@ func determineBuildOS(config *config) { config.BuildOS = func() OsType { switch runtime.GOOS { case "linux": - if Bool(config.productVariables.HostMusl) { + if Bool(config.productVariables.HostMusl) || runtime.GOARCH == "arm64" { return LinuxMusl } return Linux @@ -1565,11 +1565,25 @@ func determineBuildOS(config *config) { }() config.BuildArch = func() ArchType { - switch runtime.GOARCH { - case "amd64": - return X86_64 + switch runtime.GOOS { + case "linux": + switch runtime.GOARCH { + case "amd64": + return X86_64 + case "arm64": + return Arm64 + default: + panic(fmt.Sprintf("unsupported arch: %s", runtime.GOARCH)) + } + case "darwin": + switch runtime.GOARCH { + case "amd64": + return X86_64 + default: + panic(fmt.Sprintf("unsupported arch: %s", runtime.GOARCH)) + } default: - panic(fmt.Sprintf("unsupported Arch: %s", runtime.GOARCH)) + panic(fmt.Sprintf("unsupported OS: %s", runtime.GOOS)) } }() diff --git a/android/base_module_context.go b/android/base_module_context.go index 5e05f547a..5cb9e71cf 100644 --- a/android/base_module_context.go +++ b/android/base_module_context.go @@ -34,8 +34,6 @@ type BaseModuleContext interface { blueprintBaseModuleContext() blueprint.BaseModuleContext - EqualModules(m1, m2 Module) bool - // OtherModuleName returns the name of another Module. See BaseModuleContext.ModuleName for more information. // It is intended for use inside the visit functions of Visit* and WalkDeps. OtherModuleName(m blueprint.Module) string @@ -271,8 +269,8 @@ func getWrappedModule(module blueprint.Module) blueprint.Module { return module } -func (b *baseModuleContext) EqualModules(m1, m2 Module) bool { - return b.bp.EqualModules(getWrappedModule(m1), getWrappedModule(m2)) +func EqualModules(m1, m2 Module) bool { + return blueprint.EqualModules(getWrappedModule(m1), getWrappedModule(m2)) } func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string { @@ -412,7 +410,7 @@ func (b *baseModuleContext) validateAndroidModuleProxy( return &aModule } - if !OtherModuleProviderOrDefault(b, module, CommonModuleInfoKey).Enabled { + if !OtherModulePointerProviderOrDefault(b, module, CommonModuleInfoProvider).Enabled { if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependencyProxy(b, aModule) { if b.Config().AllowMissingDependencies() { b.AddMissingDependencies([]string{b.OtherModuleName(aModule)}) @@ -442,7 +440,7 @@ func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.Dep func (b *baseModuleContext) getDirectDepsProxyInternal(name string, tag blueprint.DependencyTag) []ModuleProxy { var deps []ModuleProxy b.VisitDirectDepsProxy(func(module ModuleProxy) { - if OtherModuleProviderOrDefault(b, module, CommonModuleInfoKey).BaseModuleName == name { + if OtherModulePointerProviderOrDefault(b, module, CommonModuleInfoProvider).BaseModuleName == name { returnedTag := b.OtherModuleDependencyTag(module) if tag == nil || returnedTag == tag { deps = append(deps, module) diff --git a/android/compliance_metadata.go b/android/compliance_metadata.go index a6dbb8d17..16a385300 100644 --- a/android/compliance_metadata.go +++ b/android/compliance_metadata.go @@ -18,7 +18,9 @@ import ( "bytes" "encoding/csv" "fmt" + "path/filepath" "slices" + "sort" "strconv" "strings" @@ -127,27 +129,37 @@ var ( // dependencies, built/installed files, etc. It is a wrapper on a map[string]string with some utility // methods to get/set properties' values. type ComplianceMetadataInfo struct { - properties map[string]string + properties map[string]string + filesContained []string + prebuiltFilesCopied []string } type complianceMetadataInfoGob struct { - Properties map[string]string + Properties map[string]string + FilesContained []string + PrebuiltFilesCopied []string } func NewComplianceMetadataInfo() *ComplianceMetadataInfo { return &ComplianceMetadataInfo{ - properties: map[string]string{}, + properties: map[string]string{}, + filesContained: make([]string, 0), + prebuiltFilesCopied: make([]string, 0), } } func (m *ComplianceMetadataInfo) ToGob() *complianceMetadataInfoGob { return &complianceMetadataInfoGob{ - Properties: m.properties, + Properties: m.properties, + FilesContained: m.filesContained, + PrebuiltFilesCopied: m.prebuiltFilesCopied, } } func (m *ComplianceMetadataInfo) FromGob(data *complianceMetadataInfoGob) { m.properties = data.Properties + m.filesContained = data.FilesContained + m.prebuiltFilesCopied = data.PrebuiltFilesCopied } func (c *ComplianceMetadataInfo) GobEncode() ([]byte, error) { @@ -169,6 +181,22 @@ func (c *ComplianceMetadataInfo) SetListValue(propertyName string, value []strin c.SetStringValue(propertyName, strings.TrimSpace(strings.Join(value, " "))) } +func (c *ComplianceMetadataInfo) SetFilesContained(files []string) { + c.filesContained = files +} + +func (c *ComplianceMetadataInfo) GetFilesContained() []string { + return c.filesContained +} + +func (c *ComplianceMetadataInfo) SetPrebuiltFilesCopied(files []string) { + c.prebuiltFilesCopied = files +} + +func (c *ComplianceMetadataInfo) GetPrebuiltFilesCopied() []string { + return c.prebuiltFilesCopied +} + func (c *ComplianceMetadataInfo) getStringValue(propertyName string) string { if !slices.Contains(COMPLIANCE_METADATA_PROPS, propertyName) { panic(fmt.Errorf("Unknown metadata property: %s.", propertyName)) @@ -276,7 +304,7 @@ func (c *complianceMetadataSingleton) GenerateBuildActions(ctx SingletonContext) rowId := -1 ctx.VisitAllModuleProxies(func(module ModuleProxy) { - commonInfo, _ := OtherModuleProvider(ctx, module, CommonModuleInfoKey) + commonInfo := OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider) if !commonInfo.Enabled { return } @@ -316,9 +344,42 @@ func (c *complianceMetadataSingleton) GenerateBuildActions(ctx SingletonContext) makeMetadataCsv := PathForOutput(ctx, "compliance-metadata", deviceProduct, "make-metadata.csv") makeModulesCsv := PathForOutput(ctx, "compliance-metadata", deviceProduct, "make-modules.csv") + productOutPath := filepath.Join(ctx.Config().OutDir(), "target", "product", String(ctx.Config().productVariables.DeviceName)) if !ctx.Config().KatiEnabled() { - WriteFileRule(ctx, makeMetadataCsv, "installed_file,module_path,is_soong_module,is_prebuilt_make_module,product_copy_files,kernel_module_copy_files,is_platform_generated,static_libs,whole_static_libs,license_text") - WriteFileRule(ctx, makeModulesCsv, "name,module_path,module_class,module_type,static_libs,whole_static_libs,built_files,installed_files") + ctx.VisitAllModuleProxies(func(module ModuleProxy) { + // In soong-only build the installed file list is from android_device module + if androidDeviceInfo, ok := OtherModuleProvider(ctx, module, AndroidDeviceInfoProvider); ok && androidDeviceInfo.Main_device { + if metadataInfo, ok := OtherModuleProvider(ctx, module, ComplianceMetadataProvider); ok { + if len(metadataInfo.filesContained) > 0 || len(metadataInfo.prebuiltFilesCopied) > 0 { + allFiles := make([]string, 0, len(metadataInfo.filesContained)+len(metadataInfo.prebuiltFilesCopied)) + allFiles = append(allFiles, metadataInfo.filesContained...) + prebuiltFilesSrcDest := make(map[string]string) + for _, srcDestPair := range metadataInfo.prebuiltFilesCopied { + prebuiltFilePath := filepath.Join(productOutPath, strings.Split(srcDestPair, ":")[1]) + allFiles = append(allFiles, prebuiltFilePath) + prebuiltFilesSrcDest[prebuiltFilePath] = srcDestPair + } + sort.Strings(allFiles) + + csvHeaders := "installed_file,module_path,is_soong_module,is_prebuilt_make_module,product_copy_files,kernel_module_copy_files,is_platform_generated,static_libs,whole_static_libs,license_text" + csvContent := make([]string, 0, len(allFiles)+1) + csvContent = append(csvContent, csvHeaders) + for _, file := range allFiles { + if _, ok := prebuiltFilesSrcDest[file]; ok { + srcDestPair := prebuiltFilesSrcDest[file] + csvContent = append(csvContent, file+",,,,"+srcDestPair+",,,,,") + } else { + csvContent = append(csvContent, file+",,Y,,,,,,,") + } + } + + WriteFileRuleVerbatim(ctx, makeMetadataCsv, strings.Join(csvContent, "\n")) + WriteFileRuleVerbatim(ctx, makeModulesCsv, "name,module_path,module_class,module_type,static_libs,whole_static_libs,built_files,installed_files") + } + return + } + } + }) } // Import metadata from Make and Soong to sqlite3 database diff --git a/android/config.go b/android/config.go index a5edf0da8..d47f0d44a 100644 --- a/android/config.go +++ b/android/config.go @@ -200,6 +200,11 @@ func (c Config) ReleaseAconfigValueSets() []string { return c.config.productVariables.ReleaseAconfigValueSets } +// If native modules should have symbols stripped by default. Default false, enabled for build tools +func (c Config) StripByDefault() bool { + return proptools.Bool(c.config.productVariables.StripByDefault) +} + func (c Config) ReleaseAconfigExtraReleaseConfigs() []string { result := []string{} if val, ok := c.config.productVariables.BuildFlags["RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS"]; ok { @@ -233,11 +238,6 @@ func (c Config) ReleaseAconfigFlagDefaultPermission() string { return c.config.productVariables.ReleaseAconfigFlagDefaultPermission } -// Enable object size sanitizer -func (c Config) ReleaseBuildObjectSizeSanitizer() bool { - return c.config.productVariables.GetBuildFlagBool("RELEASE_BUILD_OBJECT_SIZE_SANITIZER") -} - // The flag indicating behavior for the tree wrt building modules or using prebuilts // derived from RELEASE_DEFAULT_MODULE_BUILD_FROM_SOURCE func (c Config) ReleaseDefaultModuleBuildFromSource() bool { @@ -385,24 +385,28 @@ type config struct { } type partialCompileFlags struct { - // Is partial compilation enabled at all? - Enabled bool - // Whether to use d8 instead of r8 Use_d8 bool + // Whether to disable stub validation. This is slightly more surgical + // than DISABLE_STUB_VALIDATION, in that it only applies to partial + // compile builds. + Disable_stub_validation bool + + // Whether to disable api lint. + Disable_api_lint bool + // Add others as needed. } // These are the flags when `SOONG_PARTIAL_COMPILE` is empty or not set. -var defaultPartialCompileFlags = partialCompileFlags{ - Enabled: false, -} +var defaultPartialCompileFlags = partialCompileFlags{} // These are the flags when `SOONG_PARTIAL_COMPILE=true`. var enabledPartialCompileFlags = partialCompileFlags{ - Enabled: true, - Use_d8: true, + Use_d8: true, + Disable_stub_validation: false, + Disable_api_lint: false, } type deviceConfig struct { @@ -477,13 +481,29 @@ func (c *config) parsePartialCompileFlags(isEngBuild bool) (partialCompileFlags, state = "+" } switch tok { + case "all": + // Turn on **all** of the flags. + ret = partialCompileFlags{ + Use_d8: true, + Disable_stub_validation: true, + Disable_api_lint: true, + } case "true": ret = enabledPartialCompileFlags case "false": // Set everything to false. ret = partialCompileFlags{} - case "enabled": - ret.Enabled = makeVal(state, defaultPartialCompileFlags.Enabled) + + case "api_lint", "enable_api_lint": + ret.Disable_api_lint = !makeVal(state, !defaultPartialCompileFlags.Disable_api_lint) + case "disable_api_lint": + ret.Disable_api_lint = makeVal(state, defaultPartialCompileFlags.Disable_api_lint) + + case "stub_validation", "enable_stub_validation": + ret.Disable_stub_validation = !makeVal(state, !defaultPartialCompileFlags.Disable_stub_validation) + case "disable_stub_validation": + ret.Disable_stub_validation = makeVal(state, defaultPartialCompileFlags.Disable_stub_validation) + case "use_d8": ret.Use_d8 = makeVal(state, defaultPartialCompileFlags.Use_d8) default: @@ -814,11 +834,18 @@ func (c *config) HostCcSharedLibPath(ctx PathContext, lib string) Path { func (c *config) PrebuiltOS() string { switch runtime.GOOS { case "linux": - return "linux-x86" + switch runtime.GOARCH { + case "amd64": + return "linux-x86" + case "arm64": + return "linux-arm64" + default: + panic(fmt.Errorf("Unknown GOARCH %s", runtime.GOARCH)) + } case "darwin": return "darwin-x86" default: - panic("Unknown GOOS") + panic(fmt.Errorf("Unknown GOOS %s", runtime.GOOS)) } } @@ -2222,7 +2249,6 @@ var ( "RELEASE_APEX_CONTRIBUTIONS_NFC": "com.android.nfcservices", "RELEASE_APEX_CONTRIBUTIONS_ONDEVICEPERSONALIZATION": "com.android.ondevicepersonalization", "RELEASE_APEX_CONTRIBUTIONS_PERMISSION": "com.android.permission", - "RELEASE_APEX_CONTRIBUTIONS_PRIMARY_LIBS": "", "RELEASE_APEX_CONTRIBUTIONS_PROFILING": "com.android.profiling", "RELEASE_APEX_CONTRIBUTIONS_REMOTEKEYPROVISIONING": "com.android.rkpd", "RELEASE_APEX_CONTRIBUTIONS_RESOLV": "com.android.resolv", diff --git a/android/config_test.go b/android/config_test.go index 3d8686041..d1b26c12a 100644 --- a/android/config_test.go +++ b/android/config_test.go @@ -213,13 +213,18 @@ func TestConfiguredJarList(t *testing.T) { }) } -func (p partialCompileFlags) updateEnabled(value bool) partialCompileFlags { - p.Enabled = value +func (p partialCompileFlags) updateUseD8(value bool) partialCompileFlags { + p.Use_d8 = value return p } -func (p partialCompileFlags) updateUseD8(value bool) partialCompileFlags { - p.Use_d8 = value +func (p partialCompileFlags) updateDisableApiLint(value bool) partialCompileFlags { + p.Disable_api_lint = value + return p +} + +func (p partialCompileFlags) updateDisableStubValidation(value bool) partialCompileFlags { + p.Disable_stub_validation = value return p } @@ -241,10 +246,29 @@ func TestPartialCompile(t *testing.T) { {"false", true, partialCompileFlags{}}, {"true", true, enabledPartialCompileFlags}, {"true", false, partialCompileFlags{}}, + {"all", true, partialCompileFlags{}.updateUseD8(true).updateDisableApiLint(true).updateDisableStubValidation(true)}, + + // This verifies both use_d8 and the processing order. {"true,use_d8", true, enabledPartialCompileFlags.updateUseD8(true)}, {"true,-use_d8", true, enabledPartialCompileFlags.updateUseD8(false)}, {"use_d8,false", true, partialCompileFlags{}}, {"false,+use_d8", true, partialCompileFlags{}.updateUseD8(true)}, + + // disable_api_lint can be specified with any of 3 options. + {"false,-api_lint", true, partialCompileFlags{}.updateDisableApiLint(true)}, + {"false,-enable_api_lint", true, partialCompileFlags{}.updateDisableApiLint(true)}, + {"false,+disable_api_lint", true, partialCompileFlags{}.updateDisableApiLint(true)}, + {"false,+api_lint", true, partialCompileFlags{}.updateDisableApiLint(false)}, + {"false,+enable_api_lint", true, partialCompileFlags{}.updateDisableApiLint(false)}, + {"false,-disable_api_lint", true, partialCompileFlags{}.updateDisableApiLint(false)}, + + // disable_stub_validation can be specified with any of 3 options. + {"false,-stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(true)}, + {"false,-enable_stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(true)}, + {"false,+disable_stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(true)}, + {"false,+stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(false)}, + {"false,+enable_stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(false)}, + {"false,-disable_stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(false)}, } for _, test := range tests { diff --git a/android/container.go b/android/container.go index 5dc97d38e..547fe816c 100644 --- a/android/container.go +++ b/android/container.go @@ -39,7 +39,7 @@ type StubsAvailableModule interface { // Returns true if the dependency module is a stubs module var depIsStubsModule exceptionHandleFunc = func(mctx ModuleContext, _ Module, dep ModuleProxy) bool { - return OtherModuleProviderOrDefault(mctx, dep, CommonModuleInfoKey).IsStubsModule + return OtherModulePointerProviderOrDefault(mctx, dep, CommonModuleInfoProvider).IsStubsModule } // Returns true if the dependency module belongs to any of the apexes. @@ -449,7 +449,7 @@ func generateContainerInfo(ctx ModuleContext) ContainersInfo { } func getContainerModuleInfo(ctx ModuleContext, module Module) (ContainersInfo, bool) { - if ctx.EqualModules(ctx.Module(), module) { + if EqualModules(ctx.Module(), module) { return ctx.getContainersInfo(), true } @@ -474,7 +474,7 @@ func checkContainerViolations(ctx ModuleContext) { if _, ok := ctx.Module().(InstallableModule); ok { containersInfo, _ := getContainerModuleInfo(ctx, ctx.Module()) ctx.VisitDirectDepsProxy(func(dep ModuleProxy) { - if !OtherModuleProviderOrDefault(ctx, dep, CommonModuleInfoKey).Enabled { + if !OtherModuleProviderOrDefault(ctx, dep, CommonModuleInfoProvider).Enabled { return } diff --git a/android/filegroup.go b/android/filegroup.go index 47102b915..9bcfd0a83 100644 --- a/android/filegroup.go +++ b/android/filegroup.go @@ -33,6 +33,7 @@ var PrepareForTestWithFilegroup = FixtureRegisterWithContext(func(ctx Registrati func RegisterFilegroupBuildComponents(ctx RegistrationContext) { ctx.RegisterModuleType("filegroup", FileGroupFactory) ctx.RegisterModuleType("filegroup_defaults", FileGroupDefaultsFactory) + ctx.RegisterModuleType("otatools_package_filegroup", OtatoolsFileGroupFactory) } type fileGroupProperties struct { @@ -131,10 +132,11 @@ func (fg *fileGroup) Srcs() Paths { return append(Paths{}, fg.srcs...) } -func (fg *fileGroup) MakeVars(ctx MakeVarsModuleContext) { +func (fg *fileGroup) MakeVars(_ MakeVarsModuleContext) []ModuleMakeVarsValue { if makeVar := String(fg.properties.Export_to_make_var); makeVar != "" { - ctx.StrictRaw(makeVar, strings.Join(fg.srcs.Strings(), " ")) + return []ModuleMakeVarsValue{{makeVar, strings.Join(fg.srcs.Strings(), " ")}} } + return nil } // Defaults @@ -162,3 +164,54 @@ func (fg *fileGroup) IDEInfo(ctx BaseModuleContext, dpInfo *IdeInfo) { } } } + +type OtatoolsFileGroup struct { + ModuleBase +} + +func OtatoolsFileGroupFactory() Module { + module := &OtatoolsFileGroup{} + InitAndroidModule(module) + AddLoadHook(module, func(ctx LoadHookContext) { + module.createOTAToolsPackagefilegroup(ctx) + }) + return module +} + +func (fg *OtatoolsFileGroup) GenerateAndroidBuildActions(ctx ModuleContext) { +} + +// Create the filegroup to collect cert files for otatools.zip. +func (fg *OtatoolsFileGroup) createOTAToolsPackagefilegroup(ctx LoadHookContext) { + ctx.CreateModuleInDirectory( + FileGroupFactory, + ".", + &struct { + Name *string + Srcs []string + Visibility []string + }{ + Name: proptools.StringPtr("soong_generated_otatools_package_filegroup"), + Srcs: []string{ + "build/make/target/product/security/**/*.x509.pem", + "build/make/target/product/security/**/*.pk8", + "device/**/*.pk8", + "device/**/verifiedboot*", + "device/**/*.pem", + "device/**/oem*.prop", + "device/**/*.avbpubkey", + "external/avb/test/data/**/testkey_*.pem", + "external/avb/test/data/**/atx_metadata.bin", + "packages/modules/**/*.x509.pem", + "packages/modules/**/*.pk8", + "packages/modules/**/*.key.pem", + "vendor/**/*.pk8", + "vendor/**/verifiedboot*", + "vendor/**/*.pem", + "vendor/**/oem*.prop", + "vendor/**/*.avbpubkey", + }, + Visibility: []string{"//build/make/tools/otatools_package"}, + }, + ) +} diff --git a/android/gen_notice.go b/android/gen_notice.go index 9adde9e9b..45f90f47c 100644 --- a/android/gen_notice.go +++ b/android/gen_notice.go @@ -19,6 +19,7 @@ import ( "path/filepath" "strings" + "github.com/google/blueprint" "github.com/google/blueprint/proptools" ) @@ -35,34 +36,31 @@ func RegisterGenNoticeBuildComponents(ctx RegistrationContext) { type genNoticeBuildRules struct{} func (s *genNoticeBuildRules) GenerateBuildActions(ctx SingletonContext) { - ctx.VisitAllModules(func(m Module) { - gm, ok := m.(*genNoticeModule) + ctx.VisitAllModuleProxies(func(m ModuleProxy) { + gm, ok := OtherModuleProvider(ctx, m, GenNoticeInfoProvider) if !ok { return } - if len(gm.missing) > 0 { - missingReferencesRule(ctx, gm) + if len(gm.Missing) > 0 { + missingReferencesRule(ctx, m, &gm) return } out := BuildNoticeTextOutputFromLicenseMetadata - if proptools.Bool(gm.properties.Xml) { + if gm.Xml { out = BuildNoticeXmlOutputFromLicenseMetadata - } else if proptools.Bool(gm.properties.Html) { + } else if gm.Html { out = BuildNoticeHtmlOutputFromLicenseMetadata } defaultName := "" - if len(gm.properties.For) > 0 { - defaultName = gm.properties.For[0] + if len(gm.For) > 0 { + defaultName = gm.For[0] } - modules := make([]Module, 0) - for _, name := range gm.properties.For { - mods := ctx.ModuleVariantsFromName(gm, name) + modules := make([]ModuleProxy, 0) + for _, name := range gm.For { + mods := ctx.ModuleVariantsFromName(m, name) for _, mod := range mods { - if mod == nil { - continue - } - if !mod.Enabled(ctx) { // don't depend on variants without build rules + if !OtherModulePointerProviderOrDefault(ctx, mod, CommonModuleInfoProvider).Enabled { // don't depend on variants without build rules continue } modules = append(modules, mod) @@ -71,8 +69,8 @@ func (s *genNoticeBuildRules) GenerateBuildActions(ctx SingletonContext) { if ctx.Failed() { return } - out(ctx, gm.output, ctx.ModuleName(gm), - proptools.StringDefault(gm.properties.ArtifactName, defaultName), + out(ctx, gm.Output, ctx.ModuleName(m), + proptools.StringDefault(gm.ArtifactName, defaultName), []string{ filepath.Join(ctx.Config().OutDir(), "target", "product", ctx.Config().DeviceName()) + "/", ctx.Config().OutDir() + "/", @@ -115,6 +113,22 @@ type genNoticeModule struct { missing []string } +type GenNoticeInfo struct { + // For specifies the modules for which to generate a notice file. + For []string + // ArtifactName specifies the internal name to use for the notice file. + // It appears in the "used by:" list for targets whose entire name is stripped by --strip_prefix. + ArtifactName *string + // Html indicates an html-format file is needed. The default is text. Can be Html or Xml but not both. + Html bool + // Xml indicates an xml-format file is needed. The default is text. Can be Html or Xml but not both. + Xml bool + Output OutputPath + Missing []string +} + +var GenNoticeInfoProvider = blueprint.NewProvider[GenNoticeInfo]() + func (m *genNoticeModule) DepsMutator(ctx BottomUpMutatorContext) { if ctx.ContainsProperty("licenses") { ctx.PropertyErrorf("licenses", "not supported on \"gen_notice\" modules") @@ -176,6 +190,15 @@ func (m *genNoticeModule) GenerateAndroidBuildActions(ctx ModuleContext) { } out := m.getStem() + m.getSuffix() m.output = PathForModuleOut(ctx, out).OutputPath + + SetProvider(ctx, GenNoticeInfoProvider, GenNoticeInfo{ + For: m.properties.For, + ArtifactName: m.properties.ArtifactName, + Xml: proptools.Bool(m.properties.Xml), + Html: proptools.Bool(m.properties.Html), + Output: m.output, + Missing: m.missing, + }) ctx.SetOutputFiles(Paths{m.output}, "") } @@ -205,17 +228,17 @@ func (m *genNoticeModule) AndroidMkEntries() []AndroidMkEntries { } // missingReferencesRule emits an ErrorRule for missing module references. -func missingReferencesRule(ctx BuilderContext, m *genNoticeModule) { - if len(m.missing) < 1 { +func missingReferencesRule(ctx BuilderContext, m ModuleProxy, genInfo *GenNoticeInfo) { + if len(genInfo.Missing) < 1 { panic(fmt.Errorf("missing references rule requested with no missing references")) } ctx.Build(pctx, BuildParams{ Rule: ErrorRule, - Output: m.output, - Description: "notice for " + proptools.StringDefault(m.properties.ArtifactName, "container"), + Output: genInfo.Output, + Description: "notice for " + proptools.StringDefault(genInfo.ArtifactName, "container"), Args: map[string]string{ - "error": m.Name() + " references missing module(s): " + strings.Join(m.missing, ", "), + "error": m.Name() + " references missing module(s): " + strings.Join(genInfo.Missing, ", "), }, }) } diff --git a/android/init.go b/android/init.go index d3a13d0ed..af50323d3 100644 --- a/android/init.go +++ b/android/init.go @@ -17,6 +17,7 @@ package android import "encoding/gob" func init() { + gob.Register(applicableLicensesPropertyImpl{}) gob.Register(extraFilesZip{}) gob.Register(InstallPath{}) gob.Register(ModuleGenPath{}) diff --git a/android/license_metadata.go b/android/license_metadata.go index d15dfa841..0b880dd8a 100644 --- a/android/license_metadata.go +++ b/android/license_metadata.go @@ -65,7 +65,7 @@ func buildLicenseMetadata(ctx *moduleContext, licenseMetadataFile WritablePath) var allDepMetadataDepSets []depset.DepSet[Path] ctx.VisitDirectDepsProxy(func(dep ModuleProxy) { - if !OtherModuleProviderOrDefault(ctx, dep, CommonModuleInfoKey).Enabled { + if !OtherModulePointerProviderOrDefault(ctx, dep, CommonModuleInfoProvider).Enabled { return } diff --git a/android/licenses.go b/android/licenses.go index 32d12c8a2..387792144 100644 --- a/android/licenses.go +++ b/android/licenses.go @@ -22,6 +22,7 @@ import ( "sync" "github.com/google/blueprint" + "github.com/google/blueprint/gobtools" ) // Adds cross-cutting licenses dependency to propagate license metadata through the build system. @@ -67,6 +68,31 @@ type applicableLicensesPropertyImpl struct { licensesProperty *[]string } +type applicableLicensesPropertyImplGob struct { + Name string + LicensesProperty []string +} + +func (a *applicableLicensesPropertyImpl) ToGob() *applicableLicensesPropertyImplGob { + return &applicableLicensesPropertyImplGob{ + Name: a.name, + LicensesProperty: *a.licensesProperty, + } +} + +func (a *applicableLicensesPropertyImpl) FromGob(data *applicableLicensesPropertyImplGob) { + a.name = data.Name + a.licensesProperty = &data.LicensesProperty +} + +func (a applicableLicensesPropertyImpl) GobEncode() ([]byte, error) { + return gobtools.CustomGobEncode[applicableLicensesPropertyImplGob](&a) +} + +func (a *applicableLicensesPropertyImpl) GobDecode(data []byte) error { + return gobtools.CustomGobDecode[applicableLicensesPropertyImplGob](data, a) +} + func newApplicableLicensesProperty(name string, licensesProperty *[]string) applicableLicensesProperty { return applicableLicensesPropertyImpl{ name: name, @@ -351,9 +377,7 @@ func licensesMakeVarsProvider(ctx MakeVarsContext) { ctx.Strict("HTMLNOTICE", ctx.Config().HostToolPath(ctx, "htmlnotice").String()) ctx.Strict("XMLNOTICE", ctx.Config().HostToolPath(ctx, "xmlnotice").String()) ctx.Strict("TEXTNOTICE", ctx.Config().HostToolPath(ctx, "textnotice").String()) - ctx.Strict("COMPLIANCENOTICE_BOM", ctx.Config().HostToolPath(ctx, "compliancenotice_bom").String()) ctx.Strict("COMPLIANCENOTICE_SHIPPEDLIBS", ctx.Config().HostToolPath(ctx, "compliancenotice_shippedlibs").String()) ctx.Strict("COMPLIANCE_LISTSHARE", ctx.Config().HostToolPath(ctx, "compliance_listshare").String()) ctx.Strict("COMPLIANCE_CHECKSHARE", ctx.Config().HostToolPath(ctx, "compliance_checkshare").String()) - ctx.Strict("COMPLIANCE_SBOM", ctx.Config().HostToolPath(ctx, "compliance_sbom").String()) } diff --git a/android/logtags.go b/android/logtags.go index abc37f997..074f402e7 100644 --- a/android/logtags.go +++ b/android/logtags.go @@ -42,8 +42,8 @@ func MergedLogtagsPath(ctx PathContext) OutputPath { func (l *logtagsSingleton) GenerateBuildActions(ctx SingletonContext) { var allLogtags Paths - ctx.VisitAllModules(func(module Module) { - if !module.ExportedToMake() { + ctx.VisitAllModuleProxies(func(module ModuleProxy) { + if !OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider).ExportedToMake { return } if logtagsInfo, ok := OtherModuleProvider(ctx, module, LogtagsProviderKey); ok { diff --git a/android/makevars.go b/android/makevars.go index 2931d0bed..7017e7db0 100644 --- a/android/makevars.go +++ b/android/makevars.go @@ -84,6 +84,7 @@ type MakeVarsContext interface { Errorf(format string, args ...interface{}) VisitAllModules(visit func(Module)) + VisitAllModuleProxies(visit func(proxy ModuleProxy)) VisitAllModulesIf(pred func(Module) bool, visit func(Module)) // Verify the make variable matches the Soong version, fail the build @@ -108,7 +109,7 @@ type MakeVarsContext interface { // MakeVarsModuleContext contains the set of functions available for modules // implementing the ModuleMakeVarsProvider interface. type MakeVarsModuleContext interface { - BaseMakeVarsContext + Config() Config } var _ PathContext = MakeVarsContext(nil) @@ -150,14 +151,21 @@ func singletonMakeVarsProviderAdapter(singleton SingletonMakeVarsProvider) MakeV return func(ctx MakeVarsContext) { singleton.MakeVars(ctx) } } +type ModuleMakeVarsValue struct { + // Make variable name. + Name string + // Make variable value. + Value string +} + // ModuleMakeVarsProvider is a Module with an extra method to provide extra values to be exported to Make. type ModuleMakeVarsProvider interface { - Module - // MakeVars uses a MakeVarsModuleContext to provide extra values to be exported to Make. - MakeVars(ctx MakeVarsModuleContext) + MakeVars(ctx MakeVarsModuleContext) []ModuleMakeVarsValue } +var ModuleMakeVarsInfoProvider = blueprint.NewProvider[[]ModuleMakeVarsValue]() + // ///////////////////////////////////////////////////////////////////////////// func makeVarsSingletonFunc() Singleton { @@ -250,19 +258,24 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) { dists = append(dists, singletonDists.dists...) singletonDists.lock.Unlock() - ctx.VisitAllModules(func(m Module) { - if provider, ok := m.(ModuleMakeVarsProvider); ok && m.Enabled(ctx) { + ctx.VisitAllModuleProxies(func(m ModuleProxy) { + commonInfo := OtherModulePointerProviderOrDefault(ctx, m, CommonModuleInfoProvider) + if provider, ok := OtherModuleProvider(ctx, m, ModuleMakeVarsInfoProvider); ok && + commonInfo.Enabled { mctx := &makeVarsContext{ SingletonContext: ctx, } - - provider.MakeVars(mctx) + for _, val := range provider { + if val.Name != "" { + mctx.StrictRaw(val.Name, val.Value) + } + } vars = append(vars, mctx.vars...) phonies = append(phonies, mctx.phonies...) } - if m.ExportedToMake() { + if commonInfo.ExportedToMake { info := OtherModuleProviderOrDefault(ctx, m, InstallFilesProvider) katiInstalls = append(katiInstalls, info.KatiInstalls...) katiInitRcInstalls = append(katiInitRcInstalls, info.KatiInitRcInstalls...) diff --git a/android/module.go b/android/module.go index d387c2cf3..a3fe837a5 100644 --- a/android/module.go +++ b/android/module.go @@ -15,6 +15,7 @@ package android import ( + "errors" "fmt" "net/url" "path/filepath" @@ -519,6 +520,11 @@ type baseProperties struct { // names of other modules to install on target if this module is installed Target_required []string `android:"arch_variant"` + + // If this is a soong config module, this property will be set to the name of the original + // module type. This is used by neverallow to ensure you can't bypass a ModuleType() matcher + // just by creating a soong config module type. + Soong_config_base_module_type *string `blueprint:"mutated"` } type distProperties struct { @@ -996,11 +1002,19 @@ func (m *ModuleBase) baseDepsMutator(ctx BottomUpMutatorContext) { pv := ctx.Config().productVariables fullManifest := pv.DeviceArch != nil && pv.DeviceName != nil if fullManifest { - addRequiredDeps(ctx) addVintfFragmentDeps(ctx) } } +// required property can be overridden too; handle it separately +func (m *ModuleBase) baseOverridablePropertiesDepsMutator(ctx BottomUpMutatorContext) { + pv := ctx.Config().productVariables + fullManifest := pv.DeviceArch != nil && pv.DeviceName != nil + if fullManifest { + addRequiredDeps(ctx) + } +} + // addRequiredDeps adds required, target_required, and host_required as dependencies. func addRequiredDeps(ctx BottomUpMutatorContext) { addDep := func(target Target, depName string) { @@ -1219,6 +1233,13 @@ func (m *ModuleBase) GenerateTaggedDistFiles(ctx BaseModuleContext) TaggedDistFi tag := proptools.StringDefault(dist.Tag, DefaultDistTag) distFileForTagFromProvider, err := outputFilesForModuleFromProvider(ctx, m.module, tag) + + // If the module doesn't define output files for the DefaultDistTag, try the files under + // the "" tag. + if tag == DefaultDistTag && errors.Is(err, ErrUnsupportedOutputTag) { + distFileForTagFromProvider, err = outputFilesForModuleFromProvider(ctx, m.module, "") + } + if err != OutputFilesProviderNotSet { if err != nil && tag != DefaultDistTag { ctx.PropertyErrorf("dist.tag", "%s", err.Error()) @@ -1475,7 +1496,7 @@ func (m *ModuleBase) computeInstallDeps(ctx ModuleContext) ([]depset.DepSet[Inst // Installation is still handled by Make, so anything hidden from Make is not // installable. info := OtherModuleProviderOrDefault(ctx, dep, InstallFilesProvider) - commonInfo := OtherModuleProviderOrDefault(ctx, dep, CommonModuleInfoKey) + commonInfo := OtherModulePointerProviderOrDefault(ctx, dep, CommonModuleInfoProvider) if !commonInfo.HideFromMake && !commonInfo.SkipInstall { installDeps = append(installDeps, info.TransitiveInstallFiles) } @@ -1492,7 +1513,7 @@ func (m *ModuleBase) computeInstallDeps(ctx ModuleContext) ([]depset.DepSet[Inst // should also install the output files of the given dependency and dependency tag. func isInstallDepNeeded(ctx ModuleContext, dep ModuleProxy) bool { // Don't add a dependency from the platform to a library provided by an apex. - if OtherModuleProviderOrDefault(ctx, dep, CommonModuleInfoKey).UninstallableApexPlatformVariant { + if OtherModulePointerProviderOrDefault(ctx, dep, CommonModuleInfoProvider).UninstallableApexPlatformVariant { return false } // Only install modules if the dependency tag is an InstallDepNeeded tag. @@ -1646,38 +1667,10 @@ func (m *ModuleBase) generateVariantTarget(ctx *moduleContext) { } +// generateModuleTarget generates phony targets so that you can do `m <module-name>`. +// It will be run on every variant of the module, so it relies on the fact that phony targets +// are deduped to merge all the deps from different variants together. func (m *ModuleBase) generateModuleTarget(ctx *moduleContext) { - var allInstalledFiles InstallPaths - var allCheckbuildTargets Paths - var alloutputFiles Paths - ctx.VisitAllModuleVariantProxies(func(module ModuleProxy) { - var checkbuildTarget Path - var uncheckedModule bool - var skipAndroidMkProcessing bool - if ctx.EqualModules(m.module, module) { - allInstalledFiles = append(allInstalledFiles, ctx.installFiles...) - checkbuildTarget = ctx.checkbuildTarget - uncheckedModule = ctx.uncheckedModule - skipAndroidMkProcessing = shouldSkipAndroidMkProcessing(ctx, m) - } else { - info := OtherModuleProviderOrDefault(ctx, module, InstallFilesProvider) - allInstalledFiles = append(allInstalledFiles, info.InstallFiles...) - checkbuildTarget = info.CheckbuildTarget - uncheckedModule = info.UncheckedModule - skipAndroidMkProcessing = OtherModuleProviderOrDefault(ctx, module, CommonModuleInfoKey).SkipAndroidMkProcessing - } - if outputFiles, err := outputFilesForModule(ctx, module, ""); err == nil { - alloutputFiles = append(alloutputFiles, outputFiles...) - } - // A module's -checkbuild phony targets should - // 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() || !skipAndroidMkProcessing) && !uncheckedModule && checkbuildTarget != nil { - allCheckbuildTargets = append(allCheckbuildTargets, checkbuildTarget) - } - }) - var namespacePrefix string nameSpace := ctx.Namespace().Path if nameSpace != "." { @@ -1685,25 +1678,30 @@ func (m *ModuleBase) generateModuleTarget(ctx *moduleContext) { } var deps Paths - var info FinalModuleBuildTargetsInfo + var info ModuleBuildTargetsInfo - if len(allInstalledFiles) > 0 { + if len(ctx.installFiles) > 0 { name := namespacePrefix + ctx.ModuleName() + "-install" - ctx.Phony(name, allInstalledFiles.Paths()...) + installFiles := ctx.installFiles.Paths() + ctx.Phony(name, installFiles...) info.InstallTarget = PathForPhony(ctx, name) - deps = append(deps, info.InstallTarget) + deps = append(deps, installFiles...) } - if len(allCheckbuildTargets) > 0 { + // A module's -checkbuild phony targets should + // not be created if the module is not exported to make. + // Those could depend on the build target and fail to compile + // for the current build target. + if (!ctx.Config().KatiEnabled() || !shouldSkipAndroidMkProcessing(ctx, m)) && !ctx.uncheckedModule && ctx.checkbuildTarget != nil { name := namespacePrefix + ctx.ModuleName() + "-checkbuild" - ctx.Phony(name, allCheckbuildTargets...) - deps = append(deps, PathForPhony(ctx, name)) + ctx.Phony(name, ctx.checkbuildTarget) + deps = append(deps, ctx.checkbuildTarget) } - if len(alloutputFiles) > 0 { + if outputFiles, err := outputFilesForModule(ctx, ctx.Module(), ""); err == nil && len(outputFiles) > 0 { name := namespacePrefix + ctx.ModuleName() + "-outputs" - ctx.Phony(name, alloutputFiles...) - deps = append(deps, PathForPhony(ctx, name)) + ctx.Phony(name, outputFiles...) + deps = append(deps, outputFiles...) } if len(deps) > 0 { @@ -1726,7 +1724,7 @@ func (m *ModuleBase) generateModuleTarget(ctx *moduleContext) { } info.BlueprintDir = ctx.ModuleDir() - SetProvider(ctx, FinalModuleBuildTargetsProvider, info) + SetProvider(ctx, ModuleBuildTargetsProvider, info) } } @@ -1868,15 +1866,15 @@ type SourceFilesInfo struct { var SourceFilesInfoProvider = blueprint.NewProvider[SourceFilesInfo]() -// FinalModuleBuildTargetsInfo is used by buildTargetSingleton to create checkbuild and -// per-directory build targets. Only set on the final variant of each module -type FinalModuleBuildTargetsInfo struct { +// ModuleBuildTargetsInfo is used by buildTargetSingleton to create checkbuild and +// per-directory build targets. +type ModuleBuildTargetsInfo struct { InstallTarget WritablePath CheckbuildTarget WritablePath BlueprintDir string } -var FinalModuleBuildTargetsProvider = blueprint.NewProvider[FinalModuleBuildTargetsInfo]() +var ModuleBuildTargetsProvider = blueprint.NewProvider[ModuleBuildTargetsInfo]() type CommonModuleInfo struct { Enabled bool @@ -1928,6 +1926,9 @@ type CommonModuleInfo struct { TargetRequiredModuleNames []string VintfFragmentModuleNames []string Dists []Dist + ExportedToMake bool + Team string + PartitionTag string } type ApiLevelOrPlatform struct { @@ -1935,7 +1936,7 @@ type ApiLevelOrPlatform struct { IsPlatform bool } -var CommonModuleInfoKey = blueprint.NewProvider[CommonModuleInfo]() +var CommonModuleInfoProvider = blueprint.NewProvider[*CommonModuleInfo]() type PrebuiltModuleInfo struct { SourceExists bool @@ -2141,14 +2142,19 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) } if sourceFileProducer, ok := m.module.(SourceFileProducer); ok { + srcs := sourceFileProducer.Srcs() + for _, src := range srcs { + if src == nil { + ctx.ModuleErrorf("SourceFileProducer cannot return nil srcs") + return + } + } SetProvider(ctx, SourceFilesInfoProvider, SourceFilesInfo{Srcs: sourceFileProducer.Srcs()}) } - if ctx.IsFinalModule(m.module) { - m.generateModuleTarget(ctx) - if ctx.Failed() { - return - } + m.generateModuleTarget(ctx) + if ctx.Failed() { + return } ctx.TransitiveInstallFiles = depset.New[InstallPath](depset.TOPOLOGICAL, ctx.installFiles, dependencyInstallFiles) @@ -2176,6 +2182,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) } else { hostRequired = m.baseProperties.Host_required } + hostRequired = append(hostRequired, moduleInfoJSON.ExtraHostRequired...) var data []string for _, d := range ctx.testData { @@ -2287,6 +2294,9 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) TargetRequiredModuleNames: m.module.TargetRequiredModuleNames(), VintfFragmentModuleNames: m.module.VintfFragmentModuleNames(ctx), Dists: m.Dists(), + ExportedToMake: m.ExportedToMake(), + Team: m.Team(), + PartitionTag: m.PartitionTag(ctx.DeviceConfig()), } if mm, ok := m.module.(interface { MinSdkVersion(ctx EarlyModuleContext) ApiLevel @@ -2334,7 +2344,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) if mm, ok := m.module.(interface{ BaseModuleName() string }); ok { commonData.BaseModuleName = mm.BaseModuleName() } - SetProvider(ctx, CommonModuleInfoKey, commonData) + SetProvider(ctx, CommonModuleInfoProvider, &commonData) if p, ok := m.module.(PrebuiltInterface); ok && p.Prebuilt() != nil { SetProvider(ctx, PrebuiltModuleInfoProvider, PrebuiltModuleInfo{ SourceExists: p.Prebuilt().SourceExists(), @@ -2357,6 +2367,18 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) GeneratedDeps: s.GeneratedDeps(), }) } + + if m.Enabled(ctx) { + if v, ok := m.module.(ModuleMakeVarsProvider); ok { + SetProvider(ctx, ModuleMakeVarsInfoProvider, v.MakeVars(ctx)) + } + + if am, ok := m.module.(AndroidMkDataProvider); ok { + SetProvider(ctx, AndroidMkDataInfoProvider, AndroidMkDataInfo{ + Class: am.AndroidMk().Class, + }) + } + } } func SetJarJarPrefixHandler(handler func(ModuleContext)) { @@ -2640,6 +2662,8 @@ func (e configurationEvalutor) EvaluateConfiguration(condition proptools.Configu return proptools.ConfigurableValueBool(ctx.Config().UseDebugArt()) case "selinux_ignore_neverallows": return proptools.ConfigurableValueBool(ctx.Config().SelinuxIgnoreNeverallows()) + case "always_use_prebuilt_sdks": + return proptools.ConfigurableValueBool(ctx.Config().AlwaysUsePrebuiltSdks()) default: // TODO(b/323382414): Might add these on a case-by-case basis ctx.OtherModulePropertyErrorf(m, property, fmt.Sprintf("TODO(b/323382414): Product variable %q is not yet supported in selects", variable)) @@ -2873,6 +2897,8 @@ func OutputFilesForModule(ctx PathContext, module Module, tag string) Paths { // OutputFileForModule returns the output file paths with the given tag. On error, including if the // module produced zero or multiple paths, it reports errors to the ctx and returns nil. +// TODO(b/397766191): Change the signature to take ModuleProxy +// Please only access the module's internal data through providers. func OutputFileForModule(ctx PathContext, module Module, tag string) Path { paths, err := outputFilesForModule(ctx, module, tag) if err != nil { @@ -2910,9 +2936,10 @@ type OutputFilesProviderModuleContext interface { OtherModuleProviderContext Module() Module GetOutputFiles() OutputFilesInfo - EqualModules(m1, m2 Module) bool } +// TODO(b/397766191): Change the signature to take ModuleProxy +// Please only access the module's internal data through providers. func outputFilesForModule(ctx PathContext, module Module, tag string) (Paths, error) { outputFilesFromProvider, err := outputFilesForModuleFromProvider(ctx, module, tag) if outputFilesFromProvider != nil || err != OutputFilesProviderNotSet { @@ -2920,7 +2947,7 @@ func outputFilesForModule(ctx PathContext, module Module, tag string) (Paths, er } if octx, ok := ctx.(OutputFilesProviderModuleContext); ok { - if octx.EqualModules(octx.Module(), module) { + if EqualModules(octx.Module(), module) { // It is the current module, we can access the srcs through interface if sourceFileProducer, ok := module.(SourceFileProducer); ok { return sourceFileProducer.Srcs(), nil @@ -2945,14 +2972,12 @@ func outputFilesForModule(ctx PathContext, module Module, tag string) (Paths, er // If a module doesn't have the OutputFilesProvider, nil is returned. func outputFilesForModuleFromProvider(ctx PathContext, module Module, tag string) (Paths, error) { var outputFiles OutputFilesInfo - fromProperty := false if mctx, isMctx := ctx.(OutputFilesProviderModuleContext); isMctx { - if !mctx.EqualModules(mctx.Module(), module) { + if !EqualModules(mctx.Module(), module) { outputFiles, _ = OtherModuleProvider(mctx, module, OutputFilesProvider) } else { outputFiles = mctx.GetOutputFiles() - fromProperty = true } } else if cta, isCta := ctx.(*singletonContextAdaptor); isCta { outputFiles, _ = OtherModuleProvider(cta, module, OutputFilesProvider) @@ -2969,10 +2994,8 @@ func outputFilesForModuleFromProvider(ctx PathContext, module Module, tag string } else if taggedOutputFiles, hasTag := outputFiles.TaggedOutputFiles[tag]; hasTag { return taggedOutputFiles, nil } else { - if fromProperty { - return nil, fmt.Errorf("unsupported tag %q for module getting its own output files", tag) - } else { - return nil, fmt.Errorf("unsupported module reference tag %q", tag) + return nil, UnsupportedOutputTagError{ + tag: tag, } } } @@ -2991,8 +3014,24 @@ type OutputFilesInfo struct { var OutputFilesProvider = blueprint.NewProvider[OutputFilesInfo]() +type UnsupportedOutputTagError struct { + tag string +} + +func (u UnsupportedOutputTagError) Error() string { + return fmt.Sprintf("unsupported output tag %q", u.tag) +} + +func (u UnsupportedOutputTagError) Is(e error) bool { + _, ok := e.(UnsupportedOutputTagError) + return ok +} + +var _ error = UnsupportedOutputTagError{} + // This is used to mark the case where OutputFilesProvider is not set on some modules. var OutputFilesProviderNotSet = fmt.Errorf("No output files from provider") +var ErrUnsupportedOutputTag = UnsupportedOutputTagError{} // Modules can implement HostToolProvider and return a valid OptionalPath from HostToolPath() to // specify that they can be used as a tool by a genrule module. @@ -3058,8 +3097,8 @@ func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) { modulesInDir := make(map[string]Paths) - ctx.VisitAllModules(func(module Module) { - info := OtherModuleProviderOrDefault(ctx, module, FinalModuleBuildTargetsProvider) + ctx.VisitAllModuleProxies(func(module ModuleProxy) { + info := OtherModuleProviderOrDefault(ctx, module, ModuleBuildTargetsProvider) if info.CheckbuildTarget != nil { checkbuildDeps = append(checkbuildDeps, info.CheckbuildTarget) @@ -3141,14 +3180,6 @@ type IDEInfo interface { BaseModuleName() string } -// Extract the base module name from the Import name. -// Often the Import name has a prefix "prebuilt_". -// Remove the prefix explicitly if needed -// until we find a better solution to get the Import name. -type IDECustomizedModuleName interface { - IDECustomizedModuleName() string -} - // Collect information for opening IDE project files in java/jdeps.go. type IdeInfo struct { BaseModuleName string `json:"-"` diff --git a/android/module_context.go b/android/module_context.go index fb62e6749..0a23a745f 100644 --- a/android/module_context.go +++ b/android/module_context.go @@ -456,6 +456,11 @@ func (m *moduleContext) Build(pctx PackageContext, params BuildParams) { } func (m *moduleContext) Phony(name string, deps ...Path) { + for _, dep := range deps { + if dep == nil { + panic("Phony dep cannot be nil") + } + } m.phonies[name] = append(m.phonies[name], deps...) } @@ -748,6 +753,9 @@ func (m *moduleContext) installFile(installPath InstallPath, name string, srcPat m.packageFile(fullInstallPath, srcPath, executable, m.requiresFullInstall()) if checkbuild { + if srcPath == nil { + panic("srcPath cannot be nil") + } m.checkbuildFiles = append(m.checkbuildFiles, srcPath) } @@ -879,6 +887,11 @@ func (m *moduleContext) InstallTestData(installPath InstallPath, data []DataPath // CheckbuildFile specifies the output files that should be built by checkbuild. func (m *moduleContext) CheckbuildFile(srcPaths ...Path) { + for _, srcPath := range srcPaths { + if srcPath == nil { + panic("CheckbuildFile() files cannot be nil") + } + } m.checkbuildFiles = append(m.checkbuildFiles, srcPaths...) } diff --git a/android/module_info_json.go b/android/module_info_json.go index bb309ffee..50c961abe 100644 --- a/android/module_info_json.go +++ b/android/module_info_json.go @@ -40,10 +40,12 @@ type ExtraModuleInfoJSON struct { StaticDependencies []string `json:"static_dependencies,omitempty"` // $(sort $(ALL_MODULES.$(m).LOCAL_STATIC_LIBRARIES)) DataDependencies []string `json:"data_dependencies,omitempty"` // $(sort $(ALL_MODULES.$(m).TEST_DATA_BINS)) - CompatibilitySuites []string `json:"compatibility_suites,omitempty"` // $(sort $(ALL_MODULES.$(m).COMPATIBILITY_SUITES)) - AutoTestConfig []string `json:"auto_test_config,omitempty"` // $(ALL_MODULES.$(m).auto_test_config) - TestConfig []string `json:"test_config,omitempty"` // $(strip $(ALL_MODULES.$(m).TEST_CONFIG) $(ALL_MODULES.$(m).EXTRA_TEST_CONFIGS) - ExtraRequired []string `json:"-"` + CompatibilitySuites []string `json:"compatibility_suites,omitempty"` // $(sort $(ALL_MODULES.$(m).COMPATIBILITY_SUITES)) + AutoTestConfig []string `json:"auto_test_config,omitempty"` // $(ALL_MODULES.$(m).auto_test_config) + TestConfig []string `json:"test_config,omitempty"` // $(strip $(ALL_MODULES.$(m).TEST_CONFIG) $(ALL_MODULES.$(m).EXTRA_TEST_CONFIGS) + TestModuleConfigBase string `json:"test_module_config_base,omitempty"` + ExtraRequired []string `json:"-"` + ExtraHostRequired []string `json:"-"` SupportedVariantsOverride []string `json:"-"` Disabled bool `json:"-"` diff --git a/android/neverallow.go b/android/neverallow.go index 70af2acc3..5c90501d7 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -60,7 +60,8 @@ func init() { AddNeverAllowRules(createCcStubsRule()) AddNeverAllowRules(createProhibitHeaderOnlyRule()) AddNeverAllowRules(createLimitNdkExportRule()...) - AddNeverAllowRules(createLimitDirgroupRule()...) + AddNeverAllowRules(createLimitDirgroupRules()...) + AddNeverAllowRules(createLimitGenruleRules()...) AddNeverAllowRules(createFilesystemIsAutoGeneratedRule()) AddNeverAllowRules(createKotlinPluginRule()...) AddNeverAllowRules(createPrebuiltEtcBpDefineRule()) @@ -251,6 +252,7 @@ func createInstallInRootAllowingRules() []Rule { NotModuleType("prebuilt_system"). NotModuleType("prebuilt_first_stage_ramdisk"). NotModuleType("prebuilt_res"). + NotModuleType("prebuilt_any"). Because("install_in_root is only for init_first_stage or librecovery_ui_ext."), } } @@ -287,45 +289,49 @@ func createLimitNdkExportRule() []Rule { } } -func createLimitDirgroupRule() []Rule { - reason := "dirgroup module and dir_srcs / keep_gendir property of genrule is allowed only to Trusty build rule." +func createLimitDirgroupRules() []Rule { + reason := "The dirgroup module can only be used with Trusty visibility" + scriptsDirsList := []string{"//trusty/vendor/google/aosp/scripts", "//trusty/vendor/google/proprietary/scripts"} return []Rule{ NeverAllow(). ModuleType("dirgroup"). - WithMatcher("visibility", NotInList([]string{"//trusty/vendor/google/aosp/scripts", "//trusty/vendor/google/proprietary/scripts"})).Because(reason), + WithMatcher("visibility", NotInList(scriptsDirsList)).Because(reason), NeverAllow(). ModuleType("dirgroup"). - WithoutMatcher("visibility", InAllowedList([]string{"//trusty/vendor/google/aosp/scripts", "//trusty/vendor/google/proprietary/scripts"})).Because(reason), + WithoutMatcher("visibility", InAllowedList(scriptsDirsList)).Because(reason), + } +} + +func createLimitGenruleRules() []Rule { + dirSrcsReason := "The `dir_srcs` property in a `genrule` module can only be used by Trusty" + keepGendirReason := "The `keep_gendir` property in a `genrule` module can only be used by Trusty" + allowedModuleNameList := []string{ + // Trusty TEE target names + "trusty_tee_package_goog", + "trusty_tee_package", + // Trusty vm target names + "trusty_desktop_vm_arm64.bin", + "trusty_desktop_vm_x86_64.elf", + "trusty_desktop_test_vm_arm64.bin", + "trusty_desktop_test_vm_x86_64.elf", + "trusty_test_vm_arm64.bin", + "trusty_test_vm_x86_64.elf", + "trusty_test_vm_os_arm64.bin", + "trusty_test_vm_os_x86_64.elf", + "trusty_security_vm_arm64.bin", + "trusty_security_vm_x86_64.elf", + "trusty_widevine_vm_arm64.bin", + "trusty_widevine_vm_x86_64.elf", + } + return []Rule{ NeverAllow(). ModuleType("genrule"). - // TODO: remove the 4 below targets once new targets are submitted - Without("name", "trusty-arm64.lk.elf.gen"). - Without("name", "trusty-arm64-virt-test-debug.lk.elf.gen"). - Without("name", "trusty-x86_64.lk.elf.gen"). - Without("name", "trusty-x86_64-test.lk.elf.gen"). - // trusty vm target names moving forward - Without("name", "trusty-test_vm-arm64.elf.gen"). - Without("name", "trusty-test_vm-x86.elf.gen"). - Without("name", "trusty-security_vm-arm64.elf.gen"). - Without("name", "trusty-security_vm-x86.elf.gen"). - Without("name", "trusty-widevine_vm-arm64.elf.gen"). - Without("name", "trusty-widevine_vm-x86.elf.gen"). - WithMatcher("dir_srcs", isSetMatcherInstance).Because(reason), + WithoutMatcher("name", InAllowedList(allowedModuleNameList)). + WithMatcher("dir_srcs", isSetMatcherInstance).Because(dirSrcsReason), NeverAllow(). ModuleType("genrule"). - // TODO: remove the 4 below targets once new targets are submitted - Without("name", "trusty-arm64.lk.elf.gen"). - Without("name", "trusty-arm64-virt-test-debug.lk.elf.gen"). - Without("name", "trusty-x86_64.lk.elf.gen"). - Without("name", "trusty-x86_64-test.lk.elf.gen"). - // trusty vm target names moving forward - Without("name", "trusty-test_vm-arm64.elf.gen"). - Without("name", "trusty-test_vm-x86.elf.gen"). - Without("name", "trusty-security_vm-arm64.elf.gen"). - Without("name", "trusty-security_vm-x86.elf.gen"). - Without("name", "trusty-widevine_vm-arm64.elf.gen"). - Without("name", "trusty-widevine_vm-x86.elf.gen"). - With("keep_gendir", "true").Because(reason), + WithoutMatcher("name", InAllowedList(allowedModuleNameList)). + With("keep_gendir", "true").Because(keepGendirReason), } } @@ -363,6 +369,7 @@ func createKotlinPluginRule() []Rule { func createPrebuiltEtcBpDefineRule() Rule { return NeverAllow(). ModuleType( + "prebuilt_any", "prebuilt_usr_srec", "prebuilt_priv_app", "prebuilt_rfs", @@ -378,6 +385,9 @@ func createPrebuiltEtcBpDefineRule() Rule { "prebuilt_sbin", "prebuilt_system", "prebuilt_first_stage_ramdisk", + "prebuilt_radio", + "prebuilt_gpu", + "prebuilt_vendor_overlay", ). DefinedInBpFile(). Because("module type not allowed to be defined in bp file") @@ -409,7 +419,8 @@ func neverallowMutator(ctx BottomUpMutatorContext) { continue } - if !n.appliesToModuleType(ctx.ModuleType()) { + modType := proptools.StringDefault(m.base().baseProperties.Soong_config_base_module_type, ctx.ModuleType()) + if !n.appliesToModuleType(modType) { continue } diff --git a/android/neverallow_test.go b/android/neverallow_test.go index c74d5ff58..3ccc883af 100644 --- a/android/neverallow_test.go +++ b/android/neverallow_test.go @@ -388,6 +388,30 @@ var neverallowTests = []struct { `module type not allowed to be defined in bp file`, }, }, + // Test the a neverallowed module type can't be smuggled through a soong config module type + { + name: `smuggling module types through soong config modules`, + fs: map[string][]byte{ + "a/b/Android.bp": []byte(` + soong_config_bool_variable { + name: "my_var", + } + soong_config_module_type { + name: "smuggled_prebuilt_usr_srec", + module_type: "prebuilt_usr_srec", + config_namespace: "ANDROID", + variables: ["my_var"], + properties: ["enabled"], + } + smuggled_prebuilt_usr_srec { + name: "foo", + } + `), + }, + expectedErrors: []string{ + `module type not allowed to be defined in bp file`, + }, + }, } var prepareForNeverAllowTest = GroupFixturePreparers( @@ -399,6 +423,7 @@ var prepareForNeverAllowTest = GroupFixturePreparers( ctx.RegisterModuleType("filesystem", newMockFilesystemModule) ctx.RegisterModuleType("prebuilt_usr_srec", newMockPrebuiltUsrSrecModule) }), + PrepareForTestWithSoongConfigModuleBuildComponents, ) func TestNeverallow(t *testing.T) { diff --git a/android/notices.go b/android/notices.go index 3c41d924e..dc2290cce 100644 --- a/android/notices.go +++ b/android/notices.go @@ -18,9 +18,11 @@ import ( "fmt" "path/filepath" "strings" + + "github.com/google/blueprint" ) -func modulesOutputDirs(ctx BuilderContext, modules ...Module) []string { +func modulesOutputDirs(ctx BuilderContext, modules ...ModuleProxy) []string { dirs := make([]string, 0, len(modules)) for _, module := range modules { paths, err := outputFilesForModule(ctx, module, "") @@ -41,12 +43,12 @@ type BuilderAndOtherModuleProviderContext interface { OtherModuleProviderContext } -func modulesLicenseMetadata(ctx OtherModuleProviderContext, modules ...Module) Paths { +func modulesLicenseMetadata(ctx OtherModuleProviderContext, modules ...ModuleProxy) Paths { result := make(Paths, 0, len(modules)) mctx, isMctx := ctx.(ModuleContext) for _, module := range modules { var mf Path - if isMctx && mctx.Module() == module { + if isMctx && EqualModules(mctx.Module(), module) { mf = mctx.LicenseMetadataFile() } else { mf = OtherModuleProviderOrDefault(ctx, module, InstallFilesProvider).LicenseMetadataFile @@ -61,12 +63,12 @@ func modulesLicenseMetadata(ctx OtherModuleProviderContext, modules ...Module) P // buildNoticeOutputFromLicenseMetadata writes out a notice file. func buildNoticeOutputFromLicenseMetadata( ctx BuilderAndOtherModuleProviderContext, tool, ruleName string, outputFile WritablePath, - libraryName string, stripPrefix []string, modules ...Module) { + libraryName string, stripPrefix []string, modules ...ModuleProxy) { depsFile := outputFile.ReplaceExtension(ctx, strings.TrimPrefix(outputFile.Ext()+".d", ".")) rule := NewRuleBuilder(pctx, ctx) if len(modules) == 0 { if mctx, ok := ctx.(ModuleContext); ok { - modules = []Module{mctx.Module()} + modules = []ModuleProxy{{blueprint.CreateModuleProxy(mctx.Module())}} } else { panic(fmt.Errorf("%s %q needs a module to generate the notice for", ruleName, libraryName)) } @@ -97,7 +99,7 @@ func buildNoticeOutputFromLicenseMetadata( // current context module if none given. func BuildNoticeTextOutputFromLicenseMetadata( ctx BuilderAndOtherModuleProviderContext, outputFile WritablePath, ruleName, libraryName string, - stripPrefix []string, modules ...Module) { + stripPrefix []string, modules ...ModuleProxy) { buildNoticeOutputFromLicenseMetadata(ctx, "textnotice", "text_notice_"+ruleName, outputFile, libraryName, stripPrefix, modules...) } @@ -107,7 +109,7 @@ func BuildNoticeTextOutputFromLicenseMetadata( // current context module if none given. func BuildNoticeHtmlOutputFromLicenseMetadata( ctx BuilderAndOtherModuleProviderContext, outputFile WritablePath, ruleName, libraryName string, - stripPrefix []string, modules ...Module) { + stripPrefix []string, modules ...ModuleProxy) { buildNoticeOutputFromLicenseMetadata(ctx, "htmlnotice", "html_notice_"+ruleName, outputFile, libraryName, stripPrefix, modules...) } @@ -117,7 +119,7 @@ func BuildNoticeHtmlOutputFromLicenseMetadata( // current context module if none given. func BuildNoticeXmlOutputFromLicenseMetadata( ctx BuilderAndOtherModuleProviderContext, outputFile WritablePath, ruleName, libraryName string, - stripPrefix []string, modules ...Module) { + stripPrefix []string, modules ...ModuleProxy) { buildNoticeOutputFromLicenseMetadata(ctx, "xmlnotice", "xml_notice_"+ruleName, outputFile, libraryName, stripPrefix, modules...) } diff --git a/android/override_module.go b/android/override_module.go index 50ddc9b35..96620ef7a 100644 --- a/android/override_module.go +++ b/android/override_module.go @@ -367,6 +367,7 @@ func checkPrebuiltReplacesOverride(ctx BottomUpMutatorContext, b OverridableModu } func overridableModuleDepsMutator(ctx BottomUpMutatorContext) { + ctx.Module().base().baseOverridablePropertiesDepsMutator(ctx) if b, ok := ctx.Module().(OverridableModule); ok && b.Enabled(ctx) { b.OverridablePropertiesDepsMutator(ctx) } diff --git a/android/package.go b/android/package.go index 385326e53..52bddf9d9 100644 --- a/android/package.go +++ b/android/package.go @@ -38,6 +38,12 @@ type packageProperties struct { Default_team *string `android:"path"` } +type PackageInfo struct { + Properties packageProperties +} + +var PackageInfoProvider = blueprint.NewProvider[PackageInfo]() + type packageModule struct { ModuleBase @@ -56,10 +62,14 @@ func (p *packageModule) DepsMutator(ctx BottomUpMutatorContext) { } func (p *packageModule) GenerateBuildActions(ctx blueprint.ModuleContext) { - ctx.SetProvider(CommonModuleInfoKey, CommonModuleInfo{ + ctx.SetProvider(CommonModuleInfoProvider, &CommonModuleInfo{ Enabled: true, PrimaryLicensesProperty: p.primaryLicensesProperty, }) + + ctx.SetProvider(PackageInfoProvider, PackageInfo{ + Properties: p.properties, + }) } func (p *packageModule) qualifiedModuleId(ctx BaseModuleContext) qualifiedModuleName { diff --git a/android/packaging.go b/android/packaging.go index 6146f02c9..bb1fe4e45 100644 --- a/android/packaging.go +++ b/android/packaging.go @@ -89,6 +89,8 @@ type packagingSpecGob struct { ArchType ArchType Overrides []string Owner string + RequiresFullInstall bool + FullInstallPath InstallPath Variation string } @@ -113,6 +115,8 @@ func (p *PackagingSpec) ToGob() *packagingSpecGob { ArchType: p.archType, Overrides: p.overrides.ToSlice(), Owner: p.owner, + RequiresFullInstall: p.requiresFullInstall, + FullInstallPath: p.fullInstallPath, Variation: p.variation, } } @@ -129,6 +133,8 @@ func (p *PackagingSpec) FromGob(data *packagingSpecGob) { p.archType = data.ArchType p.overrides = uniquelist.Make(data.Overrides) p.owner = data.Owner + p.requiresFullInstall = data.RequiresFullInstall + p.fullInstallPath = data.FullInstallPath p.variation = data.Variation } diff --git a/android/paths.go b/android/paths.go index 1c0321c02..977473fbd 100644 --- a/android/paths.go +++ b/android/paths.go @@ -209,6 +209,10 @@ type ModuleErrorfContext interface { var _ ModuleErrorfContext = blueprint.ModuleContext(nil) +type AddMissingDependenciesContext interface { + AddMissingDependencies([]string) +} + // reportPathError will register an error with the attached context. It // attempts ctx.ModuleErrorf for a better error message first, then falls // back to ctx.Errorf. @@ -220,7 +224,9 @@ func reportPathError(ctx PathContext, err error) { // attempts ctx.ModuleErrorf for a better error message first, then falls // back to ctx.Errorf. func ReportPathErrorf(ctx PathContext, format string, args ...interface{}) { - if mctx, ok := ctx.(ModuleErrorfContext); ok { + if mctx, ok := ctx.(AddMissingDependenciesContext); ok && ctx.Config().AllowMissingDependencies() { + mctx.AddMissingDependencies([]string{fmt.Sprintf(format, args...)}) + } else if mctx, ok := ctx.(ModuleErrorfContext); ok { mctx.ModuleErrorf(format, args...) } else if ectx, ok := ctx.(errorfContext); ok { ectx.Errorf(format, args...) @@ -229,6 +235,8 @@ func ReportPathErrorf(ctx PathContext, format string, args ...interface{}) { } } +// TODO(b/397766191): Change the signature to take ModuleProxy +// Please only access the module's internal data through providers. func pathContextName(ctx PathContext, module blueprint.Module) string { if x, ok := ctx.(interface{ ModuleName(blueprint.Module) string }); ok { return x.ModuleName(module) @@ -675,7 +683,7 @@ func getPathsFromModuleDep(ctx ModuleWithDepsPathContext, path, moduleName, tag if module == nil { return nil, missingDependencyError{[]string{moduleName}} } - if !OtherModuleProviderOrDefault(ctx, *module, CommonModuleInfoKey).Enabled { + if !OtherModulePointerProviderOrDefault(ctx, *module, CommonModuleInfoProvider).Enabled { return nil, missingDependencyError{[]string{moduleName}} } diff --git a/android/phony.go b/android/phony.go index 7bdd9d31d..99ff0aaa4 100644 --- a/android/phony.go +++ b/android/phony.go @@ -55,7 +55,7 @@ var _ SingletonMakeVarsProvider = (*phonySingleton)(nil) func (p *phonySingleton) GenerateBuildActions(ctx SingletonContext) { p.phonyMap = getSingletonPhonyMap(ctx.Config()) - ctx.VisitAllModules(func(m Module) { + ctx.VisitAllModuleProxies(func(m ModuleProxy) { if info, ok := OtherModuleProvider(ctx, m, ModulePhonyProvider); ok { for k, v := range info.Phonies { p.phonyMap[k] = append(p.phonyMap[k], v...) diff --git a/android/prebuilt.go b/android/prebuilt.go index 72735991d..1ff009bf5 100644 --- a/android/prebuilt.go +++ b/android/prebuilt.go @@ -358,7 +358,7 @@ func IsModulePreferred(module Module) bool { } func IsModulePreferredProxy(ctx OtherModuleProviderContext, module ModuleProxy) bool { - if OtherModuleProviderOrDefault(ctx, module, CommonModuleInfoKey).ReplacedByPrebuilt { + if OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider).ReplacedByPrebuilt { // A source module that has been replaced by a prebuilt counterpart. return false } @@ -397,7 +397,7 @@ func GetEmbeddedPrebuilt(module Module) *Prebuilt { // the right module. This function is only safe to call after all TransitionMutators // have run, e.g. in GenerateAndroidBuildActions. func PrebuiltGetPreferred(ctx BaseModuleContext, module Module) Module { - if !OtherModuleProviderOrDefault(ctx, module, CommonModuleInfoKey).ReplacedByPrebuilt { + if !OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider).ReplacedByPrebuilt { return module } if _, ok := OtherModuleProvider(ctx, module, PrebuiltModuleInfoProvider); ok { @@ -412,7 +412,7 @@ func PrebuiltGetPreferred(ctx BaseModuleContext, module Module) Module { if prebuiltMod != nil { return false } - if ctx.EqualModules(parent, ctx.Module()) { + if EqualModules(parent, ctx.Module()) { // First level: Only recurse if the module is found as a direct dependency. sourceModDepFound = child == module return sourceModDepFound @@ -607,11 +607,6 @@ func hideUnflaggedModules(ctx BottomUpMutatorContext, psi PrebuiltSelectionInfoM if !moduleInFamily.ExportedToMake() { continue } - // Skip for the top-level java_sdk_library_(_import). This has some special cases that need to be addressed first. - // This does not run into non-determinism because PrebuiltPostDepsMutator also has the special case - if sdkLibrary, ok := moduleInFamily.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil { - continue - } if p := GetEmbeddedPrebuilt(moduleInFamily); p != nil && p.properties.UsePrebuilt { if selectedPrebuilt == nil { selectedPrebuilt = moduleInFamily @@ -638,26 +633,10 @@ func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) { if p := GetEmbeddedPrebuilt(m); p != nil { bmn, _ := m.(baseModuleName) name := bmn.BaseModuleName() - psi := PrebuiltSelectionInfoMap{} - ctx.VisitDirectDepsWithTag(AcDepTag, func(am Module) { - psi, _ = OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider) - }) if p.properties.UsePrebuilt { if p.properties.SourceExists { ctx.ReplaceDependenciesIf(name, func(from blueprint.Module, tag blueprint.DependencyTag, to blueprint.Module) bool { - if sdkLibrary, ok := m.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil { - // Do not replace deps to the top-level prebuilt java_sdk_library hook. - // This hook has been special-cased in #isSelected to be _always_ active, even in next builds - // for dexpreopt and hiddenapi processing. - // If we do not special-case this here, rdeps referring to a java_sdk_library in next builds via libs - // will get prebuilt stubs - // TODO (b/308187268): Remove this after the apexes have been added to apex_contributions - if psi.IsSelected(name) { - return false - } - } - if t, ok := tag.(ReplaceSourceWithPrebuilt); ok { return t.ReplaceSourceWithPrebuilt() } @@ -679,23 +658,13 @@ func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) { // java_sdk_library_import is a macro that creates // 1. top-level "impl" library // 2. stub libraries (suffixed with .stubs...) -// -// the impl of java_sdk_library_import is a "hook" for hiddenapi and dexpreopt processing. It does not have an impl jar, but acts as a shim -// to provide the jar deapxed from the prebuilt apex -// -// isSelected uses `all_apex_contributions` to supersede source vs prebuilts selection of the stub libraries. It does not supersede the -// selection of the top-level "impl" library so that this hook can work -// -// TODO (b/308174306) - Fix this when we need to support multiple prebuilts in main func isSelected(psi PrebuiltSelectionInfoMap, m Module) bool { if sdkLibrary, ok := m.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil { sln := proptools.String(sdkLibrary.SdkLibraryName()) // This is the top-level library - // Do not supersede the existing prebuilts vs source selection mechanisms - // TODO (b/308187268): Remove this after the apexes have been added to apex_contributions if bmn, ok := m.(baseModuleName); ok && sln == bmn.BaseModuleName() { - return false + return psi.IsSelected(m.Name()) } // Stub library created by java_sdk_library_import diff --git a/android/prebuilt_build_tool.go b/android/prebuilt_build_tool.go index 17b323067..7773bf8af 100644 --- a/android/prebuilt_build_tool.go +++ b/android/prebuilt_build_tool.go @@ -84,13 +84,12 @@ func (t *prebuiltBuildTool) GenerateAndroidBuildActions(ctx ModuleContext) { t.toolPath = OptionalPathForPath(installedPath) } -func (t *prebuiltBuildTool) MakeVars(ctx MakeVarsModuleContext) { - if makeVar := String(t.properties.Export_to_make_var); makeVar != "" { - if t.Target().Os != ctx.Config().BuildOS { - return - } - ctx.StrictRaw(makeVar, t.toolPath.String()) +func (t *prebuiltBuildTool) MakeVars(ctx MakeVarsModuleContext) []ModuleMakeVarsValue { + if makeVar := String(t.properties.Export_to_make_var); makeVar != "" && + t.Target().Os == ctx.Config().BuildOS { + return []ModuleMakeVarsValue{{makeVar, t.toolPath.String()}} } + return nil } func (t *prebuiltBuildTool) HostToolPath() OptionalPath { diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go index 27a68fbe5..d31fc4fcd 100644 --- a/android/prebuilt_test.go +++ b/android/prebuilt_test.go @@ -551,6 +551,9 @@ func (s *sourceModule) GenerateAndroidBuildActions(ctx ModuleContext) { } func (s *sourceModule) Srcs() Paths { + if s.src == nil { + return nil + } return Paths{s.src} } diff --git a/android/provider.go b/android/provider.go index b48fd9148..aae93ef88 100644 --- a/android/provider.go +++ b/android/provider.go @@ -16,6 +16,12 @@ var _ OtherModuleProviderContext = BottomUpMutatorContext(nil) var _ OtherModuleProviderContext = SingletonContext(nil) var _ OtherModuleProviderContext = (*TestContext)(nil) +// ConfigAndOtherModuleProviderContext is OtherModuleProviderContext + ConfigContext +type ConfigAndOtherModuleProviderContext interface { + OtherModuleProviderContext + ConfigContext +} + // OtherModuleProvider reads the provider for the given module. If the provider has been set the value is // returned and the boolean is true. If it has not been set the zero value of the provider's type is returned // and the boolean is false. The value returned may be a deep copy of the value originally passed to SetProvider. @@ -35,6 +41,14 @@ func OtherModuleProviderOrDefault[K any](ctx OtherModuleProviderContext, module return value } +func OtherModulePointerProviderOrDefault[K *T, T any](ctx OtherModuleProviderContext, module blueprint.Module, provider blueprint.ProviderKey[K]) K { + if value, ok := OtherModuleProvider(ctx, module, provider); ok { + return value + } + var val T + return &val +} + // ModuleProviderContext is a helper interface that is a subset of ModuleContext or BottomUpMutatorContext // for use in ModuleProvider. type ModuleProviderContext interface { diff --git a/android/provider_keys.go b/android/provider_keys.go new file mode 100644 index 000000000..60b383f53 --- /dev/null +++ b/android/provider_keys.go @@ -0,0 +1,24 @@ +// Copyright 2025 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +import "github.com/google/blueprint" + +// Providers of package filesystem +type AndroidDeviceInfo struct { + Main_device bool +} + +var AndroidDeviceInfoProvider = blueprint.NewProvider[AndroidDeviceInfo]() diff --git a/android/rule_builder.go b/android/rule_builder.go index db56c3f29..01fe6d8ea 100644 --- a/android/rule_builder.go +++ b/android/rule_builder.go @@ -660,12 +660,17 @@ func (r *RuleBuilder) build(name string, desc string) { } for _, c := range r.commands { for _, tool := range c.packagedTools { - command.CopyBefore = append(command.CopyBefore, &sbox_proto.Copy{ - From: proto.String(tool.srcPath.String()), - To: proto.String(sboxPathForPackagedToolRel(tool)), - Executable: proto.Bool(tool.executable), - }) - tools = append(tools, tool.srcPath) + if tool.srcPath != nil { + command.CopyBefore = append(command.CopyBefore, &sbox_proto.Copy{ + From: proto.String(tool.srcPath.String()), + To: proto.String(sboxPathForPackagedToolRel(tool)), + Executable: proto.Bool(tool.executable), + }) + tools = append(tools, tool.srcPath) + } else if tool.SymlinkTarget() == "" { + // We ignore symlinks for now, could be added later if needed + panic("Expected tool packagingSpec to either be a file or symlink") + } } } } @@ -1187,7 +1192,11 @@ func (c *RuleBuilderCommand) Text(text string) *RuleBuilderCommand { // Textf adds the specified formatted text to the command line. The text should not contain input or output paths or // the rule will not have them listed in its dependencies or outputs. func (c *RuleBuilderCommand) Textf(format string, a ...interface{}) *RuleBuilderCommand { - return c.Text(fmt.Sprintf(format, a...)) + if c.buf.Len() > 0 { + c.buf.WriteByte(' ') + } + fmt.Fprintf(&c.buf, format, a...) + return c } // Flag adds the specified raw text to the command line. The text should not contain input or output paths or the diff --git a/android/singleton.go b/android/singleton.go index a03ea74aa..e5f26842a 100644 --- a/android/singleton.go +++ b/android/singleton.go @@ -36,7 +36,7 @@ type SingletonContext interface { // ModuleVariantsFromName returns the list of module variants named `name` in the same namespace as `referer` enforcing visibility rules. // Allows generating build actions for `referer` based on the metadata for `name` deferred until the singleton context. - ModuleVariantsFromName(referer Module, name string) []Module + ModuleVariantsFromName(referer ModuleProxy, name string) []ModuleProxy otherModuleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) @@ -290,6 +290,10 @@ func (s *singletonContextAdaptor) ModuleType(module blueprint.Module) string { return s.SingletonContext.ModuleType(getWrappedModule(module)) } +func (s *singletonContextAdaptor) BlueprintFile(module blueprint.Module) string { + return s.SingletonContext.BlueprintFile(getWrappedModule(module)) +} + func (s *singletonContextAdaptor) VisitAllModulesBlueprint(visit func(blueprint.Module)) { s.SingletonContext.VisitAllModules(visit) } @@ -327,7 +331,7 @@ func (s *singletonContextAdaptor) VisitAllModuleVariants(module Module, visit fu } func (s *singletonContextAdaptor) VisitAllModuleVariantProxies(module Module, visit func(proxy ModuleProxy)) { - s.SingletonContext.VisitAllModuleVariantProxies(module, visitProxyAdaptor(visit)) + s.SingletonContext.VisitAllModuleVariantProxies(getWrappedModule(module), visitProxyAdaptor(visit)) } func (s *singletonContextAdaptor) PrimaryModule(module Module) Module { @@ -339,32 +343,30 @@ func (s *singletonContextAdaptor) PrimaryModuleProxy(module ModuleProxy) ModuleP } func (s *singletonContextAdaptor) IsFinalModule(module Module) bool { - return s.SingletonContext.IsFinalModule(module) + return s.SingletonContext.IsFinalModule(getWrappedModule(module)) } -func (s *singletonContextAdaptor) ModuleVariantsFromName(referer Module, name string) []Module { +func (s *singletonContextAdaptor) ModuleVariantsFromName(referer ModuleProxy, name string) []ModuleProxy { // get module reference for visibility enforcement - qualified := createVisibilityModuleReference(s.ModuleName(referer), s.ModuleDir(referer), referer) - - modules := s.SingletonContext.ModuleVariantsFromName(referer, name) - result := make([]Module, 0, len(modules)) - for _, m := range modules { - if module, ok := m.(Module); ok { - // enforce visibility - depName := s.ModuleName(module) - depDir := s.ModuleDir(module) - depQualified := qualifiedModuleName{depDir, depName} - // Targets are always visible to other targets in their own package. - if depQualified.pkg != qualified.name.pkg { - rule := effectiveVisibilityRules(s.Config(), depQualified) - if !rule.matches(qualified) { - s.ModuleErrorf(referer, "module %q references %q which is not visible to this module\nYou may need to add %q to its visibility", - referer.Name(), depQualified, "//"+s.ModuleDir(referer)) - continue - } + qualified := createVisibilityModuleProxyReference(s, s.ModuleName(referer), s.ModuleDir(referer), referer) + + modules := s.SingletonContext.ModuleVariantsFromName(referer.module, name) + result := make([]ModuleProxy, 0, len(modules)) + for _, module := range modules { + // enforce visibility + depName := s.ModuleName(module) + depDir := s.ModuleDir(module) + depQualified := qualifiedModuleName{depDir, depName} + // Targets are always visible to other targets in their own package. + if depQualified.pkg != qualified.name.pkg { + rule := effectiveVisibilityRules(s.Config(), depQualified) + if !rule.matches(qualified) { + s.ModuleErrorf(referer, "module %q references %q which is not visible to this module\nYou may need to add %q to its visibility", + referer.Name(), depQualified, "//"+s.ModuleDir(referer)) + continue } - result = append(result, module) } + result = append(result, ModuleProxy{module}) } return result } diff --git a/android/soong_config_modules.go b/android/soong_config_modules.go index e0b1d7cbe..a61c9d33d 100644 --- a/android/soong_config_modules.go +++ b/android/soong_config_modules.go @@ -506,6 +506,10 @@ func configModuleFactory(factory blueprint.ModuleFactory, moduleType *soongconfi conditionalProps := proptools.CloneEmptyProperties(conditionalFactoryProps) props = append(props, conditionalProps.Interface()) + if m, ok := module.(Module); ok { + m.base().baseProperties.Soong_config_base_module_type = &moduleType.BaseModuleType + } + // Regular Soong operation wraps the existing module factory with a // conditional on Soong config variables by reading the product // config variables from Make. diff --git a/android/team.go b/android/team.go index c273dc647..ad37f28c9 100644 --- a/android/team.go +++ b/android/team.go @@ -32,6 +32,12 @@ type teamProperties struct { Trendy_team_id *string `json:"trendy_team_id"` } +type TeamInfo struct { + Properties teamProperties +} + +var TeamInfoProvider = blueprint.NewProvider[TeamInfo]() + type teamModule struct { ModuleBase DefaultableModuleBase @@ -48,7 +54,11 @@ var TestOnlyProviderKey = blueprint.NewProvider[TestModuleInformation]() // Real work is done for the module that depends on us. // If needed, the team can serialize the config to json/proto file as well. -func (t *teamModule) GenerateAndroidBuildActions(ctx ModuleContext) {} +func (t *teamModule) GenerateAndroidBuildActions(ctx ModuleContext) { + SetProvider(ctx, TeamInfoProvider, TeamInfo{ + Properties: t.properties, + }) +} func (t *teamModule) TrendyTeamId(ctx ModuleContext) string { return *t.properties.Trendy_team_id diff --git a/android/test_suites.go b/android/test_suites.go index 39317ec62..9eaf78549 100644 --- a/android/test_suites.go +++ b/android/test_suites.go @@ -29,10 +29,7 @@ func testSuiteFilesFactory() Singleton { return &testSuiteFiles{} } -type testSuiteFiles struct { - robolectric []Path - ravenwood []Path -} +type testSuiteFiles struct{} type TestSuiteModule interface { Module @@ -61,51 +58,22 @@ func (t *testSuiteFiles) GenerateBuildActions(ctx SingletonContext) { } }) - t.robolectric = robolectricTestSuite(ctx, files["robolectric-tests"]) - ctx.Phony("robolectric-tests", t.robolectric...) - - t.ravenwood = ravenwoodTestSuite(ctx, files["ravenwood-tests"]) - ctx.Phony("ravenwood-tests", t.ravenwood...) - ctx.DistForGoal("robolectric-tests", t.robolectric...) - ctx.DistForGoal("ravenwood-tests", t.ravenwood...) -} - -func robolectricTestSuite(ctx SingletonContext, files map[string]InstallPaths) []Path { - var installedPaths InstallPaths - for _, module := range SortedKeys(files) { - installedPaths = append(installedPaths, files[module]...) - } - - outputFile := pathForPackaging(ctx, "robolectric-tests.zip") - rule := NewRuleBuilder(pctx, ctx) - rule.Command().BuiltTool("soong_zip"). - FlagWithOutput("-o ", outputFile). - FlagWithArg("-P ", "host/testcases"). - FlagWithArg("-C ", pathForTestCases(ctx).String()). - FlagWithRspFileInputList("-r ", outputFile.ReplaceExtension(ctx, "rsp"), installedPaths.Paths()). - Flag("-sha256") // necessary to save cas_uploader's time - - testList := buildTestList(ctx, "robolectric-tests_list", installedPaths) - testListZipOutputFile := pathForPackaging(ctx, "robolectric-tests_list.zip") - - rule.Command().BuiltTool("soong_zip"). - FlagWithOutput("-o ", testListZipOutputFile). - FlagWithArg("-C ", pathForPackaging(ctx).String()). - FlagWithInput("-f ", testList). - Flag("-sha256") - - rule.Build("robolectric_tests_zip", "robolectric-tests.zip") + robolectricZip, robolectrictListZip := buildTestSuite(ctx, "robolectric-tests", files["robolectric-tests"]) + ctx.Phony("robolectric-tests", robolectricZip, robolectrictListZip) + ctx.DistForGoal("robolectric-tests", robolectricZip, robolectrictListZip) - return []Path{outputFile, testListZipOutputFile} + ravenwoodZip, ravenwoodListZip := buildTestSuite(ctx, "ravenwood-tests", files["ravenwood-tests"]) + ctx.Phony("ravenwood-tests", ravenwoodZip, ravenwoodListZip) + ctx.DistForGoal("ravenwood-tests", ravenwoodZip, ravenwoodListZip) } -func ravenwoodTestSuite(ctx SingletonContext, files map[string]InstallPaths) []Path { +func buildTestSuite(ctx SingletonContext, suiteName string, files map[string]InstallPaths) (Path, Path) { var installedPaths InstallPaths for _, module := range SortedKeys(files) { installedPaths = append(installedPaths, files[module]...) } - outputFile := pathForPackaging(ctx, "ravenwood-tests.zip") + outputFile := pathForPackaging(ctx, suiteName+".zip") rule := NewRuleBuilder(pctx, ctx) rule.Command().BuiltTool("soong_zip"). FlagWithOutput("-o ", outputFile). @@ -114,8 +82,8 @@ func ravenwoodTestSuite(ctx SingletonContext, files map[string]InstallPaths) []P FlagWithRspFileInputList("-r ", outputFile.ReplaceExtension(ctx, "rsp"), installedPaths.Paths()). Flag("-sha256") // necessary to save cas_uploader's time - testList := buildTestList(ctx, "ravenwood-tests_list", installedPaths) - testListZipOutputFile := pathForPackaging(ctx, "ravenwood-tests_list.zip") + testList := buildTestList(ctx, suiteName+"_list", installedPaths) + testListZipOutputFile := pathForPackaging(ctx, suiteName+"_list.zip") rule.Command().BuiltTool("soong_zip"). FlagWithOutput("-o ", testListZipOutputFile). @@ -123,9 +91,9 @@ func ravenwoodTestSuite(ctx SingletonContext, files map[string]InstallPaths) []P FlagWithInput("-f ", testList). Flag("-sha256") - rule.Build("ravenwood_tests_zip", "ravenwood-tests.zip") + rule.Build(strings.ReplaceAll(suiteName, "-", "_")+"_zip", suiteName+".zip") - return []Path{outputFile, testListZipOutputFile} + return outputFile, testListZipOutputFile } func buildTestList(ctx SingletonContext, listFile string, installedPaths InstallPaths) Path { diff --git a/android/test_suites_test.go b/android/test_suites_test.go index dda93297a..03aa42413 100644 --- a/android/test_suites_test.go +++ b/android/test_suites_test.go @@ -108,7 +108,8 @@ var prepareForFakeTestSuite = GroupFixturePreparers( func (f *fake_module) GenerateAndroidBuildActions(ctx ModuleContext) { for _, output := range f.props.Outputs { - ctx.InstallFile(pathForTestCases(ctx), output, nil) + f := PathForModuleOut(ctx, output) + ctx.InstallFile(pathForTestCases(ctx), output, f) } SetProvider(ctx, TestSuiteInfoProvider, TestSuiteInfo{ diff --git a/android/testing.go b/android/testing.go index 1962fdea5..d2949ec8e 100644 --- a/android/testing.go +++ b/android/testing.go @@ -1197,11 +1197,11 @@ func AndroidMkInfoForTest(t *testing.T, ctx *TestContext, mod Module) *AndroidMk info := OtherModuleProviderOrDefault(ctx, mod, AndroidMkInfoProvider) aconfigUpdateAndroidMkInfos(ctx, mod, info) - commonInfo, _ := OtherModuleProvider(ctx, mod, CommonModuleInfoKey) - info.PrimaryInfo.fillInEntries(ctx, mod, &commonInfo) + commonInfo := OtherModulePointerProviderOrDefault(ctx, mod, CommonModuleInfoProvider) + info.PrimaryInfo.fillInEntries(ctx, mod, commonInfo) if len(info.ExtraInfo) > 0 { for _, ei := range info.ExtraInfo { - ei.fillInEntries(ctx, mod, &commonInfo) + ei.fillInEntries(ctx, mod, commonInfo) } } diff --git a/android/variable.go b/android/variable.go index 81999f340..3d5a6ae12 100644 --- a/android/variable.go +++ b/android/variable.go @@ -65,12 +65,6 @@ type variableProperties struct { 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 proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"` - } `android:"arch_variant"` - Malloc_low_memory struct { Cflags []string `android:"arch_variant"` Shared_libs []string `android:"arch_variant"` @@ -216,6 +210,7 @@ type ProductVariables struct { Platform_display_version_name *string `json:",omitempty"` Platform_version_name *string `json:",omitempty"` Platform_sdk_version *int `json:",omitempty"` + Platform_sdk_minor_version *int `json:",omitempty"` Platform_sdk_codename *string `json:",omitempty"` Platform_sdk_version_or_codename *string `json:",omitempty"` Platform_sdk_final *bool `json:",omitempty"` @@ -553,6 +548,8 @@ type ProductVariables struct { OdmManifestFiles []string `json:",omitempty"` UseSoongNoticeXML *bool `json:",omitempty"` + + StripByDefault *bool `json:",omitempty"` } type PartitionQualifiedVariablesType struct { @@ -653,6 +650,7 @@ type PartitionVariables struct { ProductUseDynamicPartitions bool `json:",omitempty"` ProductRetrofitDynamicPartitions bool `json:",omitempty"` ProductBuildSuperPartition bool `json:",omitempty"` + BuildingSuperEmptyImage bool `json:",omitempty"` BoardSuperPartitionSize string `json:",omitempty"` BoardSuperPartitionMetadataDevice string `json:",omitempty"` BoardSuperPartitionBlockDevices []string `json:",omitempty"` @@ -667,6 +665,7 @@ type PartitionVariables struct { AbOtaPartitions []string `json:",omitempty"` AbOtaKeys []string `json:",omitempty"` AbOtaPostInstallConfig []string `json:",omitempty"` + BoardSuperImageInUpdatePackage bool `json:",omitempty"` // Avb (android verified boot) stuff BoardAvbEnable bool `json:",omitempty"` @@ -715,6 +714,8 @@ type PartitionVariables struct { ProductFsCompression string `json:",omitempty"` ReleaseToolsExtensionDir string `json:",omitempty"` + + BoardFastbootInfoFile string `json:",omitempty"` } func boolPtr(v bool) *bool { diff --git a/android/visibility.go b/android/visibility.go index 4837c7d4b..915368710 100644 --- a/android/visibility.go +++ b/android/visibility.go @@ -58,15 +58,29 @@ const ( var visibilityRuleRegexp = regexp.MustCompile(visibilityRulePattern) type visibilityModuleReference struct { - name qualifiedModuleName - module Module + name qualifiedModuleName + partitionType *string } func createVisibilityModuleReference(name, dir string, module Module) visibilityModuleReference { - return visibilityModuleReference{ - name: createQualifiedModuleName(name, dir), - module: module, + vis := visibilityModuleReference{ + name: createQualifiedModuleName(name, dir), } + if m, ok := module.(PartitionTypeInterface); ok { + pt := m.PartitionType() + vis.partitionType = &pt + } + return vis +} + +func createVisibilityModuleProxyReference(ctx OtherModuleProviderContext, name, dir string, module ModuleProxy) visibilityModuleReference { + vis := visibilityModuleReference{ + name: createQualifiedModuleName(name, dir), + } + if m, ok := OtherModuleProvider(ctx, module, PartitionTypeInfoProvider); ok { + vis.partitionType = &m.PartitionType + } + return vis } // A visibility rule is associated with a module and determines which other modules it is visible @@ -222,9 +236,17 @@ type PartitionTypeInterface interface { PartitionType() string } +type PartitionTypeInfo struct { + // Identifies which partition this is for //visibility:any_system_image (and others) visibility + // checks, and will be used in the future for API surface checks. + PartitionType string +} + +var PartitionTypeInfoProvider = blueprint.NewProvider[PartitionTypeInfo]() + func (r anyPartitionRule) matches(m visibilityModuleReference) bool { - if m2, ok := m.module.(PartitionTypeInterface); ok { - return m2.PartitionType() == r.partitionType + if m.partitionType != nil { + return *m.partitionType == r.partitionType } return false } @@ -529,7 +551,7 @@ func visibilityRuleEnforcer(ctx BottomUpMutatorContext) { rule := effectiveVisibilityRules(ctx.Config(), depQualified) if !rule.matches(qualified) { - ctx.ModuleErrorf("depends on %s which is not visible to this module\nYou may need to add %q to its visibility, %#v", depQualified, "//"+ctx.ModuleDir(), ctx.OtherModuleDependencyTag(dep)) + ctx.ModuleErrorf("depends on %s which is not visible to this module\nYou may need to add %q to its visibility", depQualified, "//"+ctx.ModuleDir()) } }) } @@ -647,42 +669,6 @@ func (v *visibilityRuleSet) Strings() []string { return v.rules } -// Get the effective visibility rules, i.e. the actual rules that affect the visibility of the -// property irrespective of where they are defined. -// -// Includes visibility rules specified by package default_visibility and/or on defaults. -// Short hand forms, e.g. //:__subpackages__ are replaced with their full form, e.g. -// //package/containing/rule:__subpackages__. -func EffectiveVisibilityRules(ctx BaseModuleContext, module Module) VisibilityRuleSet { - moduleName := ctx.OtherModuleName(module) - dir := ctx.OtherModuleDir(module) - qualified := qualifiedModuleName{dir, moduleName} - - rule := effectiveVisibilityRules(ctx.Config(), qualified) - - currentModule := createVisibilityModuleReference(moduleName, dir, module) - - // Modules are implicitly visible to other modules in the same package, - // without checking the visibility rules. Here we need to add that visibility - // explicitly. - if !rule.matches(currentModule) { - if len(rule) == 1 { - if _, ok := rule[0].(privateRule); ok { - // If the rule is //visibility:private we can't append another - // visibility to it. Semantically we need to convert it to a package - // visibility rule for the location where the result is used, but since - // modules are implicitly visible within the package we get the same - // result without any rule at all, so just make it an empty list to be - // appended below. - rule = nil - } - } - rule = append(rule, packageRule{dir}) - } - - return &visibilityRuleSet{rule.Strings()} -} - // Clear the default visibility properties so they can be replaced. func clearVisibilityProperties(module Module) { module.base().visibilityPropertyInfo = nil diff --git a/android/visibility_test.go b/android/visibility_test.go index 277be0f65..4acaa02e5 100644 --- a/android/visibility_test.go +++ b/android/visibility_test.go @@ -2112,7 +2112,10 @@ func (j *mockFilesystemModule) DepsMutator(ctx BottomUpMutatorContext) { ctx.AddVariationDependencies(nil, dependencyTag{name: "mockdeps"}, j.properties.Deps...) } -func (p *mockFilesystemModule) GenerateAndroidBuildActions(ModuleContext) { +func (p *mockFilesystemModule) GenerateAndroidBuildActions(ctx ModuleContext) { + SetProvider(ctx, PartitionTypeInfoProvider, PartitionTypeInfo{ + PartitionType: p.PartitionType(), + }) } func (p *mockFilesystemModule) PartitionType() string { diff --git a/apex/apex.go b/apex/apex.go index 6e4685b1f..c6566e13b 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -18,6 +18,7 @@ package apex import ( "fmt" + "path" "path/filepath" "regexp" "slices" @@ -549,6 +550,9 @@ type apexBundle struct { // Required modules, filled out during GenerateAndroidBuildActions and used in AndroidMk required []string + + // appinfo of the apk-in-apex of this module + appInfos java.AppInfos } // apexFileClass represents a type of file that can be included in APEX. @@ -1498,7 +1502,7 @@ func apexFileForJavaModule(ctx android.ModuleContext, module android.Module, jav func apexFileForJavaModuleWithFile(ctx android.ModuleContext, module android.Module, javaInfo *java.JavaInfo, dexImplementationJar android.Path) apexFile { dirInApex := "javalib" - commonInfo := android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey) + commonInfo := android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider) af := newApexFile(ctx, dexImplementationJar, commonInfo.BaseModuleName, dirInApex, javaSharedLib, module) af.jacocoReportClassesFile = javaInfo.JacocoReportClassesFile if lintInfo, ok := android.OtherModuleProvider(ctx, module, java.LintProvider); ok { @@ -1603,35 +1607,8 @@ func apexFileForFilesystem(ctx android.BaseModuleContext, buildFile android.Path // to the child modules. Returning false makes the visit to continue in the sibling or the parent // modules. This is used in check* functions below. func (a *apexBundle) WalkPayloadDeps(ctx android.BaseModuleContext, do android.PayloadDepsCallback) { - ctx.WalkDeps(func(child, parent android.Module) bool { - am, ok := child.(android.ApexModule) - if !ok || !am.CanHaveApexVariants() { - return false - } - - // Filter-out unwanted depedendencies - depTag := ctx.OtherModuleDependencyTag(child) - if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok { - return false - } - if dt, ok := depTag.(*dependencyTag); ok && !dt.payload { - return false - } - if depTag == android.RequiredDepTag { - return false - } - - externalDep := !android.IsDepInSameApex(ctx, parent, child) - - // Visit actually - return do(ctx, parent, am, externalDep) - }) -} - -func (a *apexBundle) WalkPayloadDepsProxy(ctx android.BaseModuleContext, - do func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool) { ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool { - if !android.OtherModuleProviderOrDefault(ctx, child, android.CommonModuleInfoKey).CanHaveApexVariants { + if !android.OtherModulePointerProviderOrDefault(ctx, child, android.CommonModuleInfoProvider).CanHaveApexVariants { return false } // Filter-out unwanted depedendencies @@ -1844,12 +1821,12 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok { return false } - commonInfo := android.OtherModuleProviderOrDefault(ctx, child, android.CommonModuleInfoKey) + commonInfo := android.OtherModulePointerProviderOrDefault(ctx, child, android.CommonModuleInfoProvider) if !commonInfo.Enabled { return false } depName := ctx.OtherModuleName(child) - if ctx.EqualModules(parent, ctx.Module()) { + if android.EqualModules(parent, ctx.Module()) { switch depTag { case sharedLibTag, jniLibTag: isJniLib := depTag == jniLibTag @@ -1862,7 +1839,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, if ch.IsStubs { ctx.PropertyErrorf(propertyName, "%q is a stub. Remove it from the list.", depName) } - fi := apexFileForNativeLibrary(ctx, child, &commonInfo, ch, vctx.handleSpecialLibs) + fi := apexFileForNativeLibrary(ctx, child, commonInfo, ch, vctx.handleSpecialLibs) fi.isJniLib = isJniLib vctx.filesInfo = append(vctx.filesInfo, fi) // Collect the list of stub-providing libs except: @@ -1879,11 +1856,11 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, case executableTag: if ccInfo, ok := android.OtherModuleProvider(ctx, child, cc.CcInfoProvider); ok { - vctx.filesInfo = append(vctx.filesInfo, apexFileForExecutable(ctx, child, &commonInfo, ccInfo)) + vctx.filesInfo = append(vctx.filesInfo, apexFileForExecutable(ctx, child, commonInfo, ccInfo)) return true // track transitive dependencies } if _, ok := android.OtherModuleProvider(ctx, child, rust.RustInfoProvider); ok { - vctx.filesInfo = append(vctx.filesInfo, apexFileForRustExecutable(ctx, child, &commonInfo)) + vctx.filesInfo = append(vctx.filesInfo, apexFileForRustExecutable(ctx, child, commonInfo)) return true // track transitive dependencies } else { ctx.PropertyErrorf("binaries", @@ -1891,7 +1868,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, } case shBinaryTag: if csh, ok := android.OtherModuleProvider(ctx, child, sh.ShBinaryInfoProvider); ok { - vctx.filesInfo = append(vctx.filesInfo, apexFileForShBinary(ctx, child, &commonInfo, &csh)) + vctx.filesInfo = append(vctx.filesInfo, apexFileForShBinary(ctx, child, commonInfo, &csh)) } else { ctx.PropertyErrorf("sh_binaries", "%q is not a sh_binary module", depName) } @@ -1930,6 +1907,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, } case androidAppTag: if appInfo, ok := android.OtherModuleProvider(ctx, child, java.AppInfoProvider); ok { + a.appInfos = append(a.appInfos, *appInfo) if appInfo.AppSet { appDir := "app" if appInfo.Privileged { @@ -1944,7 +1922,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, af.certificate = java.PresignedCertificate vctx.filesInfo = append(vctx.filesInfo, af) } else { - vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, child, &commonInfo, appInfo)...) + vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, child, commonInfo, appInfo)...) if !appInfo.Prebuilt && !appInfo.TestHelperApp { return true // track transitive dependencies } @@ -1991,7 +1969,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, } case testTag: if ccInfo, ok := android.OtherModuleProvider(ctx, child, cc.CcInfoProvider); ok { - af := apexFileForExecutable(ctx, child, &commonInfo, ccInfo) + af := apexFileForExecutable(ctx, child, commonInfo, ccInfo) af.class = nativeTest vctx.filesInfo = append(vctx.filesInfo, af) return true // track transitive dependencies @@ -2028,7 +2006,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, // tags used below are private (e.g. `cc.sharedDepTag`). if cc.IsSharedDepTag(depTag) || cc.IsRuntimeDepTag(depTag) { if ch, ok := android.OtherModuleProvider(ctx, child, cc.LinkableInfoProvider); ok { - af := apexFileForNativeLibrary(ctx, child, &commonInfo, ch, vctx.handleSpecialLibs) + af := apexFileForNativeLibrary(ctx, child, commonInfo, ch, vctx.handleSpecialLibs) af.transitiveDep = true if ch.IsStubs || ch.HasStubsVariants { @@ -2090,7 +2068,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, } linkableInfo := android.OtherModuleProviderOrDefault(ctx, child, cc.LinkableInfoProvider) - af := apexFileForNativeLibrary(ctx, child, &commonInfo, linkableInfo, vctx.handleSpecialLibs) + af := apexFileForNativeLibrary(ctx, child, commonInfo, linkableInfo, vctx.handleSpecialLibs) af.transitiveDep = true vctx.filesInfo = append(vctx.filesInfo, af) return true // track transitive dependencies @@ -2122,7 +2100,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, javaInfo := android.OtherModuleProviderOrDefault(ctx, child, java.JavaInfoProvider) af := apexFileForJavaModule(ctx, child, javaInfo) vctx.filesInfo = append(vctx.filesInfo, af) - if profileAf := apexFileForJavaModuleProfile(ctx, &commonInfo, javaInfo); profileAf != nil { + if profileAf := apexFileForJavaModuleProfile(ctx, commonInfo, javaInfo); profileAf != nil { vctx.filesInfo = append(vctx.filesInfo, *profileAf) } return true // track transitive dependencies @@ -2138,7 +2116,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, ctx.ModuleErrorf("unexpected tag %s for indirect dependency %q", android.PrettyPrintTag(depTag), depName) } else if android.IsVintfDepTag(depTag) { if vf, ok := android.OtherModuleProvider(ctx, child, android.VintfFragmentInfoProvider); ok { - apexFile := apexFileForVintfFragment(ctx, child, &commonInfo, &vf) + apexFile := apexFileForVintfFragment(ctx, child, commonInfo, &vf) vctx.filesInfo = append(vctx.filesInfo, apexFile) } } @@ -2258,6 +2236,16 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.enforcePartitionTagOnApexSystemServerJar(ctx) a.verifyNativeImplementationLibs(ctx) + a.enforceNoVintfInUpdatable(ctx) + + android.SetProvider(ctx, android.ApexBundleDepsDataProvider, android.ApexBundleDepsData{ + FlatListPath: a.FlatListPath(), + Updatable: a.Updatable(), + }) + + android.SetProvider(ctx, filesystem.ApexKeyPathInfoProvider, filesystem.ApexKeyPathInfo{a.apexKeysPath}) + + android.SetProvider(ctx, java.AppInfosProvider, a.appInfos) } // Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file @@ -2542,7 +2530,7 @@ func (a *apexBundle) checkStaticLinkingToStubLibraries(ctx android.ModuleContext librariesDirectlyInApex[ctx.OtherModuleName(dep)] = true }) - a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from android.Module, to android.ApexModule, externalDep bool) bool { + a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool { if info, ok := android.OtherModuleProvider(ctx, to, cc.LinkableInfoProvider); ok { // If `to` is not actually in the same APEX as `from` then it does not need // apex_available and neither do any of its dependencies. @@ -2656,7 +2644,7 @@ func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) { return } - a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from android.Module, to android.ApexModule, externalDep bool) bool { + a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool { // As soon as the dependency graph crosses the APEX boundary, don't go further. if externalDep { return false @@ -2886,7 +2874,7 @@ func (a *apexBundle) verifyNativeImplementationLibs(ctx android.ModuleContext) { tag := ctx.OtherModuleDependencyTag(child) - if ctx.EqualModules(parent, ctx.Module()) { + if android.EqualModules(parent, ctx.Module()) { if !checkApexTag(tag) { return false } @@ -2911,3 +2899,16 @@ func (a *apexBundle) verifyNativeImplementationLibs(ctx android.ModuleContext) { } } } + +// TODO(b/399527905) libvintf is not forward compatible. +func (a *apexBundle) enforceNoVintfInUpdatable(ctx android.ModuleContext) { + if !a.Updatable() { + return + } + for _, fi := range a.filesInfo { + if match, _ := path.Match("etc/vintf/*", fi.path()); match { + ctx.ModuleErrorf("VINTF fragment (%s) is not supported in updatable APEX.", fi.path()) + break + } + } +} diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go index a8bd984b2..797f47b09 100644 --- a/apex/apex_singleton.go +++ b/apex/apex_singleton.go @@ -90,11 +90,11 @@ var ( func (s *apexDepsInfoSingleton) GenerateBuildActions(ctx android.SingletonContext) { updatableFlatLists := android.Paths{} - ctx.VisitAllModules(func(module android.Module) { - if binaryInfo, ok := module.(android.ApexBundleDepsInfoIntf); ok { + ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { + if binaryInfo, ok := android.OtherModuleProvider(ctx, module, android.ApexBundleDepsDataProvider); ok { apexInfo, _ := android.OtherModuleProvider(ctx, module, android.ApexInfoProvider) - if path := binaryInfo.FlatListPath(); path != nil { - if binaryInfo.Updatable() || apexInfo.Updatable { + if path := binaryInfo.FlatListPath; path != nil { + if binaryInfo.Updatable || apexInfo.Updatable { if strings.HasPrefix(module.String(), "com.android.") { updatableFlatLists = append(updatableFlatLists, path) } @@ -160,11 +160,11 @@ type apexPrebuiltInfo struct { func (a *apexPrebuiltInfo) GenerateBuildActions(ctx android.SingletonContext) { prebuiltInfos := []android.PrebuiltInfo{} - ctx.VisitAllModules(func(m android.Module) { + ctx.VisitAllModuleProxies(func(m android.ModuleProxy) { prebuiltInfo, exists := android.OtherModuleProvider(ctx, m, android.PrebuiltInfoProvider) // Use prebuiltInfoProvider to filter out non apex soong modules. // Use HideFromMake to filter out the unselected variants of a specific apex. - if exists && !m.IsHideFromMake() { + if exists && !android.OtherModulePointerProviderOrDefault(ctx, m, android.CommonModuleInfoProvider).HideFromMake { prebuiltInfos = append(prebuiltInfos, prebuiltInfo) } }) diff --git a/apex/apex_test.go b/apex/apex_test.go index 9eaf814d0..36a697487 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -11667,7 +11667,7 @@ func TestAconfifDeclarationsValidation(t *testing.T) { // Arguments passed to aconfig to retrieve the state of the flags defined in the // textproto files - aconfigFlagArgs := m.Output("released-flagged-apis-exportable.txt").Args["flags_path"] + aconfigFlagArgs := m.Output("released-flags-exportable.pb").Args["flags_path"] // "bar-lib" is a static_lib of "foo" and is passed to metalava as classpath. Thus the // cache file provided by the associated aconfig_declarations module "bar" should be passed @@ -12216,3 +12216,30 @@ func TestVintfFragmentInApex(t *testing.T) { // Ensure that vintf fragment file is being installed ensureContains(t, cmd, "/etc/vintf/my_vintf_fragment.xml ") } + +func TestNoVintfFragmentInUpdatableApex(t *testing.T) { + t.Parallel() + testApexError(t, `VINTF fragment .* is not supported in updatable APEX`, apex_default_bp+` + apex { + name: "myapex", + manifest: ":myapex.manifest", + key: "myapex.key", + binaries: [ "mybin" ], + updatable: true, + min_sdk_version: "29", + } + + cc_binary { + name: "mybin", + srcs: ["mybin.cpp"], + vintf_fragment_modules: ["my_vintf_fragment.xml"], + apex_available: [ "myapex" ], + min_sdk_version: "29", + } + + vintf_fragment { + name: "my_vintf_fragment.xml", + src: "my_vintf_fragment.xml", + } + `) +} diff --git a/apex/builder.go b/apex/builder.go index 2fc4902fb..23c2ed8aa 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -1102,7 +1102,7 @@ func (a *apexBundle) buildApexDependencyInfo(ctx android.ModuleContext) { } depInfos := android.DepNameToDepInfoMap{} - a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from android.Module, to android.ApexModule, externalDep bool) bool { + a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool { if from.Name() == to.Name() { // This can happen for cc.reuseObjTag. We are not interested in tracking this. // As soon as the dependency graph crosses the APEX boundary, don't go further. @@ -1111,7 +1111,7 @@ func (a *apexBundle) buildApexDependencyInfo(ctx android.ModuleContext) { // Skip dependencies that are only available to APEXes; they are developed with updatability // in mind and don't need manual approval. - if android.OtherModuleProviderOrDefault(ctx, to, android.CommonModuleInfoKey).NotAvailableForPlatform { + if android.OtherModulePointerProviderOrDefault(ctx, to, android.CommonModuleInfoProvider).NotAvailableForPlatform { return !externalDep } @@ -1129,7 +1129,7 @@ func (a *apexBundle) buildApexDependencyInfo(ctx android.ModuleContext) { depInfos[to.Name()] = info } else { toMinSdkVersion := "(no version)" - if info, ok := android.OtherModuleProvider(ctx, to, android.CommonModuleInfoKey); ok && + if info, ok := android.OtherModuleProvider(ctx, to, android.CommonModuleInfoProvider); ok && !info.MinSdkVersion.IsPlatform && info.MinSdkVersion.ApiLevel != nil { toMinSdkVersion = info.MinSdkVersion.ApiLevel.String() } diff --git a/apex/prebuilt.go b/apex/prebuilt.go index 0a970276a..89b0091be 100644 --- a/apex/prebuilt.go +++ b/apex/prebuilt.go @@ -21,6 +21,7 @@ import ( "android/soong/android" "android/soong/dexpreopt" + "android/soong/filesystem" "android/soong/java" "android/soong/provenance" @@ -677,6 +678,8 @@ func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) { } ctx.SetOutputFiles(android.Paths{p.outputApex}, "") + + android.SetProvider(ctx, filesystem.ApexKeyPathInfoProvider, filesystem.ApexKeyPathInfo{p.apexKeysPath}) } func (p *Prebuilt) ProvenanceMetaDataFile() android.Path { @@ -873,4 +876,6 @@ func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) { } ctx.SetOutputFiles(android.Paths{a.outputApex}, "") + + android.SetProvider(ctx, filesystem.ApexKeyPathInfoProvider, filesystem.ApexKeyPathInfo{a.apexKeysPath}) } diff --git a/bloaty/bloaty.go b/bloaty/bloaty.go index 26f2aa879..d78a907fb 100644 --- a/bloaty/bloaty.go +++ b/bloaty/bloaty.go @@ -84,8 +84,8 @@ func fileSizesSingleton() android.Singleton { func (singleton *sizesSingleton) GenerateBuildActions(ctx android.SingletonContext) { var deps android.Paths - ctx.VisitAllModules(func(m android.Module) { - if !m.ExportedToMake() { + ctx.VisitAllModuleProxies(func(m android.ModuleProxy) { + if !android.OtherModulePointerProviderOrDefault(ctx, m, android.CommonModuleInfoProvider).ExportedToMake { return } filePaths, ok := android.OtherModuleProvider(ctx, m, fileSizeMeasurerKey) diff --git a/cc/afdo.go b/cc/afdo.go index 8d8341eb4..9be39185c 100644 --- a/cc/afdo.go +++ b/cc/afdo.go @@ -105,6 +105,11 @@ func (afdo *afdo) flags(ctx ModuleContext, flags Flags) Flags { // The flags are prepended to allow overriding. profileUseFlag := fmt.Sprintf(afdoFlagsFormat, fdoProfilePath) flags.Local.CFlags = append([]string{profileUseFlag}, flags.Local.CFlags...) + // Salvage stale profile by fuzzy matching and use the remapped location for sample profile query. + flags.Local.CFlags = append([]string{"-mllvm", "--salvage-stale-profile=true"}, flags.Local.CFlags...) + flags.Local.CFlags = append([]string{"-mllvm", "--salvage-stale-profile-max-callsites=2000"}, flags.Local.CFlags...) + // Salvage stale profile by fuzzy matching renamed functions. + flags.Local.CFlags = append([]string{"-mllvm", "--salvage-unused-profile=true"}, flags.Local.CFlags...) flags.Local.LdFlags = append([]string{profileUseFlag, "-Wl,-mllvm,-no-warn-sample-unused=true"}, flags.Local.LdFlags...) // Update CFlagsDeps and LdFlagsDeps so the module is rebuilt diff --git a/cc/api_level.go b/cc/api_level.go index deca72366..fa8dfaf2f 100644 --- a/cc/api_level.go +++ b/cc/api_level.go @@ -31,11 +31,7 @@ func MinApiForArch(ctx android.EarlyModuleContext, case android.Arm64, android.X86_64: return android.FirstLp64Version case android.Riscv64: - apiLevel, err := android.ApiLevelFromUser(ctx, "VanillaIceCream") - if err != nil { - panic(err) - } - return apiLevel + return android.FutureApiLevel default: panic(fmt.Errorf("Unknown arch %q", arch)) } diff --git a/cc/binary.go b/cc/binary.go index 627d5e560..608251afc 100644 --- a/cc/binary.go +++ b/cc/binary.go @@ -551,6 +551,10 @@ func (binary *binaryDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON binary.baseLinker.moduleInfoJSON(ctx, moduleInfoJSON) } +func (binary *binaryDecorator) testSuiteInfo(ctx ModuleContext) { + // not a test +} + var _ overridable = (*binaryDecorator)(nil) func init() { @@ -81,18 +81,23 @@ type LinkerInfo struct { HeaderLibs []string ImplementationModuleName *string - BinaryDecoratorInfo *BinaryDecoratorInfo - LibraryDecoratorInfo *LibraryDecoratorInfo - TestBinaryInfo *TestBinaryInfo - BenchmarkDecoratorInfo *BenchmarkDecoratorInfo - ObjectLinkerInfo *ObjectLinkerInfo - StubDecoratorInfo *StubDecoratorInfo + BinaryDecoratorInfo *BinaryDecoratorInfo + LibraryDecoratorInfo *LibraryDecoratorInfo + TestBinaryInfo *TestBinaryInfo + BenchmarkDecoratorInfo *BenchmarkDecoratorInfo + ObjectLinkerInfo *ObjectLinkerInfo + StubDecoratorInfo *StubDecoratorInfo + PrebuiltLibraryLinkerInfo *PrebuiltLibraryLinkerInfo } type BinaryDecoratorInfo struct{} type LibraryDecoratorInfo struct { ExportIncludeDirs []string InjectBsslHash bool + // Location of the static library in the sysroot. Empty if the library is + // not included in the NDK. + NdkSysrootPath android.Path + VndkFileName string } type SnapshotInfo struct { @@ -104,14 +109,38 @@ type TestBinaryInfo struct { } type BenchmarkDecoratorInfo struct{} -type StubDecoratorInfo struct{} +type StubDecoratorInfo struct { + AbiDumpPath android.OutputPath + HasAbiDump bool + AbiDiffPaths android.Paths + InstallPath android.Path +} -type ObjectLinkerInfo struct{} +type ObjectLinkerInfo struct { + // Location of the object in the sysroot. Empty if the object is not + // included in the NDK. + NdkSysrootPath android.Path +} + +type PrebuiltLibraryLinkerInfo struct { + VndkFileName string +} type LibraryInfo struct { BuildStubs bool } +type InstallerInfo struct { + StubDecoratorInfo *StubDecoratorInfo +} + +type LocalOrGlobalFlagsInfo struct { + CommonFlags []string // Flags that apply to C, C++, and assembly source files + CFlags []string // Flags that apply to C and C++ source files + ConlyFlags []string // Flags that apply to C source files + CppFlags []string // Flags that apply to C++ source files +} + // Common info about the cc module. type CcInfo struct { IsPrebuilt bool @@ -122,6 +151,7 @@ type CcInfo struct { LinkerInfo *LinkerInfo SnapshotInfo *SnapshotInfo LibraryInfo *LibraryInfo + InstallerInfo *InstallerInfo } var CcInfoProvider = blueprint.NewProvider[*CcInfo]() @@ -131,6 +161,7 @@ type LinkableInfo struct { StaticExecutable bool Static bool Shared bool + Header bool HasStubsVariants bool StubsVersion string IsStubs bool @@ -176,6 +207,13 @@ type LinkableInfo struct { // Symlinks returns a list of symlinks that should be created for this module. Symlinks []string APIListCoverageXMLPath android.ModuleOutPath + // FuzzSharedLibraries returns the shared library dependencies for this module. + // Expects that IsFuzzModule returns true. + FuzzSharedLibraries android.RuleBuilderInstalls + IsVndkPrebuiltLibrary bool + HasLLNDKStubs bool + IsLLNDKMovedToApex bool + ImplementationModuleName string } var LinkableInfoProvider = blueprint.NewProvider[*LinkableInfo]() @@ -759,6 +797,8 @@ type linker interface { defaultDistFiles() []android.Path moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) + + testSuiteInfo(ctx ModuleContext) } // specifiedDeps is a tuple struct representing dependencies of a linked binary owned by the linker. @@ -2336,8 +2376,11 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { case *binaryDecorator: ccInfo.LinkerInfo.BinaryDecoratorInfo = &BinaryDecoratorInfo{} case *libraryDecorator: + lk := c.linker.(*libraryDecorator) ccInfo.LinkerInfo.LibraryDecoratorInfo = &LibraryDecoratorInfo{ - InjectBsslHash: Bool(c.linker.(*libraryDecorator).Properties.Inject_bssl_hash), + InjectBsslHash: Bool(lk.Properties.Inject_bssl_hash), + NdkSysrootPath: lk.ndkSysrootPath, + VndkFileName: lk.getLibNameHelper(c.BaseModuleName(), true, false) + ".so", } case *testBinary: ccInfo.LinkerInfo.TestBinaryInfo = &TestBinaryInfo{ @@ -2346,9 +2389,16 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { case *benchmarkDecorator: ccInfo.LinkerInfo.BenchmarkDecoratorInfo = &BenchmarkDecoratorInfo{} case *objectLinker: - ccInfo.LinkerInfo.ObjectLinkerInfo = &ObjectLinkerInfo{} + ccInfo.LinkerInfo.ObjectLinkerInfo = &ObjectLinkerInfo{ + NdkSysrootPath: c.linker.(*objectLinker).ndkSysrootPath, + } case *stubDecorator: ccInfo.LinkerInfo.StubDecoratorInfo = &StubDecoratorInfo{} + case *prebuiltLibraryLinker: + ccInfo.LinkerInfo.PrebuiltLibraryLinkerInfo = &PrebuiltLibraryLinkerInfo{ + VndkFileName: c.linker.(*prebuiltLibraryLinker).getLibNameHelper( + c.BaseModuleName(), true, false) + ".so", + } } if s, ok := c.linker.(SnapshotInterface); ok { @@ -2360,12 +2410,25 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { name := v.ImplementationModuleName(ctx.OtherModuleName(c)) ccInfo.LinkerInfo.ImplementationModuleName = &name } + + c.linker.testSuiteInfo(ctx) } if c.library != nil { ccInfo.LibraryInfo = &LibraryInfo{ BuildStubs: c.library.BuildStubs(), } } + if c.installer != nil { + ccInfo.InstallerInfo = &InstallerInfo{} + if installer, ok := c.installer.(*stubDecorator); ok { + ccInfo.InstallerInfo.StubDecoratorInfo = &StubDecoratorInfo{ + HasAbiDump: installer.hasAbiDump, + AbiDumpPath: installer.abiDumpPath, + AbiDiffPaths: installer.abiDiffPaths, + InstallPath: installer.installPath, + } + } + } android.SetProvider(ctx, CcInfoProvider, &ccInfo) c.setOutputFiles(ctx) @@ -2407,12 +2470,23 @@ func CreateCommonLinkableInfo(ctx android.ModuleContext, mod VersionedLinkableIn Multilib: mod.Multilib(), ImplementationModuleNameForMake: mod.ImplementationModuleNameForMake(), Symlinks: mod.Symlinks(), + Header: mod.Header(), + IsVndkPrebuiltLibrary: mod.IsVndkPrebuiltLibrary(), } vi := mod.VersionedInterface() if vi != nil { info.IsStubsImplementationRequired = vi.IsStubsImplementationRequired() info.APIListCoverageXMLPath = vi.GetAPIListCoverageXMLPath() + info.HasLLNDKStubs = vi.HasLLNDKStubs() + info.IsLLNDKMovedToApex = vi.IsLLNDKMovedToApex() + info.ImplementationModuleName = vi.ImplementationModuleName(mod.BaseModuleName()) + } + + if !mod.PreventInstall() && fuzz.IsValid(ctx, mod.FuzzModuleStruct()) && mod.IsFuzzModule() { + info.FuzzSharedLibraries = mod.FuzzSharedLibraries() + fm := mod.FuzzPackagedModule() + fuzz.SetFuzzPackagedModuleInfo(ctx, &fm) } return info @@ -3348,7 +3422,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { return } - commonInfo := android.OtherModuleProviderOrDefault(ctx, dep, android.CommonModuleInfoKey) + commonInfo := android.OtherModulePointerProviderOrDefault(ctx, dep, android.CommonModuleInfoProvider) if commonInfo.Target.Os != ctx.Os() { ctx.ModuleErrorf("OS mismatch between %q (%s) and %q (%s)", ctx.ModuleName(), ctx.Os().Name, depName, dep.Target().Os.Name) return @@ -3602,7 +3676,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { c.sabi.Properties.ReexportedSystemIncludes, depExporterInfo.SystemIncludeDirs.Strings()...) } - makeLibName := MakeLibName(ccInfo, linkableInfo, &commonInfo, commonInfo.BaseModuleName) + libDepTag.makeSuffix + makeLibName := MakeLibName(ccInfo, linkableInfo, commonInfo, commonInfo.BaseModuleName) + libDepTag.makeSuffix switch { case libDepTag.header(): c.Properties.AndroidMkHeaderLibs = append( @@ -3629,7 +3703,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { switch depTag { case runtimeDepTag: c.Properties.AndroidMkRuntimeLibs = append( - c.Properties.AndroidMkRuntimeLibs, MakeLibName(ccInfo, linkableInfo, &commonInfo, + c.Properties.AndroidMkRuntimeLibs, MakeLibName(ccInfo, linkableInfo, commonInfo, commonInfo.BaseModuleName)+libDepTag.makeSuffix) case objDepTag: depPaths.Objs.objFiles = append(depPaths.Objs.objFiles, linkFile.Path()) @@ -3673,7 +3747,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { func ShouldUseStubForApex(ctx android.ModuleContext, parent android.Module, dep android.ModuleProxy) bool { inVendorOrProduct := false bootstrap := false - if ctx.EqualModules(ctx.Module(), parent) { + if android.EqualModules(ctx.Module(), parent) { if linkable, ok := parent.(LinkableInterface); !ok { ctx.ModuleErrorf("Not a Linkable module: %q", ctx.ModuleName()) } else { @@ -3705,7 +3779,7 @@ func ShouldUseStubForApex(ctx android.ModuleContext, parent android.Module, dep // platform APIs, use stubs only when it is from an APEX (and not from // platform) However, for host, ramdisk, vendor_ramdisk, recovery or // bootstrap modules, always link to non-stub variant - isNotInPlatform := android.OtherModuleProviderOrDefault(ctx, dep, android.CommonModuleInfoKey).NotInPlatform + isNotInPlatform := android.OtherModulePointerProviderOrDefault(ctx, dep, android.CommonModuleInfoProvider).NotInPlatform useStubs = isNotInPlatform && !bootstrap } else { diff --git a/cc/cc_test.go b/cc/cc_test.go index 2c06924ea..7240ea587 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -2689,7 +2689,7 @@ func TestIncludeDirectoryOrdering(t *testing.T) { cppOnly := []string{"-fPIC", "${config.CommonGlobalCppflags}", "${config.DeviceGlobalCppflags}", "${config.ArmCppflags}"} cflags := []string{"-Werror", "-std=candcpp"} - cstd := []string{"-std=gnu17", "-std=conly"} + cstd := []string{"-std=gnu23", "-std=conly"} cppstd := []string{"-std=gnu++20", "-std=cpp", "-fno-rtti"} lastNDKFlags := []string{ diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go index 0dcf2cfd4..45b15809f 100644 --- a/cc/config/arm64_device.go +++ b/cc/config/arm64_device.go @@ -44,7 +44,7 @@ var ( // On ARMv9 and later, Pointer Authentication Codes (PAC) are mandatory, // so -fstack-protector is unnecessary. "armv9-a": []string{ - "-march=armv8.2-a+dotprod", + "-march=armv9-a", "-mbranch-protection=standard", "-fno-stack-protector", }, diff --git a/cc/config/global.go b/cc/config/global.go index 7bea124ea..5011acd50 100644 --- a/cc/config/global.go +++ b/cc/config/global.go @@ -375,7 +375,7 @@ var ( "-w", } - CStdVersion = "gnu17" + CStdVersion = "gnu23" CppStdVersion = "gnu++20" ExperimentalCStdVersion = "gnu2x" ExperimentalCppStdVersion = "gnu++2b" diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go index ddc86c299..d2f88ef34 100644 --- a/cc/config/x86_linux_bionic_host.go +++ b/cc/config/x86_linux_bionic_host.go @@ -28,7 +28,7 @@ var ( "-fno-omit-frame-pointer", "-U_FORTIFY_SOURCE", - "-D_FORTIFY_SOURCE=2", + "-D_FORTIFY_SOURCE=3", "-fstack-protector-strong", // From x86_64_device diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go index c070050b7..c3f25aa21 100644 --- a/cc/config/x86_linux_host.go +++ b/cc/config/x86_linux_host.go @@ -29,7 +29,7 @@ var ( "-fno-omit-frame-pointer", "-U_FORTIFY_SOURCE", - "-D_FORTIFY_SOURCE=2", + "-D_FORTIFY_SOURCE=3", "-fstack-protector", "--gcc-toolchain=${LinuxGccRoot}", diff --git a/cc/fuzz.go b/cc/fuzz.go index bd3d8e431..79874fc80 100644 --- a/cc/fuzz.go +++ b/cc/fuzz.go @@ -470,43 +470,37 @@ func (s *ccRustFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) // multiple fuzzers that depend on the same shared library. sharedLibraryInstalled := make(map[string]bool) - ctx.VisitAllModules(func(module android.Module) { - ccModule, ok := module.(LinkableInterface) - if !ok || ccModule.PreventInstall() { + ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { + ccModule, ok := android.OtherModuleProvider(ctx, module, LinkableInfoProvider) + if !ok { return } // Discard non-fuzz targets. - if ok := fuzz.IsValid(ctx, ccModule.FuzzModuleStruct()); !ok { + fuzzInfo, ok := android.OtherModuleProvider(ctx, module, fuzz.FuzzPackagedModuleInfoProvider) + if !ok { return } sharedLibsInstallDirPrefix := "lib" - if ccModule.InVendor() { + if ccModule.InVendor { sharedLibsInstallDirPrefix = "lib/vendor" } - if !ccModule.IsFuzzModule() { - return - } - + commonInfo := android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider) + isHost := commonInfo.Target.Os.Class == android.Host hostOrTargetString := "target" - if ccModule.Target().HostCross { + if commonInfo.Target.HostCross { hostOrTargetString = "host_cross" - } else if ccModule.Host() { + } else if isHost { hostOrTargetString = "host" } if s.onlyIncludePresubmits == true { hostOrTargetString = "presubmit-" + hostOrTargetString } - fpm := fuzz.FuzzPackagedModule{} - if ok { - fpm = ccModule.FuzzPackagedModule() - } - intermediatePath := "fuzz" - archString := ccModule.Target().Arch.ArchType.String() + archString := commonInfo.Target.Arch.ArchType.String() archDir := android.PathForIntermediates(ctx, intermediatePath, hostOrTargetString, archString) archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()} @@ -514,23 +508,24 @@ func (s *ccRustFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) builder := android.NewRuleBuilder(pctx, ctx) // Package the corpus, data, dict and config into a zipfile. - files = s.PackageArtifacts(ctx, module, fpm, archDir, builder) + files = s.PackageArtifacts(ctx, module, &fuzzInfo, archDir, builder) // Package shared libraries - files = append(files, GetSharedLibsToZip(ccModule.FuzzSharedLibraries(), ccModule, &s.FuzzPackager, archString, sharedLibsInstallDirPrefix, &sharedLibraryInstalled)...) + files = append(files, GetSharedLibsToZip(ccModule.FuzzSharedLibraries, isHost, ccModule.InVendor, &s.FuzzPackager, + archString, sharedLibsInstallDirPrefix, &sharedLibraryInstalled)...) // The executable. - files = append(files, fuzz.FileToZip{SourceFilePath: android.OutputFileForModule(ctx, ccModule, "unstripped")}) + files = append(files, fuzz.FileToZip{SourceFilePath: android.OutputFileForModule(ctx, module, "unstripped")}) if s.onlyIncludePresubmits == true { - if fpm.FuzzProperties.Fuzz_config == nil { + if fuzzInfo.FuzzConfig == nil { return } - if !BoolDefault(fpm.FuzzProperties.Fuzz_config.Use_for_presubmit, false) { + if !fuzzInfo.FuzzConfig.UseForPresubmit { return } } - archDirs[archOs], ok = s.BuildZipFile(ctx, module, fpm, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs) + archDirs[archOs], ok = s.BuildZipFile(ctx, module, &fuzzInfo, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs) if !ok { return } @@ -559,7 +554,8 @@ func (s *ccRustFuzzPackager) MakeVars(ctx android.MakeVarsContext) { // GetSharedLibsToZip finds and marks all the transiently-dependent shared libraries for // packaging. -func GetSharedLibsToZip(sharedLibraries android.RuleBuilderInstalls, module LinkableInterface, s *fuzz.FuzzPackager, archString string, destinationPathPrefix string, sharedLibraryInstalled *map[string]bool) []fuzz.FileToZip { +func GetSharedLibsToZip(sharedLibraries android.RuleBuilderInstalls, isHost bool, inVendor bool, s *fuzz.FuzzPackager, + archString string, destinationPathPrefix string, sharedLibraryInstalled *map[string]bool) []fuzz.FileToZip { var files []fuzz.FileToZip fuzzDir := "fuzz" @@ -577,7 +573,7 @@ func GetSharedLibsToZip(sharedLibraries android.RuleBuilderInstalls, module Link // install it to the output directory. Setup the install destination here, // which will be used by $(copy-many-files) in the Make backend. installDestination := SharedLibraryInstallLocation( - install, module.Host(), module.InVendor(), fuzzDir, archString) + install, isHost, inVendor, fuzzDir, archString) if (*sharedLibraryInstalled)[installDestination] { continue } @@ -594,8 +590,8 @@ func GetSharedLibsToZip(sharedLibraries android.RuleBuilderInstalls, module Link // dir. Symbolized DSO's are always installed to the device when fuzzing, but // we want symbolization tools (like `stack`) to be able to find the symbols // in $ANDROID_PRODUCT_OUT/symbols automagically. - if !module.Host() { - symbolsInstallDestination := SharedLibrarySymbolsInstallLocation(install, module.InVendor(), fuzzDir, archString) + if !isHost { + symbolsInstallDestination := SharedLibrarySymbolsInstallLocation(install, inVendor, fuzzDir, archString) symbolsInstallDestination = strings.ReplaceAll(symbolsInstallDestination, "$", "$$") s.SharedLibInstallStrings = append(s.SharedLibInstallStrings, library.String()+":"+symbolsInstallDestination) diff --git a/cc/genrule_test.go b/cc/genrule_test.go index 438eb9880..4e700a2cd 100644 --- a/cc/genrule_test.go +++ b/cc/genrule_test.go @@ -17,6 +17,7 @@ package cc import ( "reflect" "slices" + "strings" "testing" "android/soong/android" @@ -254,3 +255,42 @@ func TestMultilibGenruleOut(t *testing.T) { gen_64bit, ) } + +// Test that a genrule can depend on a tool with symlinks. The symlinks are ignored, but +// at least it doesn't cause errors. +func TestGenruleToolWithSymlinks(t *testing.T) { + bp := ` + genrule { + name: "gen", + tools: ["tool_with_symlinks"], + cmd: "$(location tool_with_symlinks) $(in) $(out)", + out: ["out"], + } + + cc_binary_host { + name: "tool_with_symlinks", + symlinks: ["symlink1", "symlink2"], + } + ` + ctx := PrepareForIntegrationTestWithCc. + ExtendWithErrorHandler(android.FixtureExpectsNoErrors). + RunTestWithBp(t, bp) + gen := ctx.ModuleForTests(t, "gen", "").Output("out") + toolFound := false + symlinkFound := false + for _, dep := range gen.RuleParams.CommandDeps { + if strings.HasSuffix(dep, "/tool_with_symlinks") { + toolFound = true + } + if strings.HasSuffix(dep, "/symlink1") || strings.HasSuffix(dep, "/symlink2") { + symlinkFound = true + } + } + if !toolFound { + t.Errorf("Tool not found") + } + // We may want to change genrules to include symlinks later + if symlinkFound { + t.Errorf("Symlinks found") + } +} diff --git a/cc/library.go b/cc/library.go index ee7610d08..5299771ca 100644 --- a/cc/library.go +++ b/cc/library.go @@ -220,6 +220,7 @@ func init() { func RegisterLibraryBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("cc_library_static", LibraryStaticFactory) + ctx.RegisterModuleType("cc_rustlibs_for_make", LibraryMakeRustlibsFactory) ctx.RegisterModuleType("cc_library_shared", LibrarySharedFactory) ctx.RegisterModuleType("cc_library", LibraryFactory) ctx.RegisterModuleType("cc_library_host_static", LibraryHostStaticFactory) @@ -249,6 +250,19 @@ func LibraryStaticFactory() android.Module { return module.Init() } +// cc_rustlibs_for_make creates a static library which bundles together rust_ffi_static +// deps for Make. This should not be depended on in Soong, and is probably not the +// module you need unless you are sure of what you're doing. These should only +// be declared as dependencies in Make. To ensure inclusion, rust_ffi_static modules +// should be declared in the whole_static_libs property. +func LibraryMakeRustlibsFactory() android.Module { + module, library := NewLibrary(android.HostAndDeviceSupported) + library.BuildOnlyStatic() + library.wideStaticlibForMake = true + module.sdkMemberTypes = []android.SdkMemberType{staticLibrarySdkMemberType} + return module.Init() +} + // cc_library_shared creates a shared library for a device and/or host. func LibrarySharedFactory() android.Module { module, library := NewLibrary(android.HostAndDeviceSupported) @@ -437,6 +451,10 @@ type libraryDecorator struct { // Path to the file containing the APIs exported by this library stubsSymbolFilePath android.Path + + // Forces production of the generated Rust staticlib for cc_library_static. + // Intended to be used to provide these generated staticlibs for Make. + wideStaticlibForMake bool } // linkerProps returns the list of properties structs relevant for this library. (For example, if @@ -588,10 +606,22 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa panic(err) } + llndkFlag := "--llndk" + if ctx.baseModuleName() == "libbinder_ndk" && ctx.inProduct() { + // This is a special case only for the libbinder_ndk. As the product partition is in the + // framework side along with system and system_ext partitions in Treble, libbinder_ndk + // provides different binder interfaces between product and vendor modules. + // In libbinder_ndk, 'llndk' annotation is for the vendor APIs; while 'systemapi' + // annotation is for the product APIs. + // Use '--systemapi' flag for building the llndk stub of product variant for the + // libbinder_ndk. + llndkFlag = "--systemapi" + } + // This is the vendor variant of an LLNDK library, build the LLNDK stubs. nativeAbiResult := ParseNativeAbiDefinition(ctx, String(library.Properties.Llndk.Symbol_file), - nativeClampedApiLevel(ctx, version), "--llndk") + nativeClampedApiLevel(ctx, version), llndkFlag) objs := CompileStubLibrary(ctx, flags, nativeAbiResult.StubSrc, sharedFlags) if !Bool(library.Properties.Llndk.Unversioned) { library.versionScriptPath = android.OptionalPathForPath( @@ -1048,6 +1078,10 @@ func (library *libraryDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSO library.baseLinker.moduleInfoJSON(ctx, moduleInfoJSON) } +func (library *libraryDecorator) testSuiteInfo(ctx ModuleContext) { + // not a test +} + func (library *libraryDecorator) linkStatic(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path { @@ -1055,6 +1089,16 @@ func (library *libraryDecorator) linkStatic(ctx ModuleContext, library.objects = library.objects.Append(objs) library.wholeStaticLibsFromPrebuilts = android.CopyOfPaths(deps.WholeStaticLibsFromPrebuilts) + if library.wideStaticlibForMake { + if generatedLib := GenerateRustStaticlib(ctx, deps.RustRlibDeps); generatedLib != nil { + // WholeStaticLibsFromPrebuilts are .a files that get included whole into the resulting staticlib + // so reuse that here for our Rust staticlibs because we don't have individual object files for + // these. + deps.WholeStaticLibsFromPrebuilts = append(deps.WholeStaticLibsFromPrebuilts, generatedLib) + } + + } + fileName := ctx.ModuleName() + staticLibraryExtension outputFile := android.PathForModuleOut(ctx, fileName) builderFlags := flagsToBuilderFlags(flags) diff --git a/cc/llndk_library.go b/cc/llndk_library.go index 8ca3ca184..b119fdac1 100644 --- a/cc/llndk_library.go +++ b/cc/llndk_library.go @@ -82,11 +82,10 @@ type movedToApexLlndkLibraries struct { func (s *movedToApexLlndkLibraries) GenerateBuildActions(ctx android.SingletonContext) { // Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to generate the linker config. movedToApexLlndkLibrariesMap := make(map[string]bool) - ctx.VisitAllModules(func(module android.Module) { - if library := moduleVersionedInterface(module); library != nil && library.HasLLNDKStubs() { - if library.IsLLNDKMovedToApex() { - name := library.ImplementationModuleName(module.(*Module).BaseModuleName()) - movedToApexLlndkLibrariesMap[name] = true + ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { + if library, ok := android.OtherModuleProvider(ctx, module, LinkableInfoProvider); ok { + if library.HasLLNDKStubs && library.IsLLNDKMovedToApex { + movedToApexLlndkLibrariesMap[library.ImplementationModuleName] = true } } }) @@ -151,14 +150,16 @@ func (txt *llndkLibrariesTxtModule) GenerateAndroidBuildActions(ctx android.Modu etc.SetCommonPrebuiltEtcInfo(ctx, txt) } -func getVndkFileName(m *Module) (string, error) { - if library, ok := m.linker.(*libraryDecorator); ok { - return library.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil - } - if prebuilt, ok := m.linker.(*prebuiltLibraryLinker); ok { - return prebuilt.libraryDecorator.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil +func getVndkFileName(info *LinkerInfo) (string, error) { + if info != nil { + if info.LibraryDecoratorInfo != nil { + return info.LibraryDecoratorInfo.VndkFileName, nil + } + if info.PrebuiltLibraryLinkerInfo != nil { + return info.PrebuiltLibraryLinkerInfo.VndkFileName, nil + } } - return "", fmt.Errorf("VNDK library should have libraryDecorator or prebuiltLibraryLinker as linker: %T", m.linker) + return "", fmt.Errorf("VNDK library should have libraryDecorator or prebuiltLibraryLinker as linker: %T", info) } func (txt *llndkLibrariesTxtModule) GenerateSingletonBuildActions(ctx android.SingletonContext) { @@ -167,9 +168,17 @@ func (txt *llndkLibrariesTxtModule) GenerateSingletonBuildActions(ctx android.Si return } - ctx.VisitAllModules(func(m android.Module) { - if c, ok := m.(*Module); ok && c.VendorProperties.IsLLNDK && !c.Header() && !c.IsVndkPrebuiltLibrary() { - filename, err := getVndkFileName(c) + ctx.VisitAllModuleProxies(func(m android.ModuleProxy) { + ccInfo, ok := android.OtherModuleProvider(ctx, m, CcInfoProvider) + if !ok { + return + } + linkableInfo, ok := android.OtherModuleProvider(ctx, m, LinkableInfoProvider) + if !ok { + return + } + if linkableInfo.IsLlndk && !linkableInfo.Header && !linkableInfo.IsVndkPrebuiltLibrary { + filename, err := getVndkFileName(ccInfo.LinkerInfo) if err != nil { ctx.ModuleErrorf(m, "%s", err) } diff --git a/cc/ndk_abi.go b/cc/ndk_abi.go index 2706261a8..b96a779cb 100644 --- a/cc/ndk_abi.go +++ b/cc/ndk_abi.go @@ -39,15 +39,15 @@ type ndkAbiDumpSingleton struct{} func (n *ndkAbiDumpSingleton) GenerateBuildActions(ctx android.SingletonContext) { var depPaths android.Paths - ctx.VisitAllModules(func(module android.Module) { - if !module.Enabled(ctx) { + ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { + if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled { return } - if m, ok := module.(*Module); ok { - if installer, ok := m.installer.(*stubDecorator); ok { - if installer.hasAbiDump { - depPaths = append(depPaths, installer.abiDumpPath) + if ccInfo, ok := android.OtherModuleProvider(ctx, module, CcInfoProvider); ok { + if ccInfo.InstallerInfo != nil && ccInfo.InstallerInfo.StubDecoratorInfo != nil { + if ccInfo.InstallerInfo.StubDecoratorInfo.HasAbiDump { + depPaths = append(depPaths, ccInfo.InstallerInfo.StubDecoratorInfo.AbiDumpPath) } } } @@ -77,14 +77,14 @@ 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(ctx) { + ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { + if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled { return } - if m, ok := module.(*Module); ok { - if installer, ok := m.installer.(*stubDecorator); ok { - depPaths = append(depPaths, installer.abiDiffPaths...) + if ccInfo, ok := android.OtherModuleProvider(ctx, module, CcInfoProvider); ok { + if ccInfo.InstallerInfo != nil && ccInfo.InstallerInfo.StubDecoratorInfo != nil { + depPaths = append(depPaths, ccInfo.InstallerInfo.StubDecoratorInfo.AbiDiffPaths...) } } }) diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go index 74819540b..6e26d4c87 100644 --- a/cc/ndk_headers.go +++ b/cc/ndk_headers.go @@ -80,6 +80,20 @@ type headerModule struct { licensePath android.Path } +type NdkHeaderInfo struct { + SrcPaths android.Paths + InstallPaths android.Paths + LicensePath android.Path + // Set to true if the headers installed by this module should skip + // verification. This step ensures that each header is self-contained (can + // be #included alone) and is valid C. This should not be disabled except in + // rare cases. Outside bionic and external, if you're using this option + // you've probably made a mistake. + SkipVerification bool +} + +var NdkHeaderInfoProvider = blueprint.NewProvider[NdkHeaderInfo]() + func getHeaderInstallDir(ctx android.ModuleContext, header android.Path, from string, to string) android.OutputPath { // Output path is the sysroot base + "usr/include" + to directory + directory component @@ -135,6 +149,13 @@ func (m *headerModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { if len(m.installPaths) == 0 { ctx.ModuleErrorf("srcs %q matched zero files", m.properties.Srcs) } + + android.SetProvider(ctx, NdkHeaderInfoProvider, NdkHeaderInfo{ + SrcPaths: m.srcPaths, + InstallPaths: m.installPaths, + LicensePath: m.licensePath, + SkipVerification: Bool(m.properties.Skip_verification), + }) } // ndk_headers installs the sets of ndk headers defined in the srcs property @@ -203,6 +224,8 @@ type preprocessedHeadersModule struct { licensePath android.Path } +var NdkPreprocessedHeaderInfoProvider = blueprint.NewProvider[NdkHeaderInfo]() + func (m *preprocessedHeadersModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { if String(m.properties.License) == "" { ctx.PropertyErrorf("license", "field is required") @@ -231,6 +254,13 @@ func (m *preprocessedHeadersModule) GenerateAndroidBuildActions(ctx android.Modu if len(m.installPaths) == 0 { ctx.ModuleErrorf("srcs %q matched zero files", m.properties.Srcs) } + + android.SetProvider(ctx, NdkPreprocessedHeaderInfoProvider, NdkHeaderInfo{ + SrcPaths: m.srcPaths, + InstallPaths: m.installPaths, + LicensePath: m.licensePath, + SkipVerification: Bool(m.properties.Skip_verification), + }) } // preprocessed_ndk_headers preprocesses all the ndk headers listed in the srcs diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go index a5f014b9f..16778627f 100644 --- a/cc/ndk_sysroot.go +++ b/cc/ndk_sysroot.go @@ -53,11 +53,12 @@ package cc // TODO(danalbert): Write `ndk_static_library` rule. import ( - "android/soong/android" "fmt" "path/filepath" "strings" + "android/soong/android" + "github.com/google/blueprint" ) @@ -209,57 +210,61 @@ func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) { var headerCCompatVerificationTimestampPaths android.Paths var installPaths android.Paths var licensePaths android.Paths - ctx.VisitAllModules(func(module android.Module) { - if m, ok := module.(android.Module); ok && !m.Enabled(ctx) { + ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { + + if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled { return } - if m, ok := module.(*headerModule); ok { - headerSrcPaths = append(headerSrcPaths, m.srcPaths...) - headerInstallPaths = append(headerInstallPaths, m.installPaths...) - if !Bool(m.properties.Skip_verification) { - for i, installPath := range m.installPaths { + if m, ok := android.OtherModuleProvider(ctx, module, NdkHeaderInfoProvider); ok { + headerSrcPaths = append(headerSrcPaths, m.SrcPaths...) + headerInstallPaths = append(headerInstallPaths, m.InstallPaths...) + if !m.SkipVerification { + for i, installPath := range m.InstallPaths { headersToVerify = append(headersToVerify, srcDestPair{ - src: m.srcPaths[i], + src: m.SrcPaths[i], dest: installPath, }) } } - installPaths = append(installPaths, m.installPaths...) - licensePaths = append(licensePaths, m.licensePath) + installPaths = append(installPaths, m.InstallPaths...) + licensePaths = append(licensePaths, m.LicensePath) } - if m, ok := module.(*preprocessedHeadersModule); ok { - headerSrcPaths = append(headerSrcPaths, m.srcPaths...) - headerInstallPaths = append(headerInstallPaths, m.installPaths...) - if !Bool(m.properties.Skip_verification) { - for i, installPath := range m.installPaths { + if m, ok := android.OtherModuleProvider(ctx, module, NdkPreprocessedHeaderInfoProvider); ok { + headerSrcPaths = append(headerSrcPaths, m.SrcPaths...) + headerInstallPaths = append(headerInstallPaths, m.InstallPaths...) + if !m.SkipVerification { + for i, installPath := range m.InstallPaths { headersToVerify = append(headersToVerify, srcDestPair{ - src: m.srcPaths[i], + src: m.SrcPaths[i], dest: installPath, }) } } - installPaths = append(installPaths, m.installPaths...) - licensePaths = append(licensePaths, m.licensePath) + installPaths = append(installPaths, m.InstallPaths...) + licensePaths = append(licensePaths, m.LicensePath) } - if m, ok := module.(*Module); ok { - if installer, ok := m.installer.(*stubDecorator); ok && m.library.BuildStubs() { - installPaths = append(installPaths, installer.installPath) + if ccInfo, ok := android.OtherModuleProvider(ctx, module, CcInfoProvider); ok { + if installer := ccInfo.InstallerInfo; installer != nil && installer.StubDecoratorInfo != nil && + ccInfo.LibraryInfo != nil && ccInfo.LibraryInfo.BuildStubs { + installPaths = append(installPaths, installer.StubDecoratorInfo.InstallPath) } - if library, ok := m.linker.(*libraryDecorator); ok { - if library.ndkSysrootPath != nil { - staticLibInstallPaths = append( - staticLibInstallPaths, library.ndkSysrootPath) + if ccInfo.LinkerInfo != nil { + if library := ccInfo.LinkerInfo.LibraryDecoratorInfo; library != nil { + if library.NdkSysrootPath != nil { + staticLibInstallPaths = append( + staticLibInstallPaths, library.NdkSysrootPath) + } } - } - if object, ok := m.linker.(*objectLinker); ok { - if object.ndkSysrootPath != nil { - staticLibInstallPaths = append( - staticLibInstallPaths, object.ndkSysrootPath) + if object := ccInfo.LinkerInfo.ObjectLinkerInfo; object != nil { + if object.NdkSysrootPath != nil { + staticLibInstallPaths = append( + staticLibInstallPaths, object.NdkSysrootPath) + } } } } diff --git a/cc/object.go b/cc/object.go index 95a8beb52..ea3ed6151 100644 --- a/cc/object.go +++ b/cc/object.go @@ -250,3 +250,7 @@ func (object *objectLinker) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *an object.baseLinker.moduleInfoJSON(ctx, moduleInfoJSON) moduleInfoJSON.Class = []string{"STATIC_LIBRARIES"} } + +func (object *objectLinker) testSuiteInfo(ctx ModuleContext) { + // not a test +} diff --git a/cc/sanitize.go b/cc/sanitize.go index b704ef4bf..f0b0308ae 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -1422,6 +1422,7 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { sanitizers = append(sanitizers, "bool", "integer-divide-by-zero", + "object-size", "return", "returns-nonnull-attribute", "shift-exponent", @@ -1438,10 +1439,6 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { //"shift-base", //"signed-integer-overflow", ) - - if mctx.Config().ReleaseBuildObjectSizeSanitizer() { - sanitizers = append(sanitizers, "object-size") - } } sanitizers = append(sanitizers, sanProps.Misc_undefined...) } diff --git a/cc/strip.go b/cc/strip.go index a950df898..42c9137b7 100644 --- a/cc/strip.go +++ b/cc/strip.go @@ -23,8 +23,9 @@ import ( // StripProperties defines the type of stripping applied to the module. type StripProperties struct { Strip struct { - // Device and host modules default to stripping enabled leaving mini debuginfo. - // This can be disabled by setting none to true. + // Device modules default to stripping enabled leaving mini debuginfo. + // Host modules default to stripping disabled, but can be enabled by setting any other + // strip boolean property. None *bool `android:"arch_variant"` // all forces stripping everything, including the mini debug info. @@ -50,7 +51,12 @@ type Stripper struct { // NeedsStrip determines if stripping is required for a module. func (stripper *Stripper) NeedsStrip(actx android.ModuleContext) bool { forceDisable := Bool(stripper.StripProperties.Strip.None) - return !forceDisable + // Strip is enabled by default for device variants. + defaultEnable := actx.Device() || actx.Config().StripByDefault() + forceEnable := Bool(stripper.StripProperties.Strip.All) || + Bool(stripper.StripProperties.Strip.Keep_symbols) || + Bool(stripper.StripProperties.Strip.Keep_symbols_and_debug_frame) + return !forceDisable && (forceEnable || defaultEnable) } func (stripper *Stripper) strip(actx android.ModuleContext, in android.Path, out android.ModuleOutPath, diff --git a/cc/test.go b/cc/test.go index d2c4b28e8..9c276b81a 100644 --- a/cc/test.go +++ b/cc/test.go @@ -274,6 +274,12 @@ func (test *testDecorator) moduleInfoJSON(ctx android.ModuleContext, moduleInfoJ } } +func (test *testDecorator) testSuiteInfo(ctx ModuleContext) { + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: test.InstallerProperties.Test_suites, + }) +} + func NewTestInstaller() *baseInstaller { return NewBaseInstaller("nativetest", "nativetest64", InstallInData) } @@ -342,6 +348,10 @@ func (test *testBinary) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *androi } +func (test *testBinary) testSuiteInfo(ctx ModuleContext) { + test.testDecorator.testSuiteInfo(ctx) +} + func (test *testBinary) installerProps() []interface{} { return append(test.baseInstaller.installerProps(), test.testDecorator.installerProps()...) } @@ -455,6 +465,9 @@ func (test *testBinary) install(ctx ModuleContext, file android.Path) { if standaloneTestDep.SkipInstall() { continue } + if standaloneTestDep.Partition() == "data" { + continue + } test.binaryDecorator.baseInstaller.installStandaloneTestDep(ctx, standaloneTestDep) } } @@ -575,6 +588,10 @@ func (test *testLibrary) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *andro test.testDecorator.moduleInfoJSON(ctx, moduleInfoJSON) } +func (test *testLibrary) testSuiteInfo(ctx ModuleContext) { + test.testDecorator.testSuiteInfo(ctx) +} + func (test *testLibrary) installerProps() []interface{} { return append(test.baseInstaller.installerProps(), test.testDecorator.installerProps()...) } @@ -692,6 +709,12 @@ func (benchmark *benchmarkDecorator) moduleInfoJSON(ctx ModuleContext, moduleInf } } +func (benchmark *benchmarkDecorator) testSuiteInfo(ctx ModuleContext) { + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: benchmark.Properties.Test_suites, + }) +} + func NewBenchmark(hod android.HostOrDeviceSupported) *Module { module, binary := newBinary(hod) module.multilib = android.MultilibBoth diff --git a/cc/tidy.go b/cc/tidy.go index 23736585a..bf273e986 100644 --- a/cc/tidy.go +++ b/cc/tidy.go @@ -211,7 +211,7 @@ func TidyPhonySingleton() android.Singleton { type tidyPhonySingleton struct{} // Given a final module, add its tidy/obj phony targets to tidy/objModulesInDirGroup. -func collectTidyObjModuleTargets(ctx android.SingletonContext, module android.Module, +func collectTidyObjModuleTargets(ctx android.SingletonContext, module android.ModuleProxy, tidyModulesInDirGroup, objModulesInDirGroup map[string]map[string]android.Paths) { allObjFileGroups := make(map[string]android.Paths) // variant group name => obj file Paths allTidyFileGroups := make(map[string]android.Paths) // variant group name => tidy file Paths @@ -220,7 +220,7 @@ func collectTidyObjModuleTargets(ctx android.SingletonContext, module android.Mo // (1) Collect all obj/tidy files into OS-specific groups. ctx.VisitAllModuleVariantProxies(module, func(variant android.ModuleProxy) { - osName := android.OtherModuleProviderOrDefault(ctx, variant, android.CommonModuleInfoKey).Target.Os.Name + osName := android.OtherModulePointerProviderOrDefault(ctx, variant, android.CommonModuleInfoProvider).Target.Os.Name info := android.OtherModuleProviderOrDefault(ctx, variant, CcObjectInfoProvider) addToOSGroup(osName, info.ObjFiles, allObjFileGroups, subsetObjFileGroups) addToOSGroup(osName, info.TidyFiles, allTidyFileGroups, subsetTidyFileGroups) @@ -253,7 +253,7 @@ func (m *tidyPhonySingleton) GenerateBuildActions(ctx android.SingletonContext) objModulesInDirGroup := make(map[string]map[string]android.Paths) // Collect tidy/obj targets from the 'final' modules. - ctx.VisitAllModules(func(module android.Module) { + ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { if ctx.IsFinalModule(module) { collectTidyObjModuleTargets(ctx, module, tidyModulesInDirGroup, objModulesInDirGroup) } @@ -268,7 +268,7 @@ func (m *tidyPhonySingleton) GenerateBuildActions(ctx android.SingletonContext) } // The name for an obj/tidy module variant group phony target is Name_group-obj/tidy, -func objTidyModuleGroupName(module android.Module, group string, suffix string) string { +func objTidyModuleGroupName(module android.ModuleProxy, group string, suffix string) string { if group == "" { return module.Name() + "-" + suffix } @@ -327,7 +327,7 @@ func addToOSGroup(osName string, files android.Paths, allGroups, subsetGroups ma } // Add an all-OS group, with groupName, to include all os-specific phony targets. -func addAllOSGroup(ctx android.SingletonContext, module android.Module, phonyTargetGroups map[string]android.Paths, groupName string, objTidyName string) { +func addAllOSGroup(ctx android.SingletonContext, module android.ModuleProxy, phonyTargetGroups map[string]android.Paths, groupName string, objTidyName string) { if len(phonyTargetGroups) > 0 { var targets android.Paths for group, _ := range phonyTargetGroups { @@ -338,7 +338,7 @@ func addAllOSGroup(ctx android.SingletonContext, module android.Module, phonyTar } // Create one phony targets for each group and add them to the targetGroups. -func genObjTidyPhonyTargets(ctx android.SingletonContext, module android.Module, objTidyName string, fileGroups map[string]android.Paths, targetGroups map[string]android.Path) { +func genObjTidyPhonyTargets(ctx android.SingletonContext, module android.ModuleProxy, objTidyName string, fileGroups map[string]android.Paths, targetGroups map[string]android.Path) { for group, files := range fileGroups { groupName := objTidyModuleGroupName(module, group, objTidyName) ctx.Phony(groupName, files...) diff --git a/ci_tests/ci_test_package_zip.go b/ci_tests/ci_test_package_zip.go index acfa8e073..95249aa10 100644 --- a/ci_tests/ci_test_package_zip.go +++ b/ci_tests/ci_test_package_zip.go @@ -20,6 +20,7 @@ import ( "strings" "android/soong/android" + "github.com/google/blueprint" "github.com/google/blueprint/proptools" ) @@ -139,6 +140,9 @@ func TestPackageZipFactory() android.Module { } func (p *testPackageZip) GenerateAndroidBuildActions(ctx android.ModuleContext) { + // Never install this test package, it's for disting only + p.SkipInstall() + if !android.InList(ctx.ModuleName(), moduleNamesAllowed) { ctx.ModuleErrorf("%s is not allowed to use module type test_package") } @@ -148,9 +152,9 @@ func (p *testPackageZip) GenerateAndroidBuildActions(ctx android.ModuleContext) ctx.SetOutputFiles(android.Paths{p.output}, "") // dist the test output - if ctx.ModuleName() == "platform_tests_soong" { - distedName := ctx.Config().Getenv("TARGET_PRODUCT") + "-tests-" + ctx.Config().BuildId() + ".zip" - ctx.DistForGoalsWithFilename([]string{"droid", "platform_tests"}, p.output, distedName) + if ctx.ModuleName() == "platform_tests" { + distedName := ctx.Config().Getenv("TARGET_PRODUCT") + "-tests-FILE_NAME_TAG_PLACEHOLDER.zip" + ctx.DistForGoalWithFilename("platform_tests", p.output, distedName) } } @@ -165,52 +169,20 @@ func createOutput(ctx android.ModuleContext, pctx android.PackageContext) androi builder.Command().Text("rm").Flag("-rf").Text(stagingDir.String()) builder.Command().Text("mkdir").Flag("-p").Output(stagingDir) builder.Temporary(stagingDir) - ctx.VisitDirectDepsWithTag(testPackageZipDepTag, func(m android.Module) { - info, ok := android.OtherModuleProvider(ctx, m, android.ModuleInfoJSONProvider) - if !ok { - ctx.OtherModuleErrorf(m, "doesn't set ModuleInfoJSON provider") - } else if len(info) != 1 { - ctx.OtherModuleErrorf(m, "doesn't provide exactly one ModuleInfoJSON") - } - - classes := info[0].GetClass() - if len(info[0].Class) != 1 { - ctx.OtherModuleErrorf(m, "doesn't have exactly one class in its ModuleInfoJSON") + ctx.WalkDeps(func(child, parent android.Module) bool { + if !child.Enabled(ctx) { + return false } - class := strings.ToLower(classes[0]) - if class == "apps" { - class = "app" - } else if class == "java_libraries" { - class = "framework" - } - - installedFilesInfo, ok := android.OtherModuleProvider(ctx, m, android.InstallFilesProvider) - if !ok { - ctx.ModuleErrorf("Module %s doesn't set InstallFilesProvider", m.Name()) - } - - for _, installedFile := range installedFilesInfo.InstallFiles { - // there are additional installed files for some app-class modules, we only need the .apk files in the test package - if class == "app" && installedFile.Ext() != ".apk" { - continue - } - name := removeFileExtension(installedFile.Base()) - f := strings.TrimPrefix(installedFile.String(), productOut+"/") - if strings.HasPrefix(f, "out") { - continue - } - f = strings.ReplaceAll(f, "system/", "DATA/") - f = strings.ReplaceAll(f, filepath.Join("testcases", name, arch), filepath.Join("DATA", class, name)) - f = strings.ReplaceAll(f, filepath.Join("testcases", name, secondArch), filepath.Join("DATA", class, name)) - f = strings.ReplaceAll(f, "testcases", filepath.Join("DATA", class)) - f = strings.ReplaceAll(f, "data/", "DATA/") - f = strings.ReplaceAll(f, "DATA_other", "system_other") - f = strings.ReplaceAll(f, "system_other/DATA", "system_other/system") - dir := filepath.Dir(f) - tempOut := android.PathForModuleOut(ctx, "STAGING", f) - builder.Command().Text("mkdir").Flag("-p").Text(filepath.Join(stagingDir.String(), dir)) - builder.Command().Text("cp").Flag("-Rf").Input(installedFile).Output(tempOut) - builder.Temporary(tempOut) + if android.EqualModules(parent, ctx.Module()) && ctx.OtherModuleDependencyTag(child) == testPackageZipDepTag { + // handle direct deps + extendBuilderCommand(ctx, child, builder, stagingDir, productOut, arch, secondArch) + return true + } else if !android.EqualModules(parent, ctx.Module()) && ctx.OtherModuleDependencyTag(child) == android.RequiredDepTag { + // handle the "required" from deps + extendBuilderCommand(ctx, child, builder, stagingDir, productOut, arch, secondArch) + return true + } else { + return false } }) @@ -225,6 +197,82 @@ func createOutput(ctx android.ModuleContext, pctx android.PackageContext) androi return output } +func extendBuilderCommand(ctx android.ModuleContext, m android.Module, builder *android.RuleBuilder, stagingDir android.ModuleOutPath, productOut, arch, secondArch string) { + info, ok := android.OtherModuleProvider(ctx, m, android.ModuleInfoJSONProvider) + if !ok { + ctx.OtherModuleErrorf(m, "doesn't set ModuleInfoJSON provider") + } else if len(info) != 1 { + ctx.OtherModuleErrorf(m, "doesn't provide exactly one ModuleInfoJSON") + } + + classes := info[0].GetClass() + if len(info[0].Class) != 1 { + ctx.OtherModuleErrorf(m, "doesn't have exactly one class in its ModuleInfoJSON") + } + class := strings.ToLower(classes[0]) + if class == "apps" { + class = "app" + } else if class == "java_libraries" { + class = "framework" + } + + installedFilesInfo, ok := android.OtherModuleProvider(ctx, m, android.InstallFilesProvider) + if !ok { + ctx.ModuleErrorf("Module %s doesn't set InstallFilesProvider", m.Name()) + } + + for _, spec := range installedFilesInfo.PackagingSpecs { + if spec.SrcPath() == nil { + // Probably a symlink + continue + } + installedFile := spec.FullInstallPath() + + ext := installedFile.Ext() + // there are additional installed files for some app-class modules, we only need the .apk, .odex and .vdex files in the test package + excludeInstalledFile := ext != ".apk" && ext != ".odex" && ext != ".vdex" + if class == "app" && excludeInstalledFile { + continue + } + // only .jar files should be included for a framework dep + if class == "framework" && ext != ".jar" { + continue + } + name := removeFileExtension(installedFile.Base()) + // some apks have other apk as installed files, these additional files shouldn't be included + isAppOrFramework := class == "app" || class == "framework" + if isAppOrFramework && name != ctx.OtherModuleName(m) { + continue + } + + f := strings.TrimPrefix(installedFile.String(), productOut+"/") + if strings.HasPrefix(f, "out") { + continue + } + if strings.HasPrefix(f, "system/") { + f = strings.Replace(f, "system/", "DATA/", 1) + } + f = strings.ReplaceAll(f, filepath.Join("testcases", name, arch), filepath.Join("DATA", class, name)) + f = strings.ReplaceAll(f, filepath.Join("testcases", name, secondArch), filepath.Join("DATA", class, name)) + if strings.HasPrefix(f, "testcases") { + f = strings.Replace(f, "testcases", filepath.Join("DATA", class), 1) + } + if strings.HasPrefix(f, "data/") { + f = strings.Replace(f, "data/", "DATA/", 1) + } + f = strings.ReplaceAll(f, "DATA_other", "system_other") + f = strings.ReplaceAll(f, "system_other/DATA", "system_other/system") + dir := filepath.Dir(f) + + tempOut := android.PathForModuleOut(ctx, "STAGING", f) + builder.Command().Text("mkdir").Flag("-p").Text(filepath.Join(stagingDir.String(), dir)) + // Copy srcPath instead of installedFile because some rules like target-files.zip + // are non-hermetic and would be affected if we built the installed files. + builder.Command().Text("cp").Flag("-Rf").Input(spec.SrcPath()).Output(tempOut) + builder.Temporary(tempOut) + } +} + func removeFileExtension(filename string) string { return strings.TrimSuffix(filename, filepath.Ext(filename)) } diff --git a/dexpreopt/Android.bp b/dexpreopt/Android.bp index 679d06627..dbc192238 100644 --- a/dexpreopt/Android.bp +++ b/dexpreopt/Android.bp @@ -9,6 +9,8 @@ bootstrap_go_package { "class_loader_context.go", "config.go", "dexpreopt.go", + "dexpreopt_tools_zip.go", + "system_server_zip.go", "testing.go", ], testSrcs: [ diff --git a/dexpreopt/class_loader_context.go b/dexpreopt/class_loader_context.go index af1d33da6..7f50912b5 100644 --- a/dexpreopt/class_loader_context.go +++ b/dexpreopt/class_loader_context.go @@ -291,6 +291,11 @@ func (clcMap ClassLoaderContextMap) addContext(ctx android.ModuleInstallPathCont // For prebuilts, library should have the same name as the source module. lib = android.RemoveOptionalPrebuiltPrefix(lib) + // Bootclasspath libraries should not be added to CLC. + if android.InList(lib, ctx.Config().BootJars()) { + return nil + } + devicePath := UnknownInstallLibraryPath if installPath == nil { if android.InList(lib, CompatUsesLibs) || android.InList(lib, OptionalCompatUsesLibs) { diff --git a/dexpreopt/config.go b/dexpreopt/config.go index c5cafb1cf..e57384fd7 100644 --- a/dexpreopt/config.go +++ b/dexpreopt/config.go @@ -464,8 +464,8 @@ func (d dex2oatDependencyTag) AllowDisabledModuleDependency(target android.Modul func (d dex2oatDependencyTag) AllowDisabledModuleDependencyProxy( ctx android.OtherModuleProviderContext, target android.ModuleProxy) bool { - return android.OtherModuleProviderOrDefault( - ctx, target, android.CommonModuleInfoKey).ReplacedByPrebuilt + return android.OtherModulePointerProviderOrDefault( + ctx, target, android.CommonModuleInfoProvider).ReplacedByPrebuilt } // Dex2oatDepTag represents the dependency onto the dex2oatd module. It is added to any module that @@ -510,7 +510,7 @@ func dex2oatPathFromDep(ctx android.ModuleContext) android.Path { var dex2oatModule android.ModuleProxy ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool { prebuiltInfo, isPrebuilt := android.OtherModuleProvider(ctx, child, android.PrebuiltModuleInfoProvider) - if ctx.EqualModules(parent, ctx.Module()) && ctx.OtherModuleDependencyTag(child) == Dex2oatDepTag { + if android.EqualModules(parent, ctx.Module()) && ctx.OtherModuleDependencyTag(child) == Dex2oatDepTag { // Found the source module, or prebuilt module that has replaced the source. dex2oatModule = child if isPrebuilt { @@ -519,7 +519,7 @@ func dex2oatPathFromDep(ctx android.ModuleContext) android.Path { return true // Recurse to check if the source has a prebuilt dependency. } } - if ctx.EqualModules(parent, dex2oatModule) && ctx.OtherModuleDependencyTag(child) == android.PrebuiltDepTag { + if android.EqualModules(parent, dex2oatModule) && ctx.OtherModuleDependencyTag(child) == android.PrebuiltDepTag { if isPrebuilt && prebuiltInfo.UsePrebuilt { dex2oatModule = child // Found a prebuilt that should be used. } @@ -717,17 +717,8 @@ func buildUffdGcFlag(ctx android.BuilderContext, global *GlobalConfig) { } else if global.EnableUffdGc == "false" { android.WriteFileRuleVerbatim(ctx, uffdGcFlag, "") } else if global.EnableUffdGc == "default" { - // Generated by `build/make/core/Makefile`. + // Generated by build/make/core/Makefile, or the android_device module in soong-only builds. kernelVersionFile := android.PathForOutput(ctx, "dexpreopt/kernel_version_for_uffd_gc.txt") - if !ctx.Config().KatiEnabled() { - // In soong-only mode, we need to generate the kernel_version_for_uffd_gc.txt with kernel version - kernelVersion := android.String(ctx.Config().ProductVariables().BoardKernelVersion) - if kernelVersion == "" { - // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=5382;drc=66783fca85911af9da48d9b4f35a61b3873023e9 - panic("BOARD_KERNEL_VERSION is not set. Build team will convert more stuff from Make to Soong to support this scenario.") - } - android.WriteFileRule(ctx, kernelVersionFile, kernelVersion) - } // Determine the UFFD GC flag by the kernel version file. rule := android.NewRuleBuilder(pctx, ctx) diff --git a/dexpreopt/dexpreopt_tools_zip.go b/dexpreopt/dexpreopt_tools_zip.go new file mode 100644 index 000000000..c7cf12830 --- /dev/null +++ b/dexpreopt/dexpreopt_tools_zip.go @@ -0,0 +1,62 @@ +package dexpreopt + +import "android/soong/android" + +func init() { + android.InitRegistrationContext.RegisterSingletonType("dexpreopt_tools_zip_singleton", dexpreoptToolsZipSingletonFactory) +} + +func dexpreoptToolsZipSingletonFactory() android.Singleton { + return &dexpreoptToolsZipSingleton{} +} + +type dexpreoptToolsZipSingleton struct{} + +func (s *dexpreoptToolsZipSingleton) GenerateBuildActions(ctx android.SingletonContext) { + // The mac build doesn't build dex2oat, so create the zip file only if the build OS is linux. + if !ctx.Config().BuildOS.Linux() { + return + } + global := GetGlobalConfig(ctx) + if global.DisablePreopt { + return + } + config := GetCachedGlobalSoongConfig(ctx) + if config == nil { + return + } + + deps := android.Paths{ + ctx.Config().HostToolPath(ctx, "dexpreopt_gen"), + ctx.Config().HostToolPath(ctx, "dexdump"), + ctx.Config().HostToolPath(ctx, "oatdump"), + config.Profman, + config.Dex2oat, + config.Aapt, + config.SoongZip, + config.Zip2zip, + config.ManifestCheck, + config.ConstructContext, + config.UffdGcFlag, + } + + out := android.PathForOutput(ctx, "dexpreopt_tools.zip") + builder := android.NewRuleBuilder(pctx, ctx) + + cmd := builder.Command().BuiltTool("soong_zip"). + Flag("-d"). + FlagWithOutput("-o ", out). + Flag("-j") + + for _, dep := range deps { + cmd.FlagWithInput("-f ", dep) + } + + // This reads through a symlink to include the file it points to. This isn't great for + // build reproducibility, will need to be revisited later. + cmd.Textf("-f $(realpath %s)", config.Dex2oat) + + builder.Build("dexpreopt_tools_zip", "building dexpreopt_tools.zip") + + ctx.DistForGoal("droidcore", out) +} diff --git a/dexpreopt/system_server_zip.go b/dexpreopt/system_server_zip.go new file mode 100644 index 000000000..cef847b7d --- /dev/null +++ b/dexpreopt/system_server_zip.go @@ -0,0 +1,49 @@ +package dexpreopt + +import "android/soong/android" + +func init() { + android.InitRegistrationContext.RegisterSingletonType("system_server_zip_singleton", systemServerZipSingletonFactory) +} + +func systemServerZipSingletonFactory() android.Singleton { + return &systemServerZipSingleton{} +} + +type systemServerZipSingleton struct{} + +func (s *systemServerZipSingleton) GenerateBuildActions(ctx android.SingletonContext) { + global := GetGlobalConfig(ctx) + if global.DisablePreopt || global.OnlyPreoptArtBootImage { + return + } + + systemServerDexjarsDir := android.PathForOutput(ctx, SystemServerDexjarsDir) + + out := android.PathForOutput(ctx, "system_server.zip") + builder := android.NewRuleBuilder(pctx, ctx) + cmd := builder.Command().BuiltTool("soong_zip"). + FlagWithOutput("-o ", out). + FlagWithArg("-C ", systemServerDexjarsDir.String()) + + for i := 0; i < global.SystemServerJars.Len(); i++ { + jar := global.SystemServerJars.Jar(i) + ".jar" + cmd.FlagWithInput("-f ", systemServerDexjarsDir.Join(ctx, jar)) + } + for i := 0; i < global.StandaloneSystemServerJars.Len(); i++ { + jar := global.StandaloneSystemServerJars.Jar(i) + ".jar" + cmd.FlagWithInput("-f ", systemServerDexjarsDir.Join(ctx, jar)) + } + for i := 0; i < global.ApexSystemServerJars.Len(); i++ { + jar := global.ApexSystemServerJars.Jar(i) + ".jar" + cmd.FlagWithInput("-f ", systemServerDexjarsDir.Join(ctx, jar)) + } + for i := 0; i < global.ApexStandaloneSystemServerJars.Len(); i++ { + jar := global.ApexStandaloneSystemServerJars.Jar(i) + ".jar" + cmd.FlagWithInput("-f ", systemServerDexjarsDir.Join(ctx, jar)) + } + + builder.Build("system_server_zip", "building system_server.zip") + + ctx.DistForGoal("droidcore", out) +} diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go index fad8f0779..3b0c0329d 100644 --- a/etc/prebuilt_etc.go +++ b/etc/prebuilt_etc.go @@ -65,6 +65,7 @@ func RegisterPrebuiltEtcBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("prebuilt_font", PrebuiltFontFactory) ctx.RegisterModuleType("prebuilt_overlay", PrebuiltOverlayFactory) ctx.RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory) + ctx.RegisterModuleType("prebuilt_gpu", PrebuiltGPUFactory) ctx.RegisterModuleType("prebuilt_dsp", PrebuiltDSPFactory) ctx.RegisterModuleType("prebuilt_rfsa", PrebuiltRFSAFactory) ctx.RegisterModuleType("prebuilt_renderscript_bitcode", PrebuiltRenderScriptBitcodeFactory) @@ -73,12 +74,14 @@ func RegisterPrebuiltEtcBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("prebuilt_bin", PrebuiltBinaryFactory) ctx.RegisterModuleType("prebuilt_wallpaper", PrebuiltWallpaperFactory) ctx.RegisterModuleType("prebuilt_priv_app", PrebuiltPrivAppFactory) + ctx.RegisterModuleType("prebuilt_radio", PrebuiltRadioFactory) ctx.RegisterModuleType("prebuilt_rfs", PrebuiltRfsFactory) ctx.RegisterModuleType("prebuilt_framework", PrebuiltFrameworkFactory) ctx.RegisterModuleType("prebuilt_res", PrebuiltResFactory) ctx.RegisterModuleType("prebuilt_wlc_upt", PrebuiltWlcUptFactory) ctx.RegisterModuleType("prebuilt_odm", PrebuiltOdmFactory) ctx.RegisterModuleType("prebuilt_vendor_dlkm", PrebuiltVendorDlkmFactory) + ctx.RegisterModuleType("prebuilt_vendor_overlay", PrebuiltVendorOverlayFactory) ctx.RegisterModuleType("prebuilt_bt_firmware", PrebuiltBtFirmwareFactory) ctx.RegisterModuleType("prebuilt_tvservice", PrebuiltTvServiceFactory) ctx.RegisterModuleType("prebuilt_optee", PrebuiltOpteeFactory) @@ -87,6 +90,7 @@ func RegisterPrebuiltEtcBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("prebuilt_sbin", PrebuiltSbinFactory) ctx.RegisterModuleType("prebuilt_system", PrebuiltSystemFactory) ctx.RegisterModuleType("prebuilt_first_stage_ramdisk", PrebuiltFirstStageRamdiskFactory) + ctx.RegisterModuleType("prebuilt_any", PrebuiltAnyFactory) ctx.RegisterModuleType("prebuilt_defaults", defaultsFactory) @@ -113,12 +117,6 @@ type PrebuiltEtcProperties struct { // set. May use globs in filenames. Srcs proptools.Configurable[[]string] `android:"path,arch_variant"` - // Destination files of this prebuilt. Requires srcs to be used and causes srcs not to implicitly - // set filename_from_src. This can be used to install each source file to a different directory - // and/or change filenames when files are installed. Must be exactly one entry per source file, - // which means care must be taken if srcs has globs. - Dsts proptools.Configurable[[]string] `android:"path,arch_variant"` - // Optional name for the installed file. If unspecified, name of the module is used as the file // name. Only available when using a single source (src). Filename *string `android:"arch_variant"` @@ -157,6 +155,20 @@ type PrebuiltEtcProperties struct { Oem_specific *bool `android:"arch_variant"` } +// Dsts is useful in that it allows prebuilt_* modules to easily map the source files to the +// install path within the partition. Dsts values are allowed to contain filepath separator +// so that the source files can be installed in subdirectories within the partition. +// However, this functionality should not be supported for prebuilt_root module type, as it +// allows the module to install to any arbitrary location. Thus, this property is defined in +// a separate struct so that it's not available to be set in prebuilt_root module type. +type PrebuiltDstsProperties struct { + // Destination files of this prebuilt. Requires srcs to be used and causes srcs not to implicitly + // set filename_from_src. This can be used to install each source file to a different directory + // and/or change filenames when files are installed. Must be exactly one entry per source file, + // which means care must be taken if srcs has globs. + Dsts proptools.Configurable[[]string] `android:"path,arch_variant"` +} + type prebuiltSubdirProperties struct { // Optional subdirectory under which this file is installed into, cannot be specified with // relative_install_path, prefer relative_install_path. @@ -192,6 +204,8 @@ type PrebuiltEtc struct { properties PrebuiltEtcProperties + dstsProperties PrebuiltDstsProperties + // rootProperties is used to return the value of the InstallInRoot() method. Currently, only // prebuilt_avb and prebuilt_root modules use this. rootProperties prebuiltRootProperties @@ -382,7 +396,7 @@ func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) { if srcProperty.IsPresent() && len(srcsProperty) > 0 { ctx.PropertyErrorf("src", "src is set. Cannot set srcs") } - dstsProperty := p.properties.Dsts.GetOrDefault(ctx, nil) + dstsProperty := p.dstsProperties.Dsts.GetOrDefault(ctx, nil) if len(dstsProperty) > 0 && len(srcsProperty) == 0 { ctx.PropertyErrorf("dsts", "dsts is set. Must use srcs") } @@ -610,6 +624,7 @@ func InitPrebuiltEtcModule(p *PrebuiltEtc, dirBase string) { p.AddProperties(&p.properties) p.AddProperties(&p.subdirProperties) p.AddProperties(&p.rootProperties) + p.AddProperties(&p.dstsProperties) } func InitPrebuiltRootModule(p *PrebuiltEtc) { @@ -621,6 +636,7 @@ func InitPrebuiltRootModule(p *PrebuiltEtc) { func InitPrebuiltAvbModule(p *PrebuiltEtc) { p.installDirBase = "avb" p.AddProperties(&p.properties) + p.AddProperties(&p.dstsProperties) p.rootProperties.Install_in_root = proptools.BoolPtr(true) } @@ -664,6 +680,20 @@ func PrebuiltEtcHostFactory() android.Module { return module } +// prebuilt_any is a special module where the module can define the subdirectory that the files +// are installed to. This is only used for converting the PRODUCT_COPY_FILES entries to Soong +// modules, and should never be defined in the bp files. If none of the existing prebuilt_* +// modules allow installing the file at the desired location, introduce a new prebuilt_* module +// type instead. +func PrebuiltAnyFactory() android.Module { + module := &PrebuiltEtc{} + InitPrebuiltEtcModule(module, ".") + // This module is device-only + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) + android.InitDefaultableModule(module) + return module +} + // prebuilt_etc_host is for a host prebuilt artifact that is installed in // <partition>/etc/<sub_dir> directory. func PrebuiltEtcCaCertsFactory() android.Module { @@ -831,6 +861,15 @@ func PrebuiltFirmwareFactory() android.Module { return module } +// prebuilt_gpu is for a prebuilt artifact in <partition>/gpu directory. +func PrebuiltGPUFactory() android.Module { + module := &PrebuiltEtc{} + InitPrebuiltEtcModule(module, "gpu") + // This module is device-only + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) + return module +} + // prebuilt_dsp installs a DSP related file to <partition>/etc/dsp directory for system image. // If soc_specific property is set to true, the DSP related file is installed to the // vendor <partition>/dsp directory for vendor image. @@ -921,6 +960,16 @@ func PrebuiltPrivAppFactory() android.Module { return module } +// prebuilt_radio installs files in <partition>/radio directory. +func PrebuiltRadioFactory() android.Module { + module := &PrebuiltEtc{} + InitPrebuiltEtcModule(module, "radio") + // This module is device-only + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) + android.InitDefaultableModule(module) + return module +} + // prebuilt_rfs installs files in <partition>/rfs directory. func PrebuiltRfsFactory() android.Module { module := &PrebuiltEtc{} @@ -1031,6 +1080,16 @@ func PrebuiltVendorFactory() android.Module { return module } +// prebuilt_vendor_overlay is for a prebuilt artifact in <partition>/vendor_overlay directory. +func PrebuiltVendorOverlayFactory() android.Module { + module := &PrebuiltEtc{} + InitPrebuiltEtcModule(module, "vendor_overlay") + // This module is device-only + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) + android.InitDefaultableModule(module) + return module +} + // prebuilt_sbin installs files in <partition>/sbin directory. func PrebuiltSbinFactory() android.Module { module := &PrebuiltEtc{} diff --git a/filesystem/aconfig_files.go b/filesystem/aconfig_files.go index b4173d784..20a195313 100644 --- a/filesystem/aconfig_files.go +++ b/filesystem/aconfig_files.go @@ -17,6 +17,7 @@ package filesystem import ( "android/soong/android" "strconv" + "strings" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -31,19 +32,12 @@ var ( Command: `$aconfig create-storage --container $container --file $fileType --out $out --cache $in --version $version`, CommandDeps: []string{"$aconfig"}, }, "container", "fileType", "version") -) - -type installedAconfigFlagsInfo struct { - aconfigFiles android.Paths -} - -var installedAconfigFlagsProvider = blueprint.NewProvider[installedAconfigFlagsInfo]() -type importAconfigDepDag struct { - blueprint.BaseDependencyTag -} - -var importAconfigDependencyTag = interPartitionDepTag{} + subPartitionsInPartition = map[string][]string{ + "system": {"system_ext", "product", "vendor"}, + "vendor": {"odm"}, + } +) func (f *filesystem) buildAconfigFlagsFiles( ctx android.ModuleContext, @@ -52,88 +46,97 @@ func (f *filesystem) buildAconfigFlagsFiles( dir android.OutputPath, fullInstallPaths *[]FullInstallPathInfo, ) { + if !proptools.Bool(f.properties.Gen_aconfig_flags_pb) { + return + } + + partition := f.PartitionType() + subPartitionsFound := map[string]bool{} + fullInstallPath := android.PathForModuleInPartitionInstall(ctx, partition) + + for _, subPartition := range subPartitionsInPartition[partition] { + subPartitionsFound[subPartition] = false + } + var caches []android.Path for _, ps := range specs { caches = append(caches, ps.GetAconfigPaths()...) + for subPartition, found := range subPartitionsFound { + if !found && strings.HasPrefix(ps.RelPathInPackage(), subPartition+"/") { + subPartitionsFound[subPartition] = true + break + } + } } + caches = android.SortedUniquePaths(caches) - ctx.VisitDirectDepsWithTag(importAconfigDependencyTag, func(m android.Module) { - info, ok := android.OtherModuleProvider(ctx, m, installedAconfigFlagsProvider) - if !ok { - ctx.ModuleErrorf("expected dependency %s to have an installedAconfigFlagsProvider", m.Name()) - return + buildAconfigFlagsFiles := func(container string, dir android.OutputPath, fullInstallPath android.InstallPath) { + aconfigFlagsPb := android.PathForModuleOut(ctx, "aconfig", container, "aconfig_flags.pb") + aconfigFlagsPbBuilder := android.NewRuleBuilder(pctx, ctx) + cmd := aconfigFlagsPbBuilder.Command(). + BuiltTool("aconfig"). + Text(" dump-cache --dedup --format protobuf --out"). + Output(aconfigFlagsPb). + Textf("--filter container:%s+state:ENABLED", container). + Textf("--filter container:%s+permission:READ_WRITE", container) + for _, cache := range caches { + cmd.FlagWithInput("--cache ", cache) } - caches = append(caches, info.aconfigFiles...) - }) - caches = android.SortedUniquePaths(caches) + aconfigFlagsPbBuilder.Build(container+"_aconfig_flags_pb", "build aconfig_flags.pb") - android.SetProvider(ctx, installedAconfigFlagsProvider, installedAconfigFlagsInfo{ - aconfigFiles: caches, - }) + installEtcDir := dir.Join(ctx, "etc") + installAconfigFlagsPath := installEtcDir.Join(ctx, "aconfig_flags.pb") + builder.Command().Text("mkdir -p ").Text(installEtcDir.String()) + builder.Command().Text("cp").Input(aconfigFlagsPb).Text(installAconfigFlagsPath.String()) + *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{ + FullInstallPath: fullInstallPath.Join(ctx, "etc/aconfig_flags.pb"), + SourcePath: aconfigFlagsPb, + }) + f.appendToEntry(ctx, installAconfigFlagsPath) - if !proptools.Bool(f.properties.Gen_aconfig_flags_pb) { - return - } + // To enable fingerprint, we need to have v2 storage files. The default version is 1. + storageFilesVersion := 1 + if ctx.Config().ReleaseFingerprintAconfigPackages() { + storageFilesVersion = 2 + } - container := f.PartitionType() - - aconfigFlagsPb := android.PathForModuleOut(ctx, "aconfig", "aconfig_flags.pb") - aconfigFlagsPbBuilder := android.NewRuleBuilder(pctx, ctx) - cmd := aconfigFlagsPbBuilder.Command(). - BuiltTool("aconfig"). - Text(" dump-cache --dedup --format protobuf --out"). - Output(aconfigFlagsPb). - Textf("--filter container:%s+state:ENABLED", container). - Textf("--filter container:%s+permission:READ_WRITE", container) - for _, cache := range caches { - cmd.FlagWithInput("--cache ", cache) - } - aconfigFlagsPbBuilder.Build("aconfig_flags_pb", "build aconfig_flags.pb") - - installAconfigFlagsPath := dir.Join(ctx, "etc", "aconfig_flags.pb") - builder.Command().Text("mkdir -p ").Text(dir.Join(ctx, "etc").String()) - builder.Command().Text("cp").Input(aconfigFlagsPb).Text(installAconfigFlagsPath.String()) - *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{ - FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), "etc/aconfig_flags.pb"), - SourcePath: aconfigFlagsPb, - }) - f.appendToEntry(ctx, installAconfigFlagsPath) - - // To enable fingerprint, we need to have v2 storage files. The default version is 1. - storageFilesVersion := 1 - if ctx.Config().ReleaseFingerprintAconfigPackages() { - storageFilesVersion = 2 - } + installAconfigStorageDir := installEtcDir.Join(ctx, "aconfig") + builder.Command().Text("mkdir -p").Text(installAconfigStorageDir.String()) + + generatePartitionAconfigStorageFile := func(fileType, fileName string) { + outPath := android.PathForModuleOut(ctx, "aconfig", container, fileName) + installPath := installAconfigStorageDir.Join(ctx, fileName) + ctx.Build(pctx, android.BuildParams{ + Rule: aconfigCreateStorage, + Input: aconfigFlagsPb, + Output: outPath, + Args: map[string]string{ + "container": container, + "fileType": fileType, + "version": strconv.Itoa(storageFilesVersion), + }, + }) + builder.Command(). + Text("cp").Input(outPath).Text(installPath.String()) + *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{ + SourcePath: outPath, + FullInstallPath: fullInstallPath.Join(ctx, "etc/aconfig", fileName), + }) + f.appendToEntry(ctx, installPath) + } - installAconfigStorageDir := dir.Join(ctx, "etc", "aconfig") - builder.Command().Text("mkdir -p").Text(installAconfigStorageDir.String()) - - generatePartitionAconfigStorageFile := func(fileType, fileName string) { - outPath := android.PathForModuleOut(ctx, "aconfig", fileName) - installPath := installAconfigStorageDir.Join(ctx, fileName) - ctx.Build(pctx, android.BuildParams{ - Rule: aconfigCreateStorage, - Input: aconfigFlagsPb, - Output: outPath, - Args: map[string]string{ - "container": container, - "fileType": fileType, - "version": strconv.Itoa(storageFilesVersion), - }, - }) - builder.Command(). - Text("cp").Input(outPath).Text(installPath.String()) - *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{ - SourcePath: outPath, - FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), "etc/aconfig", fileName), - }) - f.appendToEntry(ctx, installPath) + if ctx.Config().ReleaseCreateAconfigStorageFile() { + generatePartitionAconfigStorageFile("package_map", "package.map") + generatePartitionAconfigStorageFile("flag_map", "flag.map") + generatePartitionAconfigStorageFile("flag_val", "flag.val") + generatePartitionAconfigStorageFile("flag_info", "flag.info") + } } - if ctx.Config().ReleaseCreateAconfigStorageFile() { - generatePartitionAconfigStorageFile("package_map", "package.map") - generatePartitionAconfigStorageFile("flag_map", "flag.map") - generatePartitionAconfigStorageFile("flag_val", "flag.val") - generatePartitionAconfigStorageFile("flag_info", "flag.info") + buildAconfigFlagsFiles(partition, dir, fullInstallPath) + for _, subPartition := range android.SortedKeys(subPartitionsFound) { + if subPartitionsFound[subPartition] { + buildAconfigFlagsFiles(subPartition, dir.Join(ctx, subPartition), fullInstallPath.Join(ctx, subPartition)) + } } } diff --git a/filesystem/android_device.go b/filesystem/android_device.go index fef4aeb43..3f6348dbf 100644 --- a/filesystem/android_device.go +++ b/filesystem/android_device.go @@ -19,6 +19,7 @@ import ( "fmt" "path/filepath" "slices" + "sort" "strings" "sync/atomic" @@ -87,6 +88,14 @@ type DeviceProperties struct { Ramdisk_node_list *string `android:"path"` Releasetools_extension *string `android:"path"` + FastbootInfo *string `android:"path"` + + // The kernel version in the build. Will be verified against the actual kernel. + // If not provided, will attempt to extract it from the loose kernel or the kernel inside + // the boot image. The version is later used to decide whether or not to enable uffd_gc + // when dexpreopting apps. So setting this doesn't really do anything except enforce that the + // actual kernel version is as specified here. + Kernel_version *string } type androidDevice struct { @@ -98,9 +107,15 @@ type androidDevice struct { allImagesZip android.Path - proguardDictZip android.Path - proguardDictMapping android.Path - proguardUsageZip android.Path + proguardDictZip android.Path + proguardDictMapping android.Path + proguardUsageZip android.Path + kernelConfig android.Path + kernelVersion android.Path + miscInfo android.Path + rootDirForFsConfig string + rootDirForFsConfigTimestamp android.Path + apkCertsInfo android.Path } func AndroidDeviceFactory() android.Module { @@ -175,7 +190,10 @@ func (a *androidDevice) GenerateAndroidBuildActions(ctx android.ModuleContext) { allInstalledModules := a.allInstalledModules(ctx) - a.buildTargetFilesZip(ctx) + a.apkCertsInfo = a.buildApkCertsInfo(ctx, allInstalledModules) + a.kernelVersion, a.kernelConfig = a.extractKernelVersionAndConfigs(ctx) + a.miscInfo = a.addMiscInfo(ctx) + a.buildTargetFilesZip(ctx, allInstalledModules) a.buildProguardZips(ctx, allInstalledModules) var deps []android.Path @@ -263,6 +281,39 @@ func (a *androidDevice) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.setVbmetaPhonyTargets(ctx) a.distFiles(ctx) + + android.SetProvider(ctx, android.AndroidDeviceInfoProvider, android.AndroidDeviceInfo{ + Main_device: android.Bool(a.deviceProps.Main_device), + }) + + if proptools.String(a.partitionProps.Super_partition_name) != "" { + buildComplianceMetadata(ctx, superPartitionDepTag, filesystemDepTag) + } else { + buildComplianceMetadata(ctx, filesystemDepTag) + } +} + +func buildComplianceMetadata(ctx android.ModuleContext, tags ...blueprint.DependencyTag) { + // Collect metadata from deps + filesContained := make([]string, 0) + prebuiltFilesCopied := make([]string, 0) + for _, tag := range tags { + ctx.VisitDirectDepsProxyWithTag(tag, func(m android.ModuleProxy) { + if complianceMetadataInfo, ok := android.OtherModuleProvider(ctx, m, android.ComplianceMetadataProvider); ok { + filesContained = append(filesContained, complianceMetadataInfo.GetFilesContained()...) + prebuiltFilesCopied = append(prebuiltFilesCopied, complianceMetadataInfo.GetPrebuiltFilesCopied()...) + } + }) + } + // Merge to module's ComplianceMetadataInfo + complianceMetadataInfo := ctx.ComplianceMetadataInfo() + filesContained = append(filesContained, complianceMetadataInfo.GetFilesContained()...) + sort.Strings(filesContained) + complianceMetadataInfo.SetFilesContained(filesContained) + + prebuiltFilesCopied = append(prebuiltFilesCopied, complianceMetadataInfo.GetPrebuiltFilesCopied()...) + sort.Strings(prebuiltFilesCopied) + complianceMetadataInfo.SetPrebuiltFilesCopied(prebuiltFilesCopied) } // Returns a list of modules that are installed, which are collected from the dependency @@ -279,7 +330,7 @@ func (a *androidDevice) allInstalledModules(ctx android.ModuleContext) []android ret := []android.Module{} ctx.WalkDepsProxy(func(mod, _ android.ModuleProxy) bool { - if variations, ok := allOwners[mod.Name()]; ok && android.InList(ctx.OtherModuleSubDir(mod), variations) { + if variations, ok := allOwners[ctx.OtherModuleName(mod)]; ok && android.InList(ctx.OtherModuleSubDir(mod), variations) { ret = append(ret, mod) } return true @@ -302,18 +353,32 @@ func insertBeforeExtension(file, insertion string) string { return strings.TrimSuffix(file, ext) + insertion + ext } +func (a *androidDevice) distInstalledFiles(ctx android.ModuleContext) { + distInstalledFilesJsonAndTxt := func(installedFiles InstalledFilesStruct) { + if installedFiles.Json != nil { + ctx.DistForGoal("droidcore-unbundled", installedFiles.Json) + } + if installedFiles.Txt != nil { + ctx.DistForGoal("droidcore-unbundled", installedFiles.Txt) + } + } + + fsInfoMap := a.getFsInfos(ctx) + for _, partition := range android.SortedKeys(fsInfoMap) { + // installed-files-*{.txt | .json} is not disted for userdata partition + if partition == "userdata" { + continue + } + fsInfo := fsInfoMap[partition] + for _, installedFiles := range fsInfo.InstalledFilesDepSet.ToList() { + distInstalledFilesJsonAndTxt(installedFiles) + } + } +} + func (a *androidDevice) distFiles(ctx android.ModuleContext) { if !ctx.Config().KatiEnabled() && proptools.Bool(a.deviceProps.Main_device) { - fsInfoMap := a.getFsInfos(ctx) - for _, partition := range android.SortedKeys(fsInfoMap) { - fsInfo := fsInfoMap[partition] - if fsInfo.InstalledFiles.Json != nil { - ctx.DistForGoal("droidcore-unbundled", fsInfo.InstalledFiles.Json) - } - if fsInfo.InstalledFiles.Txt != nil { - ctx.DistForGoal("droidcore-unbundled", fsInfo.InstalledFiles.Txt) - } - } + a.distInstalledFiles(ctx) namePrefix := "" if ctx.Config().HasDeviceProduct() { @@ -322,13 +387,18 @@ func (a *androidDevice) distFiles(ctx android.ModuleContext) { ctx.DistForGoalWithFilename("droidcore-unbundled", a.proguardDictZip, namePrefix+insertBeforeExtension(a.proguardDictZip.Base(), "-FILE_NAME_TAG_PLACEHOLDER")) ctx.DistForGoalWithFilename("droidcore-unbundled", a.proguardDictMapping, namePrefix+insertBeforeExtension(a.proguardDictMapping.Base(), "-FILE_NAME_TAG_PLACEHOLDER")) ctx.DistForGoalWithFilename("droidcore-unbundled", a.proguardUsageZip, namePrefix+insertBeforeExtension(a.proguardUsageZip.Base(), "-FILE_NAME_TAG_PLACEHOLDER")) + + if a.deviceProps.Android_info != nil { + ctx.DistForGoal("droidcore-unbundled", android.PathForModuleSrc(ctx, *a.deviceProps.Android_info)) + } } } -func (a *androidDevice) MakeVars(ctx android.MakeVarsModuleContext) { +func (a *androidDevice) MakeVars(_ android.MakeVarsModuleContext) []android.ModuleMakeVarsValue { if proptools.Bool(a.deviceProps.Main_device) { - ctx.StrictRaw("SOONG_ONLY_ALL_IMAGES_ZIP", a.allImagesZip.String()) + return []android.ModuleMakeVarsValue{{"SOONG_ONLY_ALL_IMAGES_ZIP", a.allImagesZip.String()}} } + return nil } func (a *androidDevice) buildProguardZips(ctx android.ModuleContext, allInstalledModules []android.Module) { @@ -392,7 +462,7 @@ type targetFilesystemZipCopy struct { destSubdir string } -func (a *androidDevice) buildTargetFilesZip(ctx android.ModuleContext) { +func (a *androidDevice) buildTargetFilesZip(ctx android.ModuleContext, allInstalledModules []android.Module) { targetFilesDir := android.PathForModuleOut(ctx, "target_files_dir") targetFilesZip := android.PathForModuleOut(ctx, "target_files.zip") @@ -458,6 +528,17 @@ func (a *androidDevice) buildTargetFilesZip(ctx android.ModuleContext) { if toCopy.destSubdir == "SYSTEM" { // Create the ROOT partition in target_files.zip builder.Command().Textf("rsync --links --exclude=system/* %s/ -r %s/ROOT", toCopy.fsInfo.RootDir, targetFilesDir.String()) + // Add a duplicate rule to assemble the ROOT/ directory in separate intermediates. + // The output timestamp will be an input to a separate fs_config call. + a.rootDirForFsConfig = android.PathForModuleOut(ctx, "root_dir_for_fs_config").String() + rootDirBuilder := android.NewRuleBuilder(pctx, ctx) + rootDirForFsConfigTimestamp := android.PathForModuleOut(ctx, "root_dir_for_fs_config.timestamp") + rootDirBuilder.Command().Textf("rsync --links --exclude=system/* %s/ -r %s", toCopy.fsInfo.RootDir, a.rootDirForFsConfig). + Implicit(toCopy.fsInfo.Output). + Text("&& touch"). + Output(rootDirForFsConfigTimestamp) + rootDirBuilder.Build("assemble_root_dir_for_fs_config", "Assemble ROOT/ for fs_config") + a.rootDirForFsConfigTimestamp = rootDirForFsConfigTimestamp } } // Copy cmdline, kernel etc. files of boot images @@ -496,7 +577,7 @@ func (a *androidDevice) buildTargetFilesZip(ctx android.ModuleContext) { } a.copyImagesToTargetZip(ctx, builder, targetFilesDir) - a.copyMetadataToTargetZip(ctx, builder, targetFilesDir) + a.copyMetadataToTargetZip(ctx, builder, targetFilesDir, allInstalledModules) builder.Command(). BuiltTool("soong_zip"). @@ -542,13 +623,17 @@ func (a *androidDevice) copyImagesToTargetZip(ctx android.ModuleContext, builder builder.Command().Textf("cp ").Input(info.SubImageInfo[partition].MapFile).Textf(" %s/IMAGES/", targetFilesDir.String()) } } + // super_empty.img + if info.SuperEmptyImage != nil { + builder.Command().Textf("cp ").Input(info.SuperEmptyImage).Textf(" %s/IMAGES/", targetFilesDir.String()) + } } else { ctx.ModuleErrorf("Super partition %s does set SuperImageProvider\n", superPartition.Name()) } } } -func (a *androidDevice) copyMetadataToTargetZip(ctx android.ModuleContext, builder *android.RuleBuilder, targetFilesDir android.WritablePath) { +func (a *androidDevice) copyMetadataToTargetZip(ctx android.ModuleContext, builder *android.RuleBuilder, targetFilesDir android.WritablePath, allInstalledModules []android.Module) { // Create a META/ subdirectory builder.Command().Textf("mkdir -p %s/META", targetFilesDir.String()) if proptools.Bool(a.deviceProps.Ab_ota_updater) { @@ -586,7 +671,28 @@ func (a *androidDevice) copyMetadataToTargetZip(ctx android.ModuleContext, build if android.InList(partition, []string{"userdata"}) { continue } - builder.Command().Textf("cp").Input(fsInfos[partition].FilesystemConfig).Textf(" %s/META/%s", targetFilesDir.String(), a.filesystemConfigNameForTargetFiles(partition)) + if partition != "vendor_ramdisk" { + // vendor_ramdisk will be handled separately. + builder.Command().Textf("cp").Input(fsInfos[partition].FilesystemConfig).Textf(" %s/META/%s", targetFilesDir.String(), a.filesystemConfigNameForTargetFiles(partition)) + } + if partition == "ramdisk" { + // Create an additional copy at boot_filesystem_config.txt + builder.Command().Textf("cp").Input(fsInfos[partition].FilesystemConfig).Textf(" %s/META/boot_filesystem_config.txt", targetFilesDir.String()) + } + if partition == "system" { + // Create root_filesystem_config from the assembled ROOT/ intermediates directory + a.generateFilesystemConfigForTargetFiles(ctx, builder, a.rootDirForFsConfigTimestamp, targetFilesDir.String(), a.rootDirForFsConfig, "root_filesystem_config.txt") + } + if partition == "vendor_ramdisk" { + // Create vendor_boot_filesystem_config from the assembled VENDOR_BOOT/RAMDISK intermediates directory + vendorRamdiskStagingDir := targetFilesDir.String() + "/VENDOR_BOOT/RAMDISK" + vendorRamdiskFsConfigOut := targetFilesDir.String() + "/META/vendor_boot_filesystem_config.txt" + fsConfigBin := ctx.Config().HostToolPath(ctx, "fs_config") + builder.Command().Textf( + `(cd %s; find . -type d | sed 's,$,/,'; find . \! -type d) | cut -c 3- | sort | sed 's,^,,' | %s -C -D %s -R \"\" > %s`, + vendorRamdiskStagingDir, fsConfigBin, vendorRamdiskStagingDir, vendorRamdiskFsConfigOut). + Implicit(fsConfigBin) + } } // Copy ramdisk_node_list if ramdiskNodeList := android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Ramdisk_node_list)); ramdiskNodeList != nil { @@ -596,6 +702,148 @@ func (a *androidDevice) copyMetadataToTargetZip(ctx android.ModuleContext, build if releaseTools := android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Releasetools_extension)); releaseTools != nil { builder.Command().Textf("cp").Input(releaseTools).Textf(" %s/META/", targetFilesDir.String()) } + // apexkeys.txt + var installedApexKeys []android.Path + for _, installedModule := range allInstalledModules { + if info, ok := android.OtherModuleProvider(ctx, installedModule, ApexKeyPathInfoProvider); ok { + installedApexKeys = append(installedApexKeys, info.ApexKeyPath) + } + } + installedApexKeys = android.SortedUniquePaths(installedApexKeys) // Sort by keypath to match make + builder.Command().Text("cat").Inputs(installedApexKeys).Textf(" >> %s/META/apexkeys.txt", targetFilesDir.String()) + // apkcerts.txt + builder.Command().Textf("cp").Input(a.apkCertsInfo).Textf(" %s/META/", targetFilesDir.String()) + + // Copy fastboot-info.txt + if fastbootInfo := android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.FastbootInfo)); fastbootInfo != nil { + // TODO (b/399788523): Autogenerate fastboot-info.txt if there is no source fastboot-info.txt + // https://cs.android.com/android/_/android/platform/build/+/80b9546f8f69e78b8fe1870e0e745d70fc18dfcd:core/Makefile;l=5831-5893;drc=077490384423dff9eac954da5c001c6f0be3fa6e;bpv=0;bpt=0 + builder.Command().Textf("cp").Input(fastbootInfo).Textf(" %s/META/fastboot-info.txt", targetFilesDir.String()) + } + + // kernel_configs.txt and kernel_version.txt + if a.kernelConfig != nil { + builder.Command().Textf("cp").Input(a.kernelConfig).Textf(" %s/META/", targetFilesDir.String()) + } + if a.kernelVersion != nil { + builder.Command().Textf("cp").Input(a.kernelVersion).Textf(" %s/META/", targetFilesDir.String()) + } + // misc_info.txt + if a.miscInfo != nil { + builder.Command().Textf("cp").Input(a.miscInfo).Textf(" %s/META/", targetFilesDir.String()) + } + // apex_info.pb, care_map.pb, vbmeta_digest.txt + a.addImgToTargetFiles(ctx, builder, targetFilesDir.String()) + + if a.partitionProps.Super_partition_name != nil { + superPartition := ctx.GetDirectDepProxyWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag) + if info, ok := android.OtherModuleProvider(ctx, superPartition, SuperImageProvider); ok { + // dynamic_partitions_info.txt + // TODO (b/390192334): Add `building_super_empty_partition=true` + builder.Command().Text("cp").Input(info.DynamicPartitionsInfo).Textf(" %s/META/", targetFilesDir.String()) + } else { + ctx.ModuleErrorf("Super partition %s does set SuperImageProvider\n", superPartition.Name()) + } + } + +} + +// A partial implementation of make's $PRODUCT_OUT/misc_info.txt +// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=5894?q=misc_info.txt%20f:build%2Fmake%2Fcore%2FMakefile&ss=android%2Fplatform%2Fsuperproject%2Fmain +// This file is subsequently used by add_img_to_target_files to create additioanl metadata files like apex_info.pb +// TODO (b/399788119): Complete the migration of misc_info.txt +func (a *androidDevice) addMiscInfo(ctx android.ModuleContext) android.Path { + builder := android.NewRuleBuilder(pctx, ctx) + miscInfo := android.PathForModuleOut(ctx, "misc_info.txt") + builder.Command(). + Textf("rm -f %s", miscInfo). + Textf("&& echo recovery_api_version=%s >> %s", ctx.Config().VendorConfig("recovery").String("recovery_api_version"), miscInfo). + Textf("&& echo fstab_version=%s >> %s", ctx.Config().VendorConfig("recovery").String("recovery_fstab_version"), miscInfo). + ImplicitOutput(miscInfo) + + if a.partitionProps.Recovery_partition_name == nil { + builder.Command().Textf("echo no_recovery=true >> %s", miscInfo) + } + fsInfos := a.getFsInfos(ctx) + for _, partition := range android.SortedKeys(fsInfos) { + if fsInfos[partition].UseAvb { + builder.Command().Textf("echo 'avb_%s_hashtree_enable=true' >> %s", partition, miscInfo) + } + } + if len(a.partitionProps.Vbmeta_partitions) > 0 { + builder.Command(). + Textf("echo avb_enable=true >> %s", miscInfo). + Textf("&& echo avb_building_vbmeta_image=true >> %s", miscInfo). + Textf("&& echo avb_avbtool=avbtool >> %s", miscInfo) + } + if a.partitionProps.Boot_partition_name != nil { + builder.Command().Textf("echo boot_images=boot.img >> %s", miscInfo) + } + + if a.partitionProps.Super_partition_name != nil { + superPartition := ctx.GetDirectDepProxyWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag) + if info, ok := android.OtherModuleProvider(ctx, superPartition, SuperImageProvider); ok { + // cat dynamic_partition_info.txt + builder.Command().Text("cat").Input(info.DynamicPartitionsInfo).Textf(" >> %s", miscInfo) + } else { + ctx.ModuleErrorf("Super partition %s does set SuperImageProvider\n", superPartition.Name()) + } + } + bootImgNames := []*string{ + a.partitionProps.Boot_partition_name, + a.partitionProps.Init_boot_partition_name, + a.partitionProps.Vendor_boot_partition_name, + } + for _, bootImgName := range bootImgNames { + if bootImgName == nil { + continue + } + + bootImg := ctx.GetDirectDepProxyWithTag(proptools.String(bootImgName), filesystemDepTag) + bootImgInfo, _ := android.OtherModuleProvider(ctx, bootImg, BootimgInfoProvider) + // cat avb_ metadata of the boot images + builder.Command().Text("cat").Input(bootImgInfo.PropFileForMiscInfo).Textf(" >> %s", miscInfo) + } + + builder.Build("misc_info", "Building misc_info") + + return miscInfo +} + +// addImgToTargetFiles invokes `add_img_to_target_files` and creates the following files in META/ +// - apex_info.pb +// - care_map.pb +// - vbmeta_digest.txt +func (a *androidDevice) addImgToTargetFiles(ctx android.ModuleContext, builder *android.RuleBuilder, targetFilesDir string) { + mkbootimg := ctx.Config().HostToolPath(ctx, "mkbootimg") + builder.Command(). + Textf("PATH=%s:$PATH", ctx.Config().HostToolDir()). + Textf("MKBOOTIMG=%s", mkbootimg). + Implicit(mkbootimg). + BuiltTool("add_img_to_target_files"). + Flag("-a -v -p"). + Flag(ctx.Config().HostToolDir()). + Text(targetFilesDir) +} + +type ApexKeyPathInfo struct { + ApexKeyPath android.Path +} + +var ApexKeyPathInfoProvider = blueprint.NewProvider[ApexKeyPathInfo]() + +func (a *androidDevice) generateFilesystemConfigForTargetFiles(ctx android.ModuleContext, builder *android.RuleBuilder, stagingDirTimestamp android.Path, targetFilesDir, stagingDir, filename string) { + fsConfigOut := android.PathForModuleOut(ctx, filename) + ctx.Build(pctx, android.BuildParams{ + Rule: fsConfigRule, + Implicit: stagingDirTimestamp, + Output: fsConfigOut, + Args: map[string]string{ + "rootDir": stagingDir, + "prefix": "", + }, + }) + builder.Command().Textf("cp").Input(fsConfigOut).Textf(" %s/META/", targetFilesDir) } // Filenames for the partition specific fs_config files. @@ -635,3 +883,121 @@ func (a *androidDevice) setVbmetaPhonyTargets(ctx android.ModuleContext) { } } } + +func (a *androidDevice) getKernel(ctx android.ModuleContext) android.Path { + if a.partitionProps.Boot_partition_name != nil { + bootImg := ctx.GetDirectDepProxyWithTag(proptools.String(a.partitionProps.Boot_partition_name), filesystemDepTag) + bootImgInfo, _ := android.OtherModuleProvider(ctx, bootImg, BootimgInfoProvider) + return bootImgInfo.Kernel + } + return nil +} + +// Gets the kernel version and configs from the actual kernel file itself. Roughly equivalent to +// this make code: https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=5443;drc=c0b66fc59de069e06ce0ffd703d4d21613be30c6 +// However, it is a simplified version of that make code. Differences include: +// - Not handling BOARD_KERNEL_CONFIG_FILE because BOARD_KERNEL_CONFIG_FILE was never used. +// - Not unpacking the bootimage, as we should be able to just always export the kernel directly +// in the BootimgInfo. We don't currently support prebuilt boot images, but even if we add that +// in the future, it can be done in a prebuilt_bootimage module type that still exports the same +// BootimgInfo. +// - We don't print a warning and output '<unknown-kernel>' to kernel_version_for_uffd_gc.txt +// because we expect the kernel to always be present. If it's not, we will get an error that +// kernel_version_for_uffd_gc.txt doesn't exist. This may require later tweaking to the +// dexpreopt rules so that they don't attempt to access that file in builds that don't have +// a kernel. +func (a *androidDevice) extractKernelVersionAndConfigs(ctx android.ModuleContext) (android.Path, android.Path) { + kernel := a.getKernel(ctx) + // If there's no kernel, don't create kernel version / kernel config files. Reverse dependencies + // on those files have to account for this, for example by disabling dexpreopt in unbundled + // builds. + if kernel == nil { + return nil, nil + } + + lz4tool := ctx.Config().HostToolPath(ctx, "lz4") + + extractedVersionFile := android.PathForModuleOut(ctx, "kernel_version.txt") + extractedConfigsFile := android.PathForModuleOut(ctx, "kernel_configs.txt") + builder := android.NewRuleBuilder(pctx, ctx) + builder.Command().BuiltTool("extract_kernel"). + Flag("--tools lz4:"+lz4tool.String()).Implicit(lz4tool). + FlagWithInput("--input ", kernel). + FlagWithOutput("--output-release ", extractedVersionFile). + FlagWithOutput("--output-configs ", extractedConfigsFile). + Textf(`&& printf "\n" >> %s`, extractedVersionFile) + + if specifiedVersion := proptools.String(a.deviceProps.Kernel_version); specifiedVersion != "" { + specifiedVersionFile := android.PathForModuleOut(ctx, "specified_kernel_version.txt") + android.WriteFileRule(ctx, specifiedVersionFile, specifiedVersion) + builder.Command().Text("diff -q"). + Input(specifiedVersionFile). + Input(extractedVersionFile). + Textf(`|| (echo "Specified kernel version '$(cat %s)' does not match actual kernel version '$(cat %s)'"; exit 1)`, specifiedVersionFile, extractedVersionFile) + } + + builder.Build("extract_kernel_info", "Extract kernel version and configs") + + if proptools.Bool(a.deviceProps.Main_device) && !ctx.Config().KatiEnabled() { + if ctx.Config().EnableUffdGc() == "default" { + kernelVersionFile := android.PathForOutput(ctx, "dexpreopt/kernel_version_for_uffd_gc.txt") + ctx.Build(pctx, android.BuildParams{ + Rule: android.CpIfChanged, + Input: extractedVersionFile, + Output: kernelVersionFile, + }) + } + + ctx.DistForGoal("droid_targets", extractedVersionFile) + } + + return extractedVersionFile, extractedConfigsFile +} + +func (a *androidDevice) buildApkCertsInfo(ctx android.ModuleContext, allInstalledModules []android.Module) android.Path { + // TODO (spandandas): Add compressed + formatLine := func(cert java.Certificate, name, partition string) string { + pem := cert.AndroidMkString() + var key string + if cert.Key == nil { + key = "" + } else { + key = cert.Key.String() + } + return fmt.Sprintf(`name="%s" certificate="%s" private_key="%s" partition="%s"`, name, pem, key, partition) + } + + apkCerts := []string{} + for _, installedModule := range allInstalledModules { + partition := "" + if commonInfo, ok := android.OtherModuleProvider(ctx, installedModule, android.CommonModuleInfoProvider); ok { + partition = commonInfo.PartitionTag + } else { + ctx.ModuleErrorf("%s does not set CommonModuleInfoKey", installedModule.Name()) + } + if info, ok := android.OtherModuleProvider(ctx, installedModule, java.AppInfoProvider); ok { + apkCerts = append(apkCerts, formatLine(info.Certificate, info.InstallApkName+".apk", partition)) + } else if info, ok := android.OtherModuleProvider(ctx, installedModule, java.AppInfosProvider); ok { + for _, certInfo := range info { + // Partition information of apk-in-apex is not exported to the legacy Make packaging system. + // Hardcode the partition to "system" + apkCerts = append(apkCerts, formatLine(certInfo.Certificate, certInfo.InstallApkName+".apk", "system")) + } + } else if info, ok := android.OtherModuleProvider(ctx, installedModule, java.RuntimeResourceOverlayInfoProvider); ok { + apkCerts = append(apkCerts, formatLine(info.Certificate, info.OutputFile.Base(), partition)) + } + } + slices.Sort(apkCerts) // sort by name + fsInfos := a.getFsInfos(ctx) + if fsInfos["system"].HasFsverity { + defaultPem, defaultKey := ctx.Config().DefaultAppCertificate(ctx) + apkCerts = append(apkCerts, formatLine(java.Certificate{Pem: defaultPem, Key: defaultKey}, "BuildManifest.apk", "system")) + if info, ok := fsInfos["system_ext"]; ok && info.HasFsverity { + apkCerts = append(apkCerts, formatLine(java.Certificate{Pem: defaultPem, Key: defaultKey}, "BuildManifestSystemExt.apk", "system_ext")) + } + } + + apkCertsInfo := android.PathForModuleOut(ctx, "apkcerts.txt") + android.WriteFileRuleVerbatim(ctx, apkCertsInfo, strings.Join(apkCerts, "\n")+"\n") + return apkCertsInfo +} diff --git a/filesystem/avb_add_hash_footer.go b/filesystem/avb_add_hash_footer.go index c1e03cb62..327a41fda 100644 --- a/filesystem/avb_add_hash_footer.go +++ b/filesystem/avb_add_hash_footer.go @@ -210,6 +210,9 @@ var _ android.SourceFileProducer = (*avbAddHashFooter)(nil) // Implements android.SourceFileProducer func (a *avbAddHashFooter) Srcs() android.Paths { + if a.output == nil { + return nil + } return append(android.Paths{}, a.output) } diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go index effbd6542..7959365e8 100644 --- a/filesystem/bootimg.go +++ b/filesystem/bootimg.go @@ -201,7 +201,8 @@ func (b *bootimg) GenerateAndroidBuildActions(ctx android.ModuleContext) { return } - unsignedOutput := b.buildBootImage(ctx, b.getKernelPath(ctx)) + kernelPath := b.getKernelPath(ctx) + unsignedOutput := b.buildBootImage(ctx, kernelPath) output := unsignedOutput if proptools.Bool(b.properties.Use_avb) { @@ -212,7 +213,7 @@ func (b *bootimg) GenerateAndroidBuildActions(ctx android.ModuleContext) { case "default": output = b.signImage(ctx, unsignedOutput) case "make_legacy": - output = b.addAvbFooter(ctx, unsignedOutput, b.getKernelPath(ctx)) + output = b.addAvbFooter(ctx, unsignedOutput, kernelPath) default: ctx.PropertyErrorf("avb_mode", `Unknown value for avb_mode, expected "default" or "make_legacy", got: %q`, *b.properties.Avb_mode) } @@ -235,12 +236,14 @@ func (b *bootimg) GenerateAndroidBuildActions(ctx android.ModuleContext) { } // Set BootimgInfo for building target_files.zip + dtbPath := b.getDtbPath(ctx) android.SetProvider(ctx, BootimgInfoProvider, BootimgInfo{ - Cmdline: b.properties.Cmdline, - Kernel: b.getKernelPath(ctx), - Dtb: b.getDtbPath(ctx), - Bootconfig: b.getBootconfigPath(ctx), - Output: output, + Cmdline: b.properties.Cmdline, + Kernel: kernelPath, + Dtb: dtbPath, + Bootconfig: b.getBootconfigPath(ctx), + Output: output, + PropFileForMiscInfo: b.buildPropFileForMiscInfo(ctx), }) extractedPublicKey := android.PathForModuleOut(ctx, b.partitionName()+".avbpubkey") @@ -263,16 +266,32 @@ func (b *bootimg) GenerateAndroidBuildActions(ctx android.ModuleContext) { PublicKey: extractedPublicKey, Output: output, }) + + // Dump compliance metadata + complianceMetadataInfo := ctx.ComplianceMetadataInfo() + prebuiltFilesCopied := make([]string, 0) + if kernelPath != nil { + prebuiltFilesCopied = append(prebuiltFilesCopied, kernelPath.String()+":kernel") + } + if dtbPath != nil { + prebuiltFilesCopied = append(prebuiltFilesCopied, dtbPath.String()+":dtb.img") + } + complianceMetadataInfo.SetPrebuiltFilesCopied(prebuiltFilesCopied) + + if ramdisk := proptools.String(b.properties.Ramdisk_module); ramdisk != "" { + buildComplianceMetadata(ctx, bootimgRamdiskDep) + } } var BootimgInfoProvider = blueprint.NewProvider[BootimgInfo]() type BootimgInfo struct { - Cmdline []string - Kernel android.Path - Dtb android.Path - Bootconfig android.Path - Output android.Path + Cmdline []string + Kernel android.Path + Dtb android.Path + Bootconfig android.Path + Output android.Path + PropFileForMiscInfo android.Path } func (b *bootimg) getKernelPath(ctx android.ModuleContext) android.Path { @@ -491,6 +510,25 @@ func (b *bootimg) buildPropFile(ctx android.ModuleContext) (android.Path, androi return propFile, deps } +func (b *bootimg) buildPropFileForMiscInfo(ctx android.ModuleContext) android.Path { + var sb strings.Builder + addStr := func(name string, value string) { + fmt.Fprintf(&sb, "%s=%s\n", name, value) + } + + bootImgType := proptools.String(b.properties.Boot_image_type) + addStr("avb_"+bootImgType+"_add_hash_footer_args", "TODO(b/398036609)") + if b.properties.Avb_private_key != nil { + addStr("avb_"+bootImgType+"_algorithm", proptools.StringDefault(b.properties.Avb_algorithm, "SHA256_RSA4096")) + addStr("avb_"+bootImgType+"_key_path", android.PathForModuleSrc(ctx, proptools.String(b.properties.Avb_private_key)).String()) + addStr("avb_"+bootImgType+"_rollback_index_location", strconv.Itoa(proptools.Int(b.properties.Avb_rollback_index_location))) + } + + propFile := android.PathForModuleOut(ctx, "prop_for_misc_info") + android.WriteFileRuleVerbatim(ctx, propFile, sb.String()) + return propFile +} + var _ android.AndroidMkEntriesProvider = (*bootimg)(nil) // Implements android.AndroidMkEntriesProvider diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index 28eb36d1e..b8548805b 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -30,6 +30,7 @@ import ( "android/soong/linkerconfig" "github.com/google/blueprint" + "github.com/google/blueprint/depset" "github.com/google/blueprint/proptools" ) @@ -208,11 +209,6 @@ type FilesystemProperties struct { // Install aconfig_flags.pb file for the modules installed in this partition. Gen_aconfig_flags_pb *bool - // List of names of other filesystem partitions to import their aconfig flags from. - // This is used for the system partition to import system_ext's aconfig flags, as currently - // those are considered one "container": aosp/3261300 - Import_aconfig_flags_from []string - Fsverity fsverityProperties // If this property is set to true, the filesystem will call ctx.UncheckedModule(), causing @@ -359,9 +355,6 @@ func (f *filesystem) DepsMutator(ctx android.BottomUpMutatorContext) { if f.properties.Android_filesystem_deps.System_ext != nil { ctx.AddDependency(ctx.Module(), interPartitionDependencyTag, proptools.String(f.properties.Android_filesystem_deps.System_ext)) } - for _, partition := range f.properties.Import_aconfig_flags_from { - ctx.AddDependency(ctx.Module(), importAconfigDependencyTag, partition) - } for _, partition := range f.properties.Include_files_of { ctx.AddDependency(ctx.Module(), interPartitionInstallDependencyTag, partition) } @@ -382,6 +375,20 @@ func (fs fsType) IsUnknown() bool { return fs == unknown } +// Type string that build_image.py accepts. +func (t fsType) String() string { + switch t { + // TODO(372522486): add more types like f2fs, erofs, etc. + case ext4Type: + return "ext4" + case erofsType: + return "erofs" + case f2fsType: + return "f2fs" + } + panic(fmt.Errorf("unsupported fs type %d", t)) +} + type InstalledFilesStruct struct { Txt android.Path Json android.Path @@ -432,8 +439,8 @@ type FilesystemInfo struct { FullInstallPaths []FullInstallPathInfo - // Installed files list - InstalledFiles InstalledFilesStruct + // Installed files dep set of this module and its dependency filesystem modules + InstalledFilesDepSet depset.DepSet[InstalledFilesStruct] // Path to compress hints file for erofs filesystems // This will be nil for other fileystems like ext4 @@ -444,6 +451,10 @@ type FilesystemInfo struct { FilesystemConfig android.Path Owners []InstalledModuleInfo + + UseAvb bool + + HasFsverity bool } // FullInstallPathInfo contains information about the "full install" paths of all the files @@ -474,11 +485,7 @@ type FullInstallPathInfo struct { var FilesystemProvider = blueprint.NewProvider[FilesystemInfo]() -type FilesystemDefaultsInfo struct { - // Identifies which partition this is for //visibility:any_system_image (and others) visibility - // checks, and will be used in the future for API surface checks. - PartitionType string -} +type FilesystemDefaultsInfo struct{} var FilesystemDefaultsInfoProvider = blueprint.NewProvider[FilesystemDefaultsInfo]() @@ -551,13 +558,13 @@ func (f *filesystem) ModifyPackagingSpec(ps *android.PackagingSpec) { } } -func buildInstalledFiles(ctx android.ModuleContext, partition string, rootDir android.Path, image android.Path) (txt android.ModuleOutPath, json android.ModuleOutPath) { +func buildInstalledFiles(ctx android.ModuleContext, partition string, rootDir android.Path, image android.Path) InstalledFilesStruct { fileName := "installed-files" if len(partition) > 0 { fileName += fmt.Sprintf("-%s", partition) } - txt = android.PathForModuleOut(ctx, fmt.Sprintf("%s.txt", fileName)) - json = android.PathForModuleOut(ctx, fmt.Sprintf("%s.json", fileName)) + txt := android.PathForModuleOut(ctx, fmt.Sprintf("%s.txt", fileName)) + json := android.PathForModuleOut(ctx, fmt.Sprintf("%s.json", fileName)) ctx.Build(pctx, android.BuildParams{ Rule: installedFilesJsonRule, @@ -576,7 +583,10 @@ func buildInstalledFiles(ctx android.ModuleContext, partition string, rootDir an Description: "Installed file list txt", }) - return txt, json + return InstalledFilesStruct{ + Txt: txt, + Json: json, + } } func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -659,11 +669,15 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { fileListFile := android.PathForModuleOut(ctx, "fileList") android.WriteFileRule(ctx, fileListFile, f.installedFilesList()) - partitionName := f.partitionName() - if partitionName == "system" { - partitionName = "" + var partitionNameForInstalledFiles string + switch f.partitionName() { + case "system": + partitionNameForInstalledFiles = "" + case "vendor_ramdisk": + partitionNameForInstalledFiles = "vendor-ramdisk" + default: + partitionNameForInstalledFiles = f.partitionName() } - installedFileTxt, installedFileJson := buildInstalledFiles(ctx, partitionName, rootDir, f.output) var erofsCompressHints android.Path if f.properties.Erofs.Compress_hints != nil { @@ -684,18 +698,25 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { BuildImagePropFileDeps: buildImagePropFileDeps, SpecsForSystemOther: f.systemOtherFiles(ctx), FullInstallPaths: fullInstallPaths, - InstalledFiles: InstalledFilesStruct{ - Txt: installedFileTxt, - Json: installedFileJson, - }, + InstalledFilesDepSet: depset.New( + depset.POSTORDER, + []InstalledFilesStruct{buildInstalledFiles(ctx, partitionNameForInstalledFiles, rootDir, f.output)}, + includeFilesInstalledFiles(ctx), + ), ErofsCompressHints: erofsCompressHints, SelinuxFc: f.selinuxFc, FilesystemConfig: f.generateFilesystemConfig(ctx, rootDir, rebasedDir), Owners: f.gatherOwners(specs), + UseAvb: proptools.Bool(f.properties.Use_avb), + HasFsverity: f.properties.Fsverity.Inputs.GetOrDefault(ctx, nil) != nil, } android.SetProvider(ctx, FilesystemProvider, fsInfo) + android.SetProvider(ctx, android.PartitionTypeInfoProvider, android.PartitionTypeInfo{ + PartitionType: f.PartitionType(), + }) + f.fileListFile = fileListFile if proptools.Bool(f.properties.Unchecked_module) { @@ -703,6 +724,14 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { } f.setVbmetaPartitionProvider(ctx) + + // Dump metadata that can not be done in android/compliance-metadata.go + complianceMetadataInfo := ctx.ComplianceMetadataInfo() + filesContained := make([]string, 0, len(fullInstallPaths)) + for _, file := range fullInstallPaths { + filesContained = append(filesContained, file.FullInstallPath.String()) + } + complianceMetadataInfo.SetFilesContained(filesContained) } func (f *filesystem) fileystemStagingDirTimestamp(ctx android.ModuleContext) android.WritablePath { @@ -822,11 +851,12 @@ func validatePartitionType(ctx android.ModuleContext, p partition) { } ctx.VisitDirectDepsProxyWithTag(android.DefaultsDepTag, func(m android.ModuleProxy) { - if fdm, ok := android.OtherModuleProvider(ctx, m, FilesystemDefaultsInfoProvider); ok { - if p.PartitionType() != fdm.PartitionType { + if _, ok := android.OtherModuleProvider(ctx, m, FilesystemDefaultsInfoProvider); ok { + partitionInfo := android.OtherModuleProviderOrDefault(ctx, m, android.PartitionTypeInfoProvider) + if p.PartitionType() != partitionInfo.PartitionType { ctx.PropertyErrorf("partition_type", "%s doesn't match with the partition type %s of the filesystem default module %s", - p.PartitionType(), fdm.PartitionType, m.Name()) + p.PartitionType(), partitionInfo.PartitionType, m.Name()) } } }) @@ -886,13 +916,24 @@ func (f *filesystem) buildNonDepsFiles( builder.Command().Text("mkdir -p").Text(filepath.Dir(dst.String())) builder.Command().Text("ln -sf").Text(proptools.ShellEscape(target)).Text(dst.String()) f.appendToEntry(ctx, dst) - // Only add the fullInstallPath logic for files in the rebased dir. The root dir - // is harder to install to. - if strings.HasPrefix(name, rebasedPrefix) { + // Add the fullInstallPath logic for files in the rebased dir, and for non-rebased files in "system" partition + // the fullInstallPath is changed to "root" which aligns to the behavior in Make. + if f.PartitionType() == "system" { + installPath := android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), strings.TrimPrefix(name, rebasedPrefix)) + if !strings.HasPrefix(name, rebasedPrefix) { + installPath = android.PathForModuleInPartitionInstall(ctx, "root", name) + } *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{ - FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), strings.TrimPrefix(name, rebasedPrefix)), + FullInstallPath: installPath, SymlinkTarget: target, }) + } else { + if strings.HasPrefix(name, rebasedPrefix) { + *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{ + FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), strings.TrimPrefix(name, rebasedPrefix)), + SymlinkTarget: target, + }) + } } } @@ -1004,21 +1045,7 @@ func (f *filesystem) buildPropFile(ctx android.ModuleContext) (android.Path, and deps = append(deps, path) } - // Type string that build_image.py accepts. - fsTypeStr := func(t fsType) string { - switch t { - // TODO(372522486): add more types like f2fs, erofs, etc. - case ext4Type: - return "ext4" - case erofsType: - return "erofs" - case f2fsType: - return "f2fs" - } - panic(fmt.Errorf("unsupported fs type %v", t)) - } - - addStr("fs_type", fsTypeStr(f.fsType(ctx))) + addStr("fs_type", f.fsType(ctx).String()) addStr("mount_point", proptools.StringDefault(f.properties.Mount_point, "/")) addStr("use_dynamic_partition_size", "true") addPath("ext_mkuserimg", ctx.Config().HostToolPath(ctx, "mkuserimg_mke2fs")) @@ -1037,28 +1064,7 @@ func (f *filesystem) buildPropFile(ctx android.ModuleContext) (android.Path, and addPath("avb_key_path", key) } addStr("partition_name", f.partitionName()) - avb_add_hashtree_footer_args := "" - if !proptools.BoolDefault(f.properties.Use_fec, true) { - avb_add_hashtree_footer_args += " --do_not_generate_fec" - } - hashAlgorithm := proptools.StringDefault(f.properties.Avb_hash_algorithm, "sha256") - avb_add_hashtree_footer_args += " --hash_algorithm " + hashAlgorithm - if f.properties.Rollback_index != nil { - rollbackIndex := proptools.Int(f.properties.Rollback_index) - if rollbackIndex < 0 { - ctx.PropertyErrorf("rollback_index", "Rollback index must be non-negative") - } - avb_add_hashtree_footer_args += " --rollback_index " + strconv.Itoa(rollbackIndex) - } - avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.os_version:%s", f.partitionName(), ctx.Config().PlatformVersionLastStable()) - // We're not going to add BuildFingerPrintFile as a dep. If it changed, it's likely because - // the build number changed, and we don't want to trigger rebuilds solely based on the build - // number. - avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.fingerprint:{CONTENTS_OF:%s}", f.partitionName(), ctx.Config().BuildFingerprintFile(ctx)) - if f.properties.Security_patch != nil && proptools.String(f.properties.Security_patch) != "" { - avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.security_patch:%s", f.partitionName(), proptools.String(f.properties.Security_patch)) - } - addStr("avb_add_hashtree_footer_args", avb_add_hashtree_footer_args) + addStr("avb_add_hashtree_footer_args", f.getAvbAddHashtreeFooterArgs(ctx)) } if f.properties.File_contexts != nil && f.properties.Precompiled_file_contexts != nil { @@ -1107,7 +1113,7 @@ func (f *filesystem) buildPropFile(ctx android.ModuleContext) (android.Path, and addStr("f2fs_sparse_flag", "-S") } } - f.checkFsTypePropertyError(ctx, fst, fsTypeStr(fst)) + f.checkFsTypePropertyError(ctx, fst, fst.String()) if f.properties.Partition_size != nil { addStr("partition_size", strconv.FormatInt(*f.properties.Partition_size, 10)) @@ -1138,6 +1144,31 @@ func (f *filesystem) buildPropFile(ctx android.ModuleContext) (android.Path, and return propFile, deps } +func (f *filesystem) getAvbAddHashtreeFooterArgs(ctx android.ModuleContext) string { + avb_add_hashtree_footer_args := "" + if !proptools.BoolDefault(f.properties.Use_fec, true) { + avb_add_hashtree_footer_args += " --do_not_generate_fec" + } + hashAlgorithm := proptools.StringDefault(f.properties.Avb_hash_algorithm, "sha256") + avb_add_hashtree_footer_args += " --hash_algorithm " + hashAlgorithm + if f.properties.Rollback_index != nil { + rollbackIndex := proptools.Int(f.properties.Rollback_index) + if rollbackIndex < 0 { + ctx.PropertyErrorf("rollback_index", "Rollback index must be non-negative") + } + avb_add_hashtree_footer_args += " --rollback_index " + strconv.Itoa(rollbackIndex) + } + avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.os_version:%s", f.partitionName(), ctx.Config().PlatformVersionLastStable()) + // We're not going to add BuildFingerPrintFile as a dep. If it changed, it's likely because + // the build number changed, and we don't want to trigger rebuilds solely based on the build + // number. + avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.fingerprint:{CONTENTS_OF:%s}", f.partitionName(), ctx.Config().BuildFingerprintFile(ctx)) + if f.properties.Security_patch != nil && proptools.String(f.properties.Security_patch) != "" { + avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.security_patch:%s", f.partitionName(), proptools.String(f.properties.Security_patch)) + } + return avb_add_hashtree_footer_args +} + // This method checks if there is any property set for the fstype(s) other than // the current fstype. func (f *filesystem) checkFsTypePropertyError(ctx android.ModuleContext, t fsType, fs string) { @@ -1171,6 +1202,15 @@ func includeFilesRootDir(ctx android.ModuleContext) (rootDirs android.Paths, par return rootDirs, partitions } +func includeFilesInstalledFiles(ctx android.ModuleContext) (ret []depset.DepSet[InstalledFilesStruct]) { + ctx.VisitDirectDepsWithTag(interPartitionInstallDependencyTag, func(m android.Module) { + if fsProvider, ok := android.OtherModuleProvider(ctx, m, FilesystemProvider); ok { + ret = append(ret, fsProvider.InstalledFilesDepSet) + } + }) + return +} + func (f *filesystem) buildCpioImage( ctx android.ModuleContext, builder *android.RuleBuilder, @@ -1413,7 +1453,8 @@ var _ partition = (*filesystemDefaults)(nil) func (f *filesystemDefaults) GenerateAndroidBuildActions(ctx android.ModuleContext) { validatePartitionType(ctx, f) - android.SetProvider(ctx, FilesystemDefaultsInfoProvider, FilesystemDefaultsInfo{ + android.SetProvider(ctx, FilesystemDefaultsInfoProvider, FilesystemDefaultsInfo{}) + android.SetProvider(ctx, android.PartitionTypeInfoProvider, android.PartitionTypeInfo{ PartitionType: f.PartitionType(), }) } @@ -1432,7 +1473,7 @@ func (f *filesystem) getLibsForLinkerConfig(ctx android.ModuleContext) ([]androi deps := f.gatherFilteredPackagingSpecs(ctx) ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool { - if !android.OtherModuleProviderOrDefault(ctx, child, android.CommonModuleInfoKey).Enabled { + if !android.OtherModulePointerProviderOrDefault(ctx, child, android.CommonModuleInfoProvider).Enabled { return false } for _, ps := range android.OtherModuleProviderOrDefault( @@ -1453,7 +1494,7 @@ func (f *filesystem) getLibsForLinkerConfig(ctx android.ModuleContext) ([]androi var requireModules []android.ModuleProxy ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool { - if !android.OtherModuleProviderOrDefault(ctx, child, android.CommonModuleInfoKey).Enabled { + if !android.OtherModulePointerProviderOrDefault(ctx, child, android.CommonModuleInfoProvider).Enabled { return false } _, parentInPackage := modulesInPackageByModule[parent] @@ -1525,10 +1566,11 @@ func addAutogeneratedRroDeps(ctx android.BottomUpMutatorContext) { }) } -func (f *filesystem) MakeVars(ctx android.MakeVarsModuleContext) { +func (f *filesystem) MakeVars(ctx android.MakeVarsModuleContext) []android.ModuleMakeVarsValue { if f.Name() == ctx.Config().SoongDefinedSystemImage() { - ctx.StrictRaw("SOONG_DEFINED_SYSTEM_IMAGE_PATH", f.output.String()) + return []android.ModuleMakeVarsValue{{"SOONG_DEFINED_SYSTEM_IMAGE_PATH", f.output.String()}} } + return nil } func setCommonFilesystemInfo(ctx android.ModuleContext, m Filesystem) { diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go index 6d0b49016..bf7f5b64b 100644 --- a/filesystem/filesystem_test.go +++ b/filesystem/filesystem_test.go @@ -723,26 +723,47 @@ cc_library { // override_android_* modules implicitly override their base module. // If both of these are listed in `deps`, the base module should not be installed. +// Also, required deps should be updated too. func TestOverrideModulesInDeps(t *testing.T) { result := fixture.RunTestWithBp(t, ` + cc_library_shared { + name: "libfoo", + stl: "none", + system_shared_libs: [], + } + cc_library_shared { + name: "libbar", + stl: "none", + system_shared_libs: [], + } android_filesystem { name: "myfilesystem", + deps: ["myapp"], + } + android_filesystem { + name: "myfilesystem_overridden", deps: ["myapp", "myoverrideapp"], } android_app { name: "myapp", platform_apis: true, + required: ["libfoo"], } override_android_app { name: "myoverrideapp", base: "myapp", + required: ["libbar"], } `) partition := result.ModuleForTests(t, "myfilesystem", "android_common") fileList := android.ContentFromFileRuleForTests(t, result.TestContext, partition.Output("fileList")) - android.AssertStringEquals(t, "filesystem with override app", "app/myoverrideapp/myoverrideapp.apk\n", fileList) + android.AssertStringEquals(t, "filesystem without override app", "app/myapp/myapp.apk\nlib64/libfoo.so\n", fileList) + + overriddenPartition := result.ModuleForTests(t, "myfilesystem_overridden", "android_common") + overriddenFileList := android.ContentFromFileRuleForTests(t, result.TestContext, overriddenPartition.Output("fileList")) + android.AssertStringEquals(t, "filesystem with override app", "app/myoverrideapp/myoverrideapp.apk\nlib64/libbar.so\n", overriddenFileList) } func TestRamdiskPartitionSetsDevNodes(t *testing.T) { diff --git a/filesystem/super_image.go b/filesystem/super_image.go index 58c938aee..cd7df027a 100644 --- a/filesystem/super_image.go +++ b/filesystem/super_image.go @@ -78,6 +78,10 @@ type SuperImageProperties struct { // specified we default to COW version 2 in update_engine for backwards compatibility Cow_version *int64 } + // Whether the super image will be disted in the update package + Super_image_in_update_package *bool + // Whether a super_empty.img should be created + Create_super_empty *bool } type PartitionGroupsInfo struct { @@ -114,6 +118,10 @@ type SuperImageInfo struct { // Mapping from the sub-partition type to its re-exported FileSystemInfo providers from the // sub-partitions. SubImageInfo map[string]FilesystemInfo + + DynamicPartitionsInfo android.Path + + SuperEmptyImage android.Path } var SuperImageProvider = blueprint.NewProvider[SuperImageInfo]() @@ -159,7 +167,7 @@ func (s *superImage) DepsMutator(ctx android.BottomUpMutatorContext) { } func (s *superImage) GenerateAndroidBuildActions(ctx android.ModuleContext) { - miscInfo, deps, subImageInfos := s.buildMiscInfo(ctx) + miscInfo, deps, subImageInfos := s.buildMiscInfo(ctx, false) builder := android.NewRuleBuilder(pctx, ctx) output := android.PathForModuleOut(ctx, s.installFileName()) lpMake := ctx.Config().HostToolPath(ctx, "lpmake") @@ -172,90 +180,52 @@ func (s *superImage) GenerateAndroidBuildActions(ctx android.ModuleContext) { Implicits(deps). Output(output) builder.Build("build_super_image", fmt.Sprintf("Creating super image %s", s.BaseModuleName())) + var superEmptyImage android.WritablePath + if proptools.Bool(s.properties.Create_super_empty) { + superEmptyImageBuilder := android.NewRuleBuilder(pctx, ctx) + superEmptyImage = android.PathForModuleOut(ctx, "super_empty.img") + superEmptyMiscInfo, superEmptyDeps, _ := s.buildMiscInfo(ctx, true) + if superEmptyDeps != nil { + ctx.ModuleErrorf("TODO: Handle additional deps when building super_empty.img") + } + superEmptyImageBuilder.Command().Textf("PATH=%s:\\$PATH", lpMakeDir). + BuiltTool("build_super_image"). + Text("-v"). + Input(superEmptyMiscInfo). + Implicit(lpMake). + Output(superEmptyImage) + superEmptyImageBuilder.Build("build_super_empty_image", fmt.Sprintf("Creating super empty image %s", s.BaseModuleName())) + } android.SetProvider(ctx, SuperImageProvider, SuperImageInfo{ - SuperImage: output, - SubImageInfo: subImageInfos, + SuperImage: output, + SubImageInfo: subImageInfos, + DynamicPartitionsInfo: s.generateDynamicPartitionsInfo(ctx), + SuperEmptyImage: superEmptyImage, }) ctx.SetOutputFiles([]android.Path{output}, "") ctx.CheckbuildFile(output) + + buildComplianceMetadata(ctx, subImageDepTag) } func (s *superImage) installFileName() string { return "super.img" } -func (s *superImage) buildMiscInfo(ctx android.ModuleContext) (android.Path, android.Paths, map[string]FilesystemInfo) { +func (s *superImage) buildMiscInfo(ctx android.ModuleContext, superEmpty bool) (android.Path, android.Paths, map[string]FilesystemInfo) { var miscInfoString strings.Builder + partitionList := s.dumpDynamicPartitionInfo(ctx, &miscInfoString) addStr := func(name string, value string) { miscInfoString.WriteString(name) miscInfoString.WriteRune('=') miscInfoString.WriteString(value) miscInfoString.WriteRune('\n') } - - addStr("build_super_partition", "true") - addStr("use_dynamic_partitions", strconv.FormatBool(proptools.Bool(s.properties.Use_dynamic_partitions))) - if proptools.Bool(s.properties.Retrofit) { - addStr("dynamic_partition_retrofit", "true") - } - addStr("lpmake", "lpmake") - addStr("super_metadata_device", proptools.String(s.properties.Metadata_device)) - if len(s.properties.Block_devices) > 0 { - addStr("super_block_devices", strings.Join(s.properties.Block_devices, " ")) - } - addStr("super_partition_size", strconv.Itoa(proptools.Int(s.properties.Size))) - // TODO: In make, there's more complicated logic than just this surrounding super_*_device_size - addStr("super_super_device_size", strconv.Itoa(proptools.Int(s.properties.Size))) - var groups, partitionList []string - for _, groupInfo := range s.properties.Partition_groups { - groups = append(groups, groupInfo.Name) - partitionList = append(partitionList, groupInfo.PartitionList...) - addStr("super_"+groupInfo.Name+"_group_size", groupInfo.GroupSize) - addStr("super_"+groupInfo.Name+"_partition_list", strings.Join(groupInfo.PartitionList, " ")) - } - initialPartitionListLen := len(partitionList) - partitionList = android.SortedUniqueStrings(partitionList) - if len(partitionList) != initialPartitionListLen { - ctx.ModuleErrorf("Duplicate partitions found in the partition_groups property") - } - addStr("super_partition_groups", strings.Join(groups, " ")) - addStr("dynamic_partition_list", strings.Join(partitionList, " ")) - addStr("ab_update", strconv.FormatBool(proptools.Bool(s.properties.Ab_update))) - - if proptools.Bool(s.properties.Virtual_ab.Enable) { - addStr("virtual_ab", "true") - if proptools.Bool(s.properties.Virtual_ab.Retrofit) { - addStr("virtual_ab_retrofit", "true") - } - addStr("virtual_ab_compression", strconv.FormatBool(proptools.Bool(s.properties.Virtual_ab.Compression))) - if s.properties.Virtual_ab.Compression_method != nil { - matched, _ := regexp.MatchString("^[a-zA-Z0-9_-]+$", *s.properties.Virtual_ab.Compression_method) - if !matched { - ctx.PropertyErrorf("virtual_ab.compression_method", "compression_method cannot have special characters") - } - addStr("virtual_ab_compression_method", *s.properties.Virtual_ab.Compression_method) - } - if s.properties.Virtual_ab.Compression_factor != nil { - addStr("virtual_ab_compression_factor", strconv.FormatInt(*s.properties.Virtual_ab.Compression_factor, 10)) - } - if s.properties.Virtual_ab.Cow_version != nil { - addStr("virtual_ab_cow_version", strconv.FormatInt(*s.properties.Virtual_ab.Cow_version, 10)) - } - - } else { - if s.properties.Virtual_ab.Retrofit != nil { - ctx.PropertyErrorf("virtual_ab.retrofit", "This property cannot be set when virtual_ab is disabled") - } - if s.properties.Virtual_ab.Compression != nil { - ctx.PropertyErrorf("virtual_ab.compression", "This property cannot be set when virtual_ab is disabled") - } - if s.properties.Virtual_ab.Compression_method != nil { - ctx.PropertyErrorf("virtual_ab.compression_method", "This property cannot be set when virtual_ab is disabled") - } - if s.properties.Virtual_ab.Compression_factor != nil { - ctx.PropertyErrorf("virtual_ab.compression_factor", "This property cannot be set when virtual_ab is disabled") - } + if superEmpty { + miscInfo := android.PathForModuleOut(ctx, "misc_info_super_empty.txt") + android.WriteFileRule(ctx, miscInfo, miscInfoString.String()) + return miscInfo, nil, nil } subImageInfo := make(map[string]FilesystemInfo) @@ -346,3 +316,95 @@ func (s *superImage) buildMiscInfo(ctx android.ModuleContext) (android.Path, and android.WriteFileRule(ctx, miscInfo, miscInfoString.String(), missingPartitionErrorMessageFile) return miscInfo, deps, subImageInfo } + +func (s *superImage) dumpDynamicPartitionInfo(ctx android.ModuleContext, sb *strings.Builder) []string { + addStr := func(name string, value string) { + sb.WriteString(name) + sb.WriteRune('=') + sb.WriteString(value) + sb.WriteRune('\n') + } + + addStr("use_dynamic_partitions", strconv.FormatBool(proptools.Bool(s.properties.Use_dynamic_partitions))) + if proptools.Bool(s.properties.Retrofit) { + addStr("dynamic_partition_retrofit", "true") + } + addStr("lpmake", "lpmake") + addStr("build_super_partition", "true") + if proptools.Bool(s.properties.Create_super_empty) { + addStr("build_super_empty_partition", "true") + } + addStr("super_metadata_device", proptools.String(s.properties.Metadata_device)) + if len(s.properties.Block_devices) > 0 { + addStr("super_block_devices", strings.Join(s.properties.Block_devices, " ")) + } + // TODO: In make, there's more complicated logic than just this surrounding super_*_device_size + addStr("super_super_device_size", strconv.Itoa(proptools.Int(s.properties.Size))) + var groups, partitionList []string + for _, groupInfo := range s.properties.Partition_groups { + groups = append(groups, groupInfo.Name) + partitionList = append(partitionList, groupInfo.PartitionList...) + } + addStr("dynamic_partition_list", strings.Join(android.SortedUniqueStrings(partitionList), " ")) + addStr("super_partition_groups", strings.Join(groups, " ")) + initialPartitionListLen := len(partitionList) + partitionList = android.SortedUniqueStrings(partitionList) + if len(partitionList) != initialPartitionListLen { + ctx.ModuleErrorf("Duplicate partitions found in the partition_groups property") + } + // Add Partition group info after adding `super_partition_groups` and `dynamic_partition_list` + for _, groupInfo := range s.properties.Partition_groups { + addStr("super_"+groupInfo.Name+"_group_size", groupInfo.GroupSize) + addStr("super_"+groupInfo.Name+"_partition_list", strings.Join(groupInfo.PartitionList, " ")) + } + + if proptools.Bool(s.properties.Super_image_in_update_package) { + addStr("super_image_in_update_package", "true") + } + addStr("super_partition_size", strconv.Itoa(proptools.Int(s.properties.Size))) + + if proptools.Bool(s.properties.Virtual_ab.Enable) { + addStr("virtual_ab", "true") + if proptools.Bool(s.properties.Virtual_ab.Retrofit) { + addStr("virtual_ab_retrofit", "true") + } + addStr("virtual_ab_compression", strconv.FormatBool(proptools.Bool(s.properties.Virtual_ab.Compression))) + if s.properties.Virtual_ab.Compression_method != nil { + matched, _ := regexp.MatchString("^[a-zA-Z0-9_-]+$", *s.properties.Virtual_ab.Compression_method) + if !matched { + ctx.PropertyErrorf("virtual_ab.compression_method", "compression_method cannot have special characters") + } + addStr("virtual_ab_compression_method", *s.properties.Virtual_ab.Compression_method) + } + if s.properties.Virtual_ab.Cow_version != nil { + addStr("virtual_ab_cow_version", strconv.FormatInt(*s.properties.Virtual_ab.Cow_version, 10)) + } + if s.properties.Virtual_ab.Compression_factor != nil { + addStr("virtual_ab_compression_factor", strconv.FormatInt(*s.properties.Virtual_ab.Compression_factor, 10)) + } + + } else { + if s.properties.Virtual_ab.Retrofit != nil { + ctx.PropertyErrorf("virtual_ab.retrofit", "This property cannot be set when virtual_ab is disabled") + } + if s.properties.Virtual_ab.Compression != nil { + ctx.PropertyErrorf("virtual_ab.compression", "This property cannot be set when virtual_ab is disabled") + } + if s.properties.Virtual_ab.Compression_method != nil { + ctx.PropertyErrorf("virtual_ab.compression_method", "This property cannot be set when virtual_ab is disabled") + } + if s.properties.Virtual_ab.Compression_factor != nil { + ctx.PropertyErrorf("virtual_ab.compression_factor", "This property cannot be set when virtual_ab is disabled") + } + } + + return partitionList +} + +func (s *superImage) generateDynamicPartitionsInfo(ctx android.ModuleContext) android.Path { + var contents strings.Builder + s.dumpDynamicPartitionInfo(ctx, &contents) + dynamicPartitionsInfo := android.PathForModuleOut(ctx, "dynamic_partitions_info.txt") + android.WriteFileRuleVerbatim(ctx, dynamicPartitionsInfo, contents.String()) + return dynamicPartitionsInfo +} diff --git a/filesystem/system_other.go b/filesystem/system_other.go index 5309e9012..cbfd78b5b 100644 --- a/filesystem/system_other.go +++ b/filesystem/system_other.go @@ -172,9 +172,10 @@ func (m *systemOtherImage) GenerateAndroidBuildActions(ctx android.ModuleContext builder.Build("build_system_other_hermetic", "build system other") fsInfo := FilesystemInfo{ - Output: output, - OutputHermetic: outputHermetic, - RootDir: stagingDir, + Output: output, + OutputHermetic: outputHermetic, + RootDir: stagingDir, + FilesystemConfig: m.generateFilesystemConfig(ctx, stagingDir, stagingDirTimestamp), } android.SetProvider(ctx, FilesystemProvider, fsInfo) @@ -183,6 +184,20 @@ func (m *systemOtherImage) GenerateAndroidBuildActions(ctx android.ModuleContext ctx.CheckbuildFile(output) } +func (s *systemOtherImage) generateFilesystemConfig(ctx android.ModuleContext, stagingDir, stagingDirTimestamp android.Path) android.Path { + out := android.PathForModuleOut(ctx, "filesystem_config.txt") + ctx.Build(pctx, android.BuildParams{ + Rule: fsConfigRule, + Input: stagingDirTimestamp, // assemble the staging directory + Output: out, + Args: map[string]string{ + "rootDir": stagingDir.String(), + "prefix": "system/", + }, + }) + return out +} + func (f *systemOtherImage) propFileForHermeticImg(ctx android.ModuleContext, builder *android.RuleBuilder, inputPropFile android.Path) android.Path { propFilePinnedTimestamp := android.PathForModuleOut(ctx, "for_target_files", "prop") builder.Command().Textf("cat").Input(inputPropFile).Flag(">").Output(propFilePinnedTimestamp). diff --git a/fsgen/boot_imgs.go b/fsgen/boot_imgs.go index 58ebcc4ba..0ba0a90dd 100644 --- a/fsgen/boot_imgs.go +++ b/fsgen/boot_imgs.go @@ -69,6 +69,7 @@ func createBootImage(ctx android.LoadHookContext, dtbImg dtbImg) bool { ctx.CreateModule( filesystem.BootimgFactory, &filesystem.BootimgProperties{ + Boot_image_type: proptools.StringPtr("boot"), Kernel_prebuilt: proptools.StringPtr(":" + kernelFilegroupName), Header_version: proptools.StringPtr(partitionVariables.BoardBootHeaderVersion), Partition_size: partitionSize, diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go index 3d83706a3..b73fb219f 100644 --- a/fsgen/filesystem_creator.go +++ b/fsgen/filesystem_creator.go @@ -340,6 +340,26 @@ func (f *filesystemCreator) createReleaseToolsFilegroup(ctx android.LoadHookCont return releaseToolsFilegroupName, true } +func (f *filesystemCreator) createFastbootInfoFilegroup(ctx android.LoadHookContext) (string, bool) { + fastbootInfoFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BoardFastbootInfoFile + if fastbootInfoFile == "" { + return "", false + } + + fastbootInfoFilegroupName := generatedModuleName(ctx.Config(), "fastboot") + filegroupProps := &struct { + Name *string + Srcs []string + Visibility []string + }{ + Name: proptools.StringPtr(fastbootInfoFilegroupName), + Srcs: []string{fastbootInfoFile}, + Visibility: []string{"//visibility:public"}, + } + ctx.CreateModuleInDirectory(android.FileGroupFactory, ".", filegroupProps) + return fastbootInfoFilegroupName, true +} + func (f *filesystemCreator) createDeviceModule( ctx android.LoadHookContext, partitions allGeneratedPartitionData, @@ -405,6 +425,7 @@ func (f *filesystemCreator) createDeviceModule( Ab_ota_postinstall_config: ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaPostInstallConfig, Ramdisk_node_list: proptools.StringPtr(":ramdisk_node_list"), Android_info: proptools.StringPtr(":" + generatedModuleName(ctx.Config(), "android_info.prop{.txt}")), + Kernel_version: ctx.Config().ProductVariables().BoardKernelVersion, } if bootloader, ok := f.createBootloaderFilegroup(ctx); ok { @@ -413,6 +434,9 @@ func (f *filesystemCreator) createDeviceModule( if releaseTools, ok := f.createReleaseToolsFilegroup(ctx); ok { deviceProps.Releasetools_extension = proptools.StringPtr(":" + releaseTools) } + if fastbootInfo, ok := f.createFastbootInfoFilegroup(ctx); ok { + deviceProps.FastbootInfo = proptools.StringPtr(":" + fastbootInfo) + } ctx.CreateModule(filesystem.AndroidDeviceFactory, baseProps, partitionProps, deviceProps) } @@ -469,10 +493,6 @@ func partitionSpecificFsProps(ctx android.EarlyModuleContext, partitions allGene fsProps.Base_dir = proptools.StringPtr("system") fsProps.Dirs = proptools.NewSimpleConfigurable(commonPartitionDirs) fsProps.Security_patch = proptools.StringPtr(ctx.Config().PlatformSecurityPatch()) - - if systemExtName := partitions.nameForType("system_ext"); systemExtName != "" { - fsProps.Import_aconfig_flags_from = []string{systemExtName} - } fsProps.Stem = proptools.StringPtr("system.img") case "system_ext": if partitionVars.ProductFsverityGenerateMetadata { @@ -485,6 +505,7 @@ func partitionSpecificFsProps(ctx android.EarlyModuleContext, partitions allGene } fsProps.Security_patch = proptools.StringPtr(ctx.Config().PlatformSecurityPatch()) fsProps.Stem = proptools.StringPtr("system_ext.img") + fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true) case "product": fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true) fsProps.Android_filesystem_deps.System = proptools.StringPtr(partitions.nameForType("system")) @@ -833,19 +854,29 @@ func (f *filesystemCreator) createVendorBuildProp(ctx android.LoadHookContext) { Product_config *string Android_info *string Licenses []string + Dist android.Dist }{ Name: proptools.StringPtr(generatedModuleName(ctx.Config(), "vendor-build.prop")), Vendor: proptools.BoolPtr(true), Stem: proptools.StringPtr("build.prop"), Product_config: proptools.StringPtr(":product_config"), Android_info: proptools.StringPtr(":" + generatedModuleName(ctx.Config(), "android_info.prop")), - Licenses: []string{"Android-Apache-2.0"}, + Dist: android.Dist{ + Targets: []string{"droidcore-unbundled"}, + Dest: proptools.StringPtr("build.prop-vendor"), + }, + Licenses: []string{"Android-Apache-2.0"}, } vendorBuildProp := ctx.CreateModule( android.BuildPropFactory, vendorBuildProps, ) - vendorBuildProp.HideFromMake() + // We don't want this to conflict with the make-built vendor build.prop, but unfortunately + // calling HideFromMake() prevents disting files, even in soong-only mode. So only call + // HideFromMake() on soong+make builds. + if ctx.Config().KatiEnabled() { + vendorBuildProp.HideFromMake() + } } func createRecoveryBuildProp(ctx android.LoadHookContext) string { diff --git a/fsgen/filesystem_creator_test.go b/fsgen/filesystem_creator_test.go index 418e48bcd..81236a0a1 100644 --- a/fsgen/filesystem_creator_test.go +++ b/fsgen/filesystem_creator_test.go @@ -287,6 +287,8 @@ func TestPrebuiltEtcModuleGen(t *testing.T) { "some/non/existing/file.txt:system/etc/file.txt", "device/sample/etc/apns-full-conf.xml:product/etc/apns-conf.xml:google", "device/sample/etc/apns-full-conf.xml:product/etc/apns-conf-2.xml", + "device/sample/etc/apns-full-conf.xml:system/foo/file.txt", + "device/sample/etc/apns-full-conf.xml:system/foo/apns-full-conf.xml", } config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.PartitionQualifiedVariables = map[string]android.PartitionQualifiedVariablesType{ @@ -364,15 +366,25 @@ func TestPrebuiltEtcModuleGen(t *testing.T) { eval := generatedModule0.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext)) android.AssertBoolEquals( t, - "module expected to set correct srcs and dsts properties", + "module expected to set correct srcs property", true, checkModuleProp(generatedModule0, func(actual interface{}) bool { if p, ok := actual.(*etc.PrebuiltEtcProperties); ok { srcs := p.Srcs.GetOrDefault(eval, nil) - dsts := p.Dsts.GetOrDefault(eval, nil) return len(srcs) == 1 && - srcs[0] == "apns-full-conf.xml" && - len(dsts) == 1 && + srcs[0] == "apns-full-conf.xml" + } + return false + }), + ) + android.AssertBoolEquals( + t, + "module expected to set correct dsts property", + true, + checkModuleProp(generatedModule0, func(actual interface{}) bool { + if p, ok := actual.(*etc.PrebuiltDstsProperties); ok { + dsts := p.Dsts.GetOrDefault(eval, nil) + return len(dsts) == 1 && dsts[0] == "apns-conf.xml" } return false @@ -383,15 +395,25 @@ func TestPrebuiltEtcModuleGen(t *testing.T) { eval = generatedModule1.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext)) android.AssertBoolEquals( t, - "module expected to set correct srcs and dsts properties", + "module expected to set correct srcs property", true, checkModuleProp(generatedModule1, func(actual interface{}) bool { if p, ok := actual.(*etc.PrebuiltEtcProperties); ok { srcs := p.Srcs.GetOrDefault(eval, nil) - dsts := p.Dsts.GetOrDefault(eval, nil) return len(srcs) == 1 && - srcs[0] == "apns-full-conf.xml" && - len(dsts) == 1 && + srcs[0] == "apns-full-conf.xml" + } + return false + }), + ) + android.AssertBoolEquals( + t, + "module expected to set correct dsts property", + true, + checkModuleProp(generatedModule1, func(actual interface{}) bool { + if p, ok := actual.(*etc.PrebuiltDstsProperties); ok { + dsts := p.Dsts.GetOrDefault(eval, nil) + return len(dsts) == 1 && dsts[0] == "apns-conf-2.xml" } return false diff --git a/fsgen/fsgen_mutators.go b/fsgen/fsgen_mutators.go index 9b25e77a5..4f3d2a750 100644 --- a/fsgen/fsgen_mutators.go +++ b/fsgen/fsgen_mutators.go @@ -105,12 +105,14 @@ func createFsGenState(ctx android.LoadHookContext, generatedPrebuiltEtcModuleNam "libgsi": defaultDepCandidateProps(ctx.Config()), "llndk.libraries.txt": defaultDepCandidateProps(ctx.Config()), "logpersist.start": defaultDepCandidateProps(ctx.Config()), + "notice_xml_system": defaultDepCandidateProps(ctx.Config()), "update_engine_sideload": defaultDepCandidateProps(ctx.Config()), // keep-sorted end }, "vendor": { "fs_config_files_vendor": defaultDepCandidateProps(ctx.Config()), "fs_config_dirs_vendor": defaultDepCandidateProps(ctx.Config()), + "notice_xml_vendor": defaultDepCandidateProps(ctx.Config()), generatedModuleName(ctx.Config(), "vendor-build.prop"): defaultDepCandidateProps(ctx.Config()), }, "odm": { @@ -118,34 +120,41 @@ func createFsGenState(ctx android.LoadHookContext, generatedPrebuiltEtcModuleNam // https://cs.android.com/android/_/android/platform/build/+/e4849e87ab660b59a6501b3928693db065ee873b:tools/fs_config/Android.mk;l=34;drc=8d6481b92c4b4e9b9f31a61545b6862090fcc14b;bpv=1;bpt=0 "fs_config_files_odm": defaultDepCandidateProps(ctx.Config()), "fs_config_dirs_odm": defaultDepCandidateProps(ctx.Config()), + "notice_xml_odm": defaultDepCandidateProps(ctx.Config()), + }, + "product": { + "notice_xml_product": defaultDepCandidateProps(ctx.Config()), }, - "product": {}, "system_ext": { // VNDK apexes are automatically included. // This hardcoded list will need to be updated if `PRODUCT_EXTRA_VNDK_VERSIONS` is updated. // https://cs.android.com/android/_/android/platform/build/+/adba533072b00c53ac0f198c550a3cbd7a00e4cd:core/main.mk;l=984;bpv=1;bpt=0;drc=174db7b179592cf07cbfd2adb0119486fda911e7 - "com.android.vndk.v30": defaultDepCandidateProps(ctx.Config()), - "com.android.vndk.v31": defaultDepCandidateProps(ctx.Config()), - "com.android.vndk.v32": defaultDepCandidateProps(ctx.Config()), - "com.android.vndk.v33": defaultDepCandidateProps(ctx.Config()), - "com.android.vndk.v34": defaultDepCandidateProps(ctx.Config()), + "com.android.vndk.v30": defaultDepCandidateProps(ctx.Config()), + "com.android.vndk.v31": defaultDepCandidateProps(ctx.Config()), + "com.android.vndk.v32": defaultDepCandidateProps(ctx.Config()), + "com.android.vndk.v33": defaultDepCandidateProps(ctx.Config()), + "com.android.vndk.v34": defaultDepCandidateProps(ctx.Config()), + "notice_xml_system_ext": defaultDepCandidateProps(ctx.Config()), }, "userdata": {}, "system_dlkm": { // these are phony required deps of the phony fs_config_dirs_nonsystem "fs_config_dirs_system_dlkm": defaultDepCandidateProps(ctx.Config()), "fs_config_files_system_dlkm": defaultDepCandidateProps(ctx.Config()), + "notice_xml_system_dlkm": defaultDepCandidateProps(ctx.Config()), // build props are automatically added to `ALL_DEFAULT_INSTALLED_MODULES` "system_dlkm-build.prop": defaultDepCandidateProps(ctx.Config()), }, "vendor_dlkm": { "fs_config_dirs_vendor_dlkm": defaultDepCandidateProps(ctx.Config()), "fs_config_files_vendor_dlkm": defaultDepCandidateProps(ctx.Config()), + "notice_xml_vendor_dlkm": defaultDepCandidateProps(ctx.Config()), "vendor_dlkm-build.prop": defaultDepCandidateProps(ctx.Config()), }, "odm_dlkm": { "fs_config_dirs_odm_dlkm": defaultDepCandidateProps(ctx.Config()), "fs_config_files_odm_dlkm": defaultDepCandidateProps(ctx.Config()), + "notice_xml_odm_dlkm": defaultDepCandidateProps(ctx.Config()), "odm_dlkm-build.prop": defaultDepCandidateProps(ctx.Config()), }, "ramdisk": {}, @@ -178,6 +187,10 @@ func createFsGenState(ctx android.LoadHookContext, generatedPrebuiltEtcModuleNam (*fsGenState.fsDeps["product"])["system_other_avbpubkey"] = defaultDepCandidateProps(ctx.Config()) } + if len(ctx.Config().DeviceManifestFiles()) > 0 { + (*fsGenState.fsDeps["vendor"])["vendor_manifest.xml"] = defaultDepCandidateProps(ctx.Config()) + } + // Add common resources `prebuilt_res` module as dep of recovery partition (*fsGenState.fsDeps["recovery"])[fmt.Sprintf("recovery-resources-common-%s", getDpi(ctx))] = defaultDepCandidateProps(ctx.Config()) (*fsGenState.fsDeps["recovery"])[getRecoveryFontModuleName(ctx)] = defaultDepCandidateProps(ctx.Config()) diff --git a/fsgen/prebuilt_etc_modules_gen.go b/fsgen/prebuilt_etc_modules_gen.go index e028b1d5a..df361976e 100644 --- a/fsgen/prebuilt_etc_modules_gen.go +++ b/fsgen/prebuilt_etc_modules_gen.go @@ -164,7 +164,6 @@ type prebuiltModuleProperties struct { Ramdisk *bool Srcs []string - Dsts []string No_full_install *bool @@ -199,6 +198,7 @@ var ( "etc/dsp": etc.PrebuiltDSPFactory, "etc/firmware": etc.PrebuiltFirmwareFactory, "firmware": etc.PrebuiltFirmwareFactory, + "gpu": etc.PrebuiltGPUFactory, "first_stage_ramdisk": etc.PrebuiltFirstStageRamdiskFactory, "fonts": etc.PrebuiltFontFactory, "framework": etc.PrebuiltFrameworkFactory, @@ -210,6 +210,7 @@ var ( "optee": etc.PrebuiltOpteeFactory, "overlay": etc.PrebuiltOverlayFactory, "priv-app": etc.PrebuiltPrivAppFactory, + "radio": etc.PrebuiltRadioFactory, "sbin": etc.PrebuiltSbinFactory, "system": etc.PrebuiltSystemFactory, "res": etc.PrebuiltResFactory, @@ -225,6 +226,7 @@ var ( "usr/idc": etc.PrebuiltUserIdcFactory, "vendor": etc.PrebuiltVendorFactory, "vendor_dlkm": etc.PrebuiltVendorDlkmFactory, + "vendor_overlay": etc.PrebuiltVendorOverlayFactory, "wallpaper": etc.PrebuiltWallpaperFactory, "wlc_upt": etc.PrebuiltWlcUptFactory, } @@ -299,6 +301,7 @@ func createPrebuiltEtcModulesInDirectory(ctx android.LoadHookContext, partition, etcInstallPathKey = etcInstallPath } } + moduleFactory := etcInstallPathToFactoryList[etcInstallPathKey] relDestDirFromInstallDirBase, _ := filepath.Rel(etcInstallPathKey, destDir) for fileIndex := range maxLen { @@ -348,15 +351,23 @@ func createPrebuiltEtcModulesInDirectory(ctx android.LoadHookContext, partition, }) } } else { + // If dsts property has to be set and the selected module type is prebuilt_root, + // use prebuilt_any instead. + if etcInstallPathKey == "" { + moduleFactory = etc.PrebuiltAnyFactory + } modulePropsPtr.Srcs = srcBaseFiles - dsts := []string{} + dsts := proptools.NewConfigurable[[]string](nil, nil) for _, installBaseFile := range installBaseFiles { - dsts = append(dsts, filepath.Join(relDestDirFromInstallDirBase, installBaseFile)) + dsts.AppendSimpleValue([]string{filepath.Join(relDestDirFromInstallDirBase, installBaseFile)}) } - modulePropsPtr.Dsts = dsts + + propsList = append(propsList, &etc.PrebuiltDstsProperties{ + Dsts: dsts, + }) } - ctx.CreateModuleInDirectory(etcInstallPathToFactoryList[etcInstallPathKey], srcDir, propsList...) + ctx.CreateModuleInDirectory(moduleFactory, srcDir, propsList...) moduleNames = append(moduleNames, moduleName) } diff --git a/fsgen/super_img.go b/fsgen/super_img.go index 569f780fd..1d610f63c 100644 --- a/fsgen/super_img.go +++ b/fsgen/super_img.go @@ -40,11 +40,13 @@ func createSuperImage( } superImageProps := &filesystem.SuperImageProperties{ - Metadata_device: proptools.StringPtr(partitionVars.BoardSuperPartitionMetadataDevice), - Block_devices: partitionVars.BoardSuperPartitionBlockDevices, - Ab_update: proptools.BoolPtr(partitionVars.AbOtaUpdater), - Retrofit: proptools.BoolPtr(partitionVars.ProductRetrofitDynamicPartitions), - Use_dynamic_partitions: proptools.BoolPtr(partitionVars.ProductUseDynamicPartitions), + Metadata_device: proptools.StringPtr(partitionVars.BoardSuperPartitionMetadataDevice), + Block_devices: partitionVars.BoardSuperPartitionBlockDevices, + Ab_update: proptools.BoolPtr(partitionVars.AbOtaUpdater), + Retrofit: proptools.BoolPtr(partitionVars.ProductRetrofitDynamicPartitions), + Use_dynamic_partitions: proptools.BoolPtr(partitionVars.ProductUseDynamicPartitions), + Super_image_in_update_package: proptools.BoolPtr(partitionVars.BoardSuperImageInUpdatePackage), + Create_super_empty: proptools.BoolPtr(partitionVars.BuildingSuperEmptyImage), } if partitionVars.ProductVirtualAbOta { superImageProps.Virtual_ab.Enable = proptools.BoolPtr(true) diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go index 83ccd89ae..f08378d67 100644 --- a/fuzz/fuzz_common.go +++ b/fuzz/fuzz_common.go @@ -22,6 +22,7 @@ import ( "sort" "strings" + "github.com/google/blueprint" "github.com/google/blueprint/proptools" "android/soong/android" @@ -309,14 +310,14 @@ func (automatically_route_to AutomaticallyRouteTo) isValidAutomaticallyRouteTo() return false } -func IsValidConfig(fuzzModule FuzzPackagedModule, moduleName string) bool { - var config = fuzzModule.FuzzProperties.Fuzz_config +func IsValidConfig(fuzzModule *FuzzPackagedModuleInfo, moduleName string) bool { + var config = fuzzModule.FuzzConfig if config != nil { if !config.Vector.isValidVector() { panic(fmt.Errorf("Invalid vector in fuzz config in %s", moduleName)) } - if !config.Service_privilege.isValidServicePrivilege() { + if !config.ServicePrivilege.isValidServicePrivilege() { panic(fmt.Errorf("Invalid service_privilege in fuzz config in %s", moduleName)) } @@ -324,15 +325,15 @@ func IsValidConfig(fuzzModule FuzzPackagedModule, moduleName string) bool { panic(fmt.Errorf("Invalid users (user_data) in fuzz config in %s", moduleName)) } - if !config.Fuzzed_code_usage.isValidFuzzedCodeUsage() { + if !config.FuzzedCodeUsage.isValidFuzzedCodeUsage() { panic(fmt.Errorf("Invalid fuzzed_code_usage in fuzz config in %s", moduleName)) } - if !config.Automatically_route_to.isValidAutomaticallyRouteTo() { + if !config.AutomaticallyRouteTo.isValidAutomaticallyRouteTo() { panic(fmt.Errorf("Invalid automatically_route_to in fuzz config in %s", moduleName)) } - if !config.Use_platform_libs.isValidUsePlatformLibs() { + if !config.UsePlatformLibs.isValidUsePlatformLibs() { panic(fmt.Errorf("Invalid use_platform_libs in fuzz config in %s", moduleName)) } } @@ -451,6 +452,62 @@ type FuzzPackagedModule struct { Data android.Paths } +type FuzzConfigInfo struct { + Vector Vector + // How privileged the service being fuzzed is. + ServicePrivilege ServicePrivilege + // Whether the service being fuzzed handles data from multiple users or only + // a single one. + Users UserData + // Specifies the use state of the code being fuzzed. This state factors into + // how an issue is handled. + FuzzedCodeUsage FuzzedCodeUsage + // Which team to route this to, if it should be routed automatically. + AutomaticallyRouteTo AutomaticallyRouteTo + // Specifies libs used to initialize ART (java only, 'use_none' for no initialization) + UsePlatformLibs UsePlatformLibs + // Specify whether to enable continuous fuzzing on devices. Defaults to true. + FuzzOnHaikuDevice bool + // Specify whether to enable continuous fuzzing on host. Defaults to true. + FuzzOnHaikuHost bool + // Specifies whether fuzz target should check presubmitted code changes for crashes. + // Defaults to false. + UseForPresubmit bool +} +type FuzzPackagedModuleInfo struct { + FuzzConfig *FuzzConfigInfo + Dictionary android.Path + Corpus android.Paths + Config android.Path + Data android.Paths +} + +var FuzzPackagedModuleInfoProvider = blueprint.NewProvider[FuzzPackagedModuleInfo]() + +func SetFuzzPackagedModuleInfo(ctx android.ModuleContext, fm *FuzzPackagedModule) { + info := FuzzPackagedModuleInfo{ + Dictionary: fm.Dictionary, + Config: fm.Config, + Corpus: fm.Corpus, + Data: fm.Data, + } + if fm.FuzzProperties.Fuzz_config != nil { + info.FuzzConfig = &FuzzConfigInfo{ + Vector: fm.FuzzProperties.Fuzz_config.Vector, + ServicePrivilege: fm.FuzzProperties.Fuzz_config.Service_privilege, + Users: fm.FuzzProperties.Fuzz_config.Users, + FuzzedCodeUsage: fm.FuzzProperties.Fuzz_config.Fuzzed_code_usage, + AutomaticallyRouteTo: fm.FuzzProperties.Fuzz_config.Automatically_route_to, + FuzzOnHaikuDevice: BoolDefault(fm.FuzzProperties.Fuzz_config.Fuzz_on_haiku_device, true), + FuzzOnHaikuHost: BoolDefault(fm.FuzzProperties.Fuzz_config.Fuzz_on_haiku_host, true), + UsePlatformLibs: fm.FuzzProperties.Fuzz_config.Use_platform_libs, + UseForPresubmit: BoolDefault(fm.FuzzProperties.Fuzz_config.Use_for_presubmit, false), + } + } + + android.SetProvider(ctx, FuzzPackagedModuleInfoProvider, info) +} + func GetFramework(ctx android.LoadHookContext, lang Lang) Framework { framework := ctx.Config().Getenv("FUZZ_FRAMEWORK") @@ -509,7 +566,9 @@ func IsValid(ctx android.ConfigurableEvaluatorContext, fuzzModule FuzzModule) bo return true } -func (s *FuzzPackager) PackageArtifacts(ctx android.SingletonContext, module android.Module, fuzzModule FuzzPackagedModule, archDir android.OutputPath, builder *android.RuleBuilder) []FileToZip { +// TODO(b/397766191): Change the signature to take ModuleProxy +// Please only access the module's internal data through providers. +func (s *FuzzPackager) PackageArtifacts(ctx android.SingletonContext, module android.Module, fuzzModule *FuzzPackagedModuleInfo, archDir android.OutputPath, builder *android.RuleBuilder) []FileToZip { // Package the corpora into a zipfile. var files []FileToZip if fuzzModule.Corpus != nil { @@ -548,7 +607,9 @@ func (s *FuzzPackager) PackageArtifacts(ctx android.SingletonContext, module and return files } -func (s *FuzzPackager) BuildZipFile(ctx android.SingletonContext, module android.Module, fuzzModule FuzzPackagedModule, files []FileToZip, builder *android.RuleBuilder, archDir android.OutputPath, archString string, hostOrTargetString string, archOs ArchOs, archDirs map[ArchOs][]FileToZip) ([]FileToZip, bool) { +// TODO(b/397766191): Change the signature to take ModuleProxy +// Please only access the module's internal data through providers. +func (s *FuzzPackager) BuildZipFile(ctx android.SingletonContext, module android.Module, fuzzModule *FuzzPackagedModuleInfo, files []FileToZip, builder *android.RuleBuilder, archDir android.OutputPath, archString string, hostOrTargetString string, archOs ArchOs, archDirs map[ArchOs][]FileToZip) ([]FileToZip, bool) { fuzzZip := archDir.Join(ctx, module.Name()+".zip") command := builder.Command().BuiltTool("soong_zip"). @@ -570,10 +631,10 @@ func (s *FuzzPackager) BuildZipFile(ctx android.SingletonContext, module android builder.Build("create-"+fuzzZip.String(), "Package "+module.Name()+" for "+archString+"-"+hostOrTargetString) - if config := fuzzModule.FuzzProperties.Fuzz_config; config != nil { - if strings.Contains(hostOrTargetString, "host") && !BoolDefault(config.Fuzz_on_haiku_host, true) { + if config := fuzzModule.FuzzConfig; config != nil { + if strings.Contains(hostOrTargetString, "host") && !config.FuzzOnHaikuHost { return archDirs[archOs], false - } else if !strings.Contains(hostOrTargetString, "host") && !BoolDefault(config.Fuzz_on_haiku_device, true) { + } else if !strings.Contains(hostOrTargetString, "host") && !config.FuzzOnHaikuDevice { return archDirs[archOs], false } } diff --git a/genrule/genrule.go b/genrule/genrule.go index 6bd1fcc8d..710ec9555 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -112,8 +112,8 @@ func (t hostToolDependencyTag) AllowDisabledModuleDependency(target android.Modu func (t hostToolDependencyTag) AllowDisabledModuleDependencyProxy( ctx android.OtherModuleProviderContext, target android.ModuleProxy) bool { - return android.OtherModuleProviderOrDefault( - ctx, target, android.CommonModuleInfoKey).ReplacedByPrebuilt + return android.OtherModulePointerProviderOrDefault( + ctx, target, android.CommonModuleInfoProvider).ReplacedByPrebuilt } var _ android.AllowDisabledModuleDependency = (*hostToolDependencyTag)(nil) @@ -353,7 +353,7 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) { if h, ok := android.OtherModuleProvider(ctx, module, android.HostToolProviderInfoProvider); ok { // A HostToolProvider provides the path to a tool, which will be copied // into the sandbox. - if !android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey).Enabled { + if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled { if ctx.Config().AllowMissingDependencies() { ctx.AddMissingDependencies([]string{tool}) } else { diff --git a/java/Android.bp b/java/Android.bp index 911af8336..99d9c38a6 100644 --- a/java/Android.bp +++ b/java/Android.bp @@ -78,6 +78,7 @@ bootstrap_go_package { "system_modules.go", "systemserver_classpath_fragment.go", "testing.go", + "tracereferences.go", "tradefed.go", ], testSrcs: [ diff --git a/java/aar.go b/java/aar.go index 976e4fcb1..ebada655f 100644 --- a/java/aar.go +++ b/java/aar.go @@ -219,11 +219,7 @@ func (p propagateRROEnforcementTransitionMutator) Mutate(ctx android.BottomUpMut func (a *aapt) useResourceProcessorBusyBox(ctx android.BaseModuleContext) bool { return BoolDefault(a.aaptProperties.Use_resource_processor, true) && // TODO(b/331641946): remove this when ResourceProcessorBusyBox supports generating shared libraries. - !slices.Contains(a.aaptProperties.Aaptflags, "--shared-lib") && - // Use the legacy resource processor in kythe builds. - // The legacy resource processor creates an R.srcjar, which kythe can use for generating crossrefs. - // TODO(b/354854007): Re-enable BusyBox in kythe builds - !ctx.Config().EmitXrefRules() + !slices.Contains(a.aaptProperties.Aaptflags, "--shared-lib") } func (a *aapt) filterProduct() string { @@ -945,6 +941,12 @@ type AndroidLibraryInfo struct { var AndroidLibraryInfoProvider = blueprint.NewProvider[AndroidLibraryInfo]() +type AARImportInfo struct { + // Empty for now +} + +var AARImportInfoProvider = blueprint.NewProvider[AARImportInfo]() + type AndroidLibrary struct { Library aapt @@ -1571,6 +1573,8 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { JniPackages: a.jniPackages, }) + android.SetProvider(ctx, AARImportInfoProvider, AARImportInfo{}) + ctx.SetOutputFiles([]android.Path{a.implementationAndResourcesJarFile}, "") ctx.SetOutputFiles([]android.Path{a.aarPath}, ".aar") diff --git a/java/app.go b/java/app.go index 17548e74a..553c65894 100644 --- a/java/app.go +++ b/java/app.go @@ -425,6 +425,10 @@ func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleCon } else { moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite") } + + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: a.appTestHelperAppProperties.Test_suites, + }) } func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -531,7 +535,7 @@ func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVer if _, ok := android.OtherModuleProvider(ctx, m, cc.CcInfoProvider); !ok { panic(fmt.Errorf("jni dependency is not a cc module: %v", m)) } - commonInfo, ok := android.OtherModuleProvider(ctx, m, android.CommonModuleInfoKey) + commonInfo, ok := android.OtherModuleProvider(ctx, m, android.CommonModuleInfoProvider) if !ok { panic(fmt.Errorf("jni dependency doesn't have CommonModuleInfo provider: %v", m)) } @@ -611,7 +615,7 @@ func getAconfigFilePaths(ctx android.ModuleContext) (aconfigTextFilePaths androi ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) { tag := ctx.OtherModuleDependencyTag(dep) switch tag { - case staticLibTag: + case staticLibTag, rroDepTag: if flagPackages, ok := android.OtherModuleProvider(ctx, dep, FlagsPackagesProvider); ok { aconfigTextFilePaths = append(aconfigTextFilePaths, flagPackages.AconfigTextFiles...) } @@ -1124,6 +1128,11 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { android.SetProvider(ctx, JavaInfoProvider, javaInfo) } + android.SetProvider(ctx, android.ApexBundleDepsDataProvider, android.ApexBundleDepsData{ + FlatListPath: a.FlatListPath(), + Updatable: a.Updatable(), + }) + moduleInfoJSON := ctx.ModuleInfoJSON() moduleInfoJSON.Class = []string{"APPS"} if !a.embeddedJniLibs { @@ -1170,7 +1179,7 @@ func collectAppDeps(ctx android.ModuleContext, app appDepsInterface, apkInApex := ctx.Module().(android.ApexModule).NotInPlatform() childLinkable, _ := android.OtherModuleProvider(ctx, child, cc.LinkableInfoProvider) parentIsLinkable := false - if ctx.EqualModules(ctx.Module(), parent) { + if android.EqualModules(ctx.Module(), parent) { parentLinkable, _ := ctx.Module().(cc.LinkableInterface) parentIsLinkable = parentLinkable != nil } else { @@ -1224,7 +1233,7 @@ func collectJniDeps(ctx android.ModuleContext, seenModulePaths := make(map[string]bool) ctx.WalkDepsProxy(func(module, parent android.ModuleProxy) bool { - if !android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey).Enabled { + if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled { return false } otherName := ctx.OtherModuleName(module) @@ -1244,7 +1253,7 @@ func collectJniDeps(ctx android.ModuleContext, } seenModulePaths[path.String()] = true - commonInfo := android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey) + commonInfo := android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider) if checkNativeSdkVersion && commonInfo.SdkVersion == "" { ctx.PropertyErrorf("jni_libs", "JNI dependency %q uses platform APIs, but this module does not", otherName) @@ -1282,13 +1291,13 @@ func collectJniDeps(ctx android.ModuleContext, } func (a *AndroidApp) WalkPayloadDeps(ctx android.BaseModuleContext, do android.PayloadDepsCallback) { - ctx.WalkDeps(func(child, parent android.Module) bool { + ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool { // TODO(ccross): Should this use android.DepIsInSameApex? Right now it is applying the android app // heuristics to every transitive dependency, when it should probably be using the heuristics of the // immediate parent. isExternal := !a.GetDepInSameApexChecker().OutgoingDepIsInSameApex(ctx.OtherModuleDependencyTag(child)) - if am, ok := child.(android.ApexModule); ok { - if !do(ctx, parent, am, isExternal) { + if am, ok := android.OtherModuleProvider(ctx, child, android.CommonModuleInfoProvider); ok && am.IsApexModule { + if !do(ctx, parent, child, isExternal) { return false } } @@ -1302,12 +1311,12 @@ func (a *AndroidApp) buildAppDependencyInfo(ctx android.ModuleContext) { } depsInfo := android.DepNameToDepInfoMap{} - a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from android.Module, to android.ApexModule, externalDep bool) bool { + a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool { depName := to.Name() // Skip dependencies that are only available to APEXes; they are developed with updatability // in mind and don't need manual approval. - if android.OtherModuleProviderOrDefault(ctx, to, android.CommonModuleInfoKey).NotAvailableForPlatform { + if android.OtherModulePointerProviderOrDefault(ctx, to, android.CommonModuleInfoProvider).NotAvailableForPlatform { return true } @@ -1317,7 +1326,7 @@ func (a *AndroidApp) buildAppDependencyInfo(ctx android.ModuleContext) { depsInfo[depName] = info } else { toMinSdkVersion := "(no version)" - if info, ok := android.OtherModuleProvider(ctx, to, android.CommonModuleInfoKey); ok && + if info, ok := android.OtherModuleProvider(ctx, to, android.CommonModuleInfoProvider); ok && !info.MinSdkVersion.IsPlatform && info.MinSdkVersion.ApiLevel != nil { toMinSdkVersion = info.MinSdkVersion.ApiLevel.String() } @@ -1698,6 +1707,10 @@ func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { moduleInfoJSON.AutoTestConfig = []string{"true"} } moduleInfoJSON.TestMainlineModules = append(moduleInfoJSON.TestMainlineModules, a.testProperties.Test_mainline_modules...) + + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: a.testProperties.Test_suites, + }) } func testcaseRel(paths android.Paths) []string { @@ -2204,3 +2217,7 @@ func setCommonAppInfo(appInfo *AppInfo, m androidApp) { appInfo.Certificate = m.Certificate() appInfo.PrivAppAllowlist = m.PrivAppAllowlist() } + +type AppInfos []AppInfo + +var AppInfosProvider = blueprint.NewProvider[AppInfos]() diff --git a/java/app_import.go b/java/app_import.go index 37c673ca0..c0e8171d5 100644 --- a/java/app_import.go +++ b/java/app_import.go @@ -177,7 +177,7 @@ type AndroidAppImportProperties struct { Prebuilt_info *string `android:"path"` // Path of extracted apk which is extracted from prebuilt apk. Use this extracted to import. - Extract_apk *string + Extract_apk proptools.Configurable[string] // Compress the output APK using gzip. Defaults to false. Compress_apk proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"` @@ -307,7 +307,7 @@ func (a *AndroidAppImport) uncompressEmbeddedJniLibs( func (a *AndroidAppImport) extractSubApk( ctx android.ModuleContext, inputPath android.Path, outputPath android.WritablePath) { - extractApkPath := *a.properties.Extract_apk + extractApkPath := a.properties.Extract_apk.GetOrDefault(ctx, "") ctx.Build(pctx, android.BuildParams{ Rule: extractApkRule, Input: inputPath, @@ -405,7 +405,7 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext // TODO: LOCAL_PACKAGE_SPLITS srcApk := a.prebuilt.SingleSourcePath(ctx) - if a.properties.Extract_apk != nil { + if a.properties.Extract_apk.GetOrDefault(ctx, "") != "" { extract_apk := android.PathForModuleOut(ctx, "extract-apk", ctx.ModuleName()+".apk") a.extractSubApk(ctx, srcApk, extract_apk) srcApk = extract_apk @@ -787,6 +787,10 @@ func (a *AndroidTestImport) GenerateAndroidBuildActions(ctx android.ModuleContex a.updateModuleInfoJSON(ctx) a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data) + + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: a.testProperties.Test_suites, + }) } func (a *AndroidTestImport) updateModuleInfoJSON(ctx android.ModuleContext) { diff --git a/java/base.go b/java/base.go index 0833831fc..1a12075bc 100644 --- a/java/base.go +++ b/java/base.go @@ -629,7 +629,7 @@ func CheckStableSdkVersion(ctx android.BaseModuleContext, module android.ModuleP return nil } if info.SdkVersion.Kind == android.SdkCorePlatform { - if useLegacyCorePlatformApi(ctx, android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey).BaseModuleName) { + if useLegacyCorePlatformApi(ctx, android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).BaseModuleName) { return fmt.Errorf("non stable SDK %v - uses legacy core platform", info.SdkVersion) } else { // Treat stable core platform as stable. @@ -888,6 +888,10 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) { // Add dependency on libraries that provide additional hidden api annotations. ctx.AddVariationDependencies(nil, hiddenApiAnnotationsTag, j.properties.Hiddenapi_additional_annotations...) + // Add dependency on (soft) downstream libs from which to trace references during optimization. + traceRefs := j.dexProperties.Optimize.Trace_references_from.GetOrDefault(ctx, []string{}) + ctx.AddVariationDependencies(nil, traceReferencesTag, traceRefs...) + // For library dependencies that are component libraries (like stubs), add the implementation // as a dependency (dexpreopt needs to be against the implementation library, not stubs). for _, dep := range libDeps { diff --git a/java/builder.go b/java/builder.go index ade978450..dff0032d8 100644 --- a/java/builder.go +++ b/java/builder.go @@ -310,7 +310,7 @@ var ( gatherReleasedFlaggedApisRule = pctx.AndroidStaticRule("gatherReleasedFlaggedApisRule", blueprint.RuleParams{ - Command: `${aconfig} dump-cache --dedup --format='{fully_qualified_name}' ` + + Command: `${aconfig} dump-cache --dedup --format=protobuf ` + `--out ${out} ` + `${flags_path} ` + `${filter_args} `, @@ -320,8 +320,8 @@ var ( generateMetalavaRevertAnnotationsRule = pctx.AndroidStaticRule("generateMetalavaRevertAnnotationsRule", blueprint.RuleParams{ - Command: `${keep-flagged-apis} ${in} > ${out}`, - CommandDeps: []string{"${keep-flagged-apis}"}, + Command: `${aconfig-to-metalava-flags} ${in} > ${out}`, + CommandDeps: []string{"${aconfig-to-metalava-flags}"}, }) generateApiXMLRule = pctx.AndroidStaticRule("generateApiXMLRule", @@ -339,7 +339,7 @@ func init() { pctx.HostBinToolVariable("aconfig", "aconfig") pctx.HostBinToolVariable("ravenizer", "ravenizer") pctx.HostBinToolVariable("apimapper", "apimapper") - pctx.HostBinToolVariable("keep-flagged-apis", "keep-flagged-apis") + pctx.HostBinToolVariable("aconfig-to-metalava-flags", "aconfig-to-metalava-flags") } type javaBuilderFlags struct { diff --git a/java/config/config.go b/java/config/config.go index 71025de6a..fdb8d7886 100644 --- a/java/config/config.go +++ b/java/config/config.go @@ -173,6 +173,7 @@ func init() { pctx.HostBinToolVariable("R8Cmd", "r8") pctx.HostBinToolVariable("ExtractR8RulesCmd", "extract-r8-rules") pctx.HostBinToolVariable("ResourceShrinkerCmd", "resourceshrinker") + pctx.HostBinToolVariable("TraceReferencesCmd", "tracereferences") pctx.HostBinToolVariable("HiddenAPICmd", "hiddenapi") pctx.HostBinToolVariable("ExtractApksCmd", "extract_apks") pctx.VariableFunc("TurbineJar", func(ctx android.PackageVarContext) string { diff --git a/java/dex.go b/java/dex.go index ed2df2103..ed9c82ba2 100644 --- a/java/dex.go +++ b/java/dex.go @@ -103,6 +103,34 @@ type DexProperties struct { // If true, transitive reverse dependencies of this module will have this // module's proguard spec appended to their optimization action Export_proguard_flags_files *bool + + // Path to a file containing a list of class names that should not be compiled using R8. + // These classes will be compiled by D8 similar to when Optimize.Enabled is false. + // + // Example: + // + // r8.exclude: + // com.example.Foo + // com.example.Bar + // com.example.Bar$Baz + // + // By default all classes are compiled using R8 when Optimize.Enabled is set. + Exclude *string `android:"path"` + + // Optional list of downstream (Java) libraries from which to trace and preserve references + // when optimizing. Note that this requires that the source reference does *not* have + // a strict lib dependency on this target; dependencies should be on intermediate targets + // statically linked into this target, e.g., if A references B, and we want to trace and + // keep references from A when optimizing B, you would create an intermediate B.impl ( + // containing all static code), have A depend on `B.impl` via libs, and set + // `trace_references_from: ["A"]` on B. + // + // Also note that these are *not* inherited across targets, they must be specified at the + // top-level target that is optimized. + // + // TODO(b/212737576): Handle this implicitly using bottom-up deps mutation and implicit + // creation of a proxy `.impl` library. + Trace_references_from proptools.Configurable[[]string] `android:"arch_variant"` } // Keep the data uncompressed. We always need uncompressed dex for execution, @@ -445,6 +473,20 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams, flagFiles = append(flagFiles, android.PathsForModuleSrc(ctx, opt.Proguard_flags_files)...) + traceReferencesSources := android.Paths{} + ctx.VisitDirectDepsProxyWithTag(traceReferencesTag, func(m android.ModuleProxy) { + if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok { + traceReferencesSources = append(traceReferencesSources, dep.ImplementationJars...) + } + }) + if len(traceReferencesSources) > 0 { + traceTarget := dexParams.classesJar + traceLibs := android.FirstUniquePaths(append(flags.bootClasspath.Paths(), flags.dexClasspath.Paths()...)) + traceReferencesFlags := android.PathForModuleOut(ctx, "proguard", "trace_references.flags") + TraceReferences(ctx, traceReferencesSources, traceTarget, traceLibs, traceReferencesFlags) + flagFiles = append(flagFiles, traceReferencesFlags) + } + flagFiles = android.FirstUniquePaths(flagFiles) r8Flags = append(r8Flags, android.JoinWithPrefix(flagFiles.Strings(), "-include ")) @@ -528,6 +570,11 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams, r8Flags = append(r8Flags, "--store-store-fence-constructor-inlining") } + if opt.Exclude != nil { + r8Flags = append(r8Flags, "--exclude", *opt.Exclude) + r8Deps = append(r8Deps, android.PathForModuleSrc(ctx, *opt.Exclude)) + } + return r8Flags, r8Deps, artProfileOutput } diff --git a/java/dex_test.go b/java/dex_test.go index 66d801dcc..e94864bbc 100644 --- a/java/dex_test.go +++ b/java/dex_test.go @@ -866,3 +866,46 @@ func TestDebugReleaseFlags(t *testing.T) { }) } } + +func TestTraceReferences(t *testing.T) { + t.Parallel() + bp := ` + android_app { + name: "app", + libs: ["lib.impl"], + srcs: ["foo.java"], + platform_apis: true, + } + + java_library { + name: "lib", + optimize: { + enabled: true, + trace_references_from: ["app"], + }, + srcs: ["bar.java"], + static_libs: ["lib.impl"], + installable: true, + } + + java_library { + name: "lib.impl", + srcs: ["baz.java"], + } + ` + result := android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + ).RunTestWithBp(t, bp) + + appJar := result.ModuleForTests(t, "app", "android_common").Output("combined/app.jar").Output + libJar := result.ModuleForTests(t, "lib", "android_common").Output("combined/lib.jar").Output + libTraceRefs := result.ModuleForTests(t, "lib", "android_common").Rule("traceReferences") + libR8 := result.ModuleForTests(t, "lib", "android_common").Rule("r8") + + android.AssertStringDoesContain(t, "expected trace reference source from app jar", + libTraceRefs.Args["sources"], "--source "+appJar.String()) + android.AssertStringEquals(t, "expected trace reference target into lib jar", + libJar.String(), libTraceRefs.Input.String()) + android.AssertStringDoesContain(t, "expected trace reference proguard flags in lib r8 flags", + libR8.Args["r8Flags"], "trace_references.flags") +} diff --git a/java/dexpreopt.go b/java/dexpreopt.go index b21cfc968..e8e1cd405 100644 --- a/java/dexpreopt.go +++ b/java/dexpreopt.go @@ -650,6 +650,9 @@ func checkSystemServerOrder(ctx android.ModuleContext, libName string) { // for now just exclude any known irrelevant dependencies that would lead to incorrect errors. if _, ok := tag.(bootclasspathDependencyTag); ok { return false + } else if tag == traceReferencesTag { + // Allow ordering inversion if the dependency is purely for tracing references. + return false } depIndex := jars.IndexOfJar(dep.Name()) if jarIndex < depIndex && !config.BrokenSuboptimalOrderOfSystemServerJars { diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index 313d8c7a4..228704355 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -675,6 +675,139 @@ func (d *dexpreoptBootJars) GenerateAndroidBuildActions(ctx android.ModuleContex installs: artBootImageHostInstalls, }, ) + + d.buildBootZip(ctx) +} + +// Build the boot.zip which contains the boot jars and their compilation output +// We can do this only if preopt is enabled and if the product uses libart config (which sets the +// default properties for preopting). +// Origionally, this was only for ART Cloud. +func (d *dexpreoptBootJars) buildBootZip(ctx android.ModuleContext) { + image := d.defaultBootImage + if image == nil || SkipDexpreoptBootJars(ctx) { + return + } + global := dexpreopt.GetGlobalConfig(ctx) + globalSoong := dexpreopt.GetGlobalSoongConfig(ctx) + if global.DisablePreopt || global.OnlyPreoptArtBootImage { + return + } + + bootclasspathDexFiles, bootclassPathLocations := bcpForDexpreopt(ctx, global.PreoptWithUpdatableBcp) + if len(bootclasspathDexFiles) == 0 { + return + } + + systemServerDexjarsDir := android.PathForOutput(ctx, dexpreopt.SystemServerDexjarsDir) + + bootZipMetadataTmp := android.PathForModuleOut(ctx, "boot_zip", "METADATA.txt.tmp") + bootZipMetadata := android.PathForModuleOut(ctx, "boot_zip", "METADATA.txt") + newlineFile := android.PathForModuleOut(ctx, "boot_zip", "newline.txt") + android.WriteFileRule(ctx, newlineFile, "") + + dexPreoptRootDir := filepath.Dir(filepath.Dir(bootclasspathDexFiles[0].String())) + + var sb strings.Builder + sb.WriteString("bootclasspath = ") + for i, bootclasspathJar := range bootclasspathDexFiles { + if i > 0 { + sb.WriteString(":") + } + rel, err := filepath.Rel(dexPreoptRootDir, bootclasspathJar.String()) + if err != nil { + ctx.ModuleErrorf("All dexpreopt jars should be under the same rootdir %q, but %q wasn't.", dexPreoptRootDir, bootclasspathJar) + } else { + sb.WriteString(rel) + } + } + sb.WriteString("\nbootclasspath-locations = ") + for i, bootclasspathLocation := range bootclassPathLocations { + if i > 0 { + sb.WriteString(":") + } + sb.WriteString(bootclasspathLocation) + } + sb.WriteString("\nboot-image = ") + + // Infix can be 'art' (ART image for testing), 'boot' (primary), or 'mainline' (mainline + // extension). Soong creates a set of variables for Make, one or each boot image. The only + // reason why the ART image is exposed to Make is testing (art gtests) and benchmarking (art + // golem benchmarks). Install rules that use those variables are in dex_preopt_libart.mk. Here + // for dexpreopt purposes the infix is always 'boot' or 'mainline'. + dexpreoptInfix := "boot" + if global.PreoptWithUpdatableBcp { + dexpreoptInfix = "mainline" + } + + var dexPreoptImageZipBoot android.Path + var dexPreoptImageZipArt android.Path + var dexPreoptImageZipMainline android.Path + for _, current := range append(d.otherImages, image) { + if current.name == dexpreoptInfix { + _, imageLocationsOnDevice := current.getAnyAndroidVariant().imageLocations() + for i, location := range imageLocationsOnDevice { + imageLocationsOnDevice[i] = strings.TrimPrefix(location, "/") + } + sb.WriteString(strings.Join(imageLocationsOnDevice, ":")) + } + switch current.name { + case "boot": + dexPreoptImageZipBoot = current.zip + case "art": + dexPreoptImageZipArt = current.zip + case "mainline": + dexPreoptImageZipMainline = current.zip + } + } + sb.WriteString("\nextra-args = ") + android.WriteFileRuleVerbatim(ctx, bootZipMetadataTmp, sb.String()) + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cat, + Inputs: []android.Path{ + bootZipMetadataTmp, + globalSoong.UffdGcFlag, + newlineFile, + }, + Output: bootZipMetadata, + }) + + bootZipFirstPart := android.PathForModuleOut(ctx, "boot_zip", "boot_first_part.zip") + bootZip := android.PathForModuleOut(ctx, "boot_zip", "boot.zip") + builder := android.NewRuleBuilder(pctx, ctx) + cmd := builder.Command().BuiltTool("soong_zip"). + FlagWithOutput("-o ", bootZipFirstPart). + FlagWithArg("-C ", filepath.Dir(filepath.Dir(bootclasspathDexFiles[0].String()))) + for _, bootclasspathJar := range bootclasspathDexFiles { + cmd.FlagWithInput("-f ", bootclasspathJar) + } + for i := range global.SystemServerJars.Len() { + // Use "/system" path for JARs with "platform:" prefix. These JARs counterintuitively use + // "platform" prefix but they will be actually installed to /system partition. + // For the remaining system server JARs use the partition signified by the prefix. + // For example, prefix "system_ext:" will use "/system_ext" path. + dir := global.SystemServerJars.Apex(i) + if dir == "platform" { + dir = "system" + } + jar := global.SystemServerJars.Jar(i) + ".jar" + cmd.FlagWithArg("-e ", dir+"/framework/"+jar) + cmd.FlagWithInput("-f ", systemServerDexjarsDir.Join(ctx, jar)) + } + cmd.Flag("-j") + cmd.FlagWithInput("-f ", bootZipMetadata) + + builder.Command().BuiltTool("merge_zips"). + Output(bootZip). + Input(bootZipFirstPart). + Input(dexPreoptImageZipBoot). + Input(dexPreoptImageZipArt). + Input(dexPreoptImageZipMainline) + + builder.Build("boot_zip", "build boot.zip") + + ctx.DistForGoal("droidcore", bootZipMetadata) + ctx.DistForGoal("droidcore", bootZip) } // GenerateSingletonBuildActions generates build rules for the dexpreopt config for Make. diff --git a/java/dexpreopt_check.go b/java/dexpreopt_check.go index c97156541..9d0f539ba 100644 --- a/java/dexpreopt_check.go +++ b/java/dexpreopt_check.go @@ -100,7 +100,12 @@ func (m *dexpreoptSystemserverCheck) GenerateAndroidBuildActions(ctx android.Mod if systemServerJar.InstallInSystemExt() && ctx.Config().InstallApexSystemServerDexpreoptSamePartition() { partition = ctx.DeviceConfig().SystemExtPath() // system_ext } - dexLocation := dexpreopt.GetSystemServerDexLocation(ctx, global, systemServerJar.Name()) + var dexLocation string + if m, ok := systemServerJar.(ModuleWithStem); ok { + dexLocation = dexpreopt.GetSystemServerDexLocation(ctx, global, m.Stem()) + } else { + ctx.PropertyErrorf("dexpreopt_systemserver_check", "%v is not a ModuleWithStem", systemServerJar.Name()) + } odexLocation := dexpreopt.ToOdexPath(dexLocation, targets[0].Arch.ArchType, partition) odexPath := getInstallPath(ctx, odexLocation) vdexPath := getInstallPath(ctx, pathtools.ReplaceExtension(odexLocation, "vdex")) diff --git a/java/droiddoc.go b/java/droiddoc.go index 225f201a9..3faf294de 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -195,6 +195,9 @@ func apiCheckEnabled(ctx android.ModuleContext, apiToCheck ApiToCheck, apiVersio "them instead.") } return false + } else if ctx.Config().PartialCompileFlags().Disable_stub_validation && + !ctx.Config().BuildFromTextStub() { + return false } else if String(apiToCheck.Api_file) != "" && String(apiToCheck.Removed_api_file) != "" { return true } else if String(apiToCheck.Api_file) != "" { diff --git a/java/droidstubs.go b/java/droidstubs.go index caad6883e..c21592518 100644 --- a/java/droidstubs.go +++ b/java/droidstubs.go @@ -821,19 +821,17 @@ func generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBu } } - if len(aconfigFlagsPaths) == 0 { - // This argument should not be added for "everything" stubs - cmd.Flag("--revert-annotation android.annotation.FlaggedApi") - return - } + // If aconfigFlagsPaths is empty then it is still important to generate the + // Metalava flags config file, albeit with an empty set of flags, so that all + // flagged APIs will be reverted. - releasedFlaggedApisFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flagged-apis-%s.txt", stubsType.String())) - revertAnnotationsFile := android.PathForModuleOut(ctx, fmt.Sprintf("revert-annotations-%s.txt", stubsType.String())) + releasedFlagsFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flags-%s.pb", stubsType.String())) + metalavaFlagsConfigFile := android.PathForModuleOut(ctx, fmt.Sprintf("flags-config-%s.xml", stubsType.String())) ctx.Build(pctx, android.BuildParams{ Rule: gatherReleasedFlaggedApisRule, Inputs: aconfigFlagsPaths, - Output: releasedFlaggedApisFile, + Output: releasedFlagsFile, Description: fmt.Sprintf("%s gather aconfig flags", stubsType), Args: map[string]string{ "flags_path": android.JoinPathsWithPrefix(aconfigFlagsPaths, "--cache "), @@ -843,12 +841,12 @@ func generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBu ctx.Build(pctx, android.BuildParams{ Rule: generateMetalavaRevertAnnotationsRule, - Input: releasedFlaggedApisFile, - Output: revertAnnotationsFile, - Description: fmt.Sprintf("%s revert annotations", stubsType), + Input: releasedFlagsFile, + Output: metalavaFlagsConfigFile, + Description: fmt.Sprintf("%s metalava flags config", stubsType), }) - cmd.FlagWithInput("@", revertAnnotationsFile) + cmd.FlagWithInput("--config-file ", metalavaFlagsConfigFile) } func (d *Droidstubs) commonMetalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder, @@ -1245,7 +1243,7 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) { // Add options for the other optional tasks: API-lint and check-released. // We generate separate timestamp files for them. - doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false) + doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false) && !ctx.Config().PartialCompileFlags().Disable_api_lint doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") writeSdkValues := Bool(d.properties.Write_sdk_values) diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go index dfdf87703..1f9d223b5 100644 --- a/java/droidstubs_test.go +++ b/java/droidstubs_test.go @@ -410,12 +410,12 @@ func TestAconfigDeclarations(t *testing.T) { m := result.ModuleForTests(t, "foo", "android_common") android.AssertStringDoesContain(t, "foo generates revert annotations file", - strings.Join(m.AllOutputs(), ""), "revert-annotations-exportable.txt") + strings.Join(m.AllOutputs(), ""), "flags-config-exportable.xml") // revert-annotations.txt passed to exportable stubs generation metalava command manifest := m.Output("metalava_exportable.sbox.textproto") cmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest).Commands[0].Command) - android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "revert-annotations-exportable.txt") + android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "flags-config-exportable.xml") android.AssertStringDoesContain(t, "foo generates exportable stubs jar", strings.Join(m.AllOutputs(), ""), "exportable/foo-stubs.srcjar") @@ -460,7 +460,7 @@ func TestReleaseExportRuntimeApis(t *testing.T) { m := result.ModuleForTests(t, "foo", "android_common") - rule := m.Output("released-flagged-apis-exportable.txt") + rule := m.Output("released-flags-exportable.pb") exposeWritableApisFilter := "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'" android.AssertStringEquals(t, "Filter argument expected to contain READ_WRITE permissions", exposeWritableApisFilter, rule.Args["filter_args"]) } diff --git a/java/fuzz.go b/java/fuzz.go index 5973957a2..0e239f0ec 100644 --- a/java/fuzz.go +++ b/java/fuzz.go @@ -132,6 +132,8 @@ func (j *JavaFuzzTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { } j.Test.GenerateAndroidBuildActions(ctx) + + fuzz.SetFuzzPackagedModuleInfo(ctx, &j.fuzzPackagedModule) } type javaFuzzPackager struct { @@ -153,6 +155,10 @@ func (s *javaFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { if !ok { return } + fuzzInfo, ok := android.OtherModuleProvider(ctx, module, fuzz.FuzzPackagedModuleInfoProvider) + if !ok { + return + } hostOrTargetString := "target" if javaFuzzModule.Target().HostCross { @@ -179,7 +185,7 @@ func (s *javaFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { builder := android.NewRuleBuilder(pctx, ctx) // Package the artifacts (data, corpus, config and dictionary) into a zipfile. - files = s.PackageArtifacts(ctx, module, javaFuzzModule.fuzzPackagedModule, archDir, builder) + files = s.PackageArtifacts(ctx, module, &fuzzInfo, archDir, builder) // Add .jar if !javaFuzzModule.Host() { @@ -193,7 +199,7 @@ func (s *javaFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { files = append(files, fuzz.FileToZip{SourceFilePath: fPath}) } - archDirs[archOs], ok = s.BuildZipFile(ctx, module, javaFuzzModule.fuzzPackagedModule, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs) + archDirs[archOs], ok = s.BuildZipFile(ctx, module, &fuzzInfo, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs) if !ok { return } diff --git a/java/java.go b/java/java.go index b18c56130..dd9f852f0 100644 --- a/java/java.go +++ b/java/java.go @@ -432,6 +432,9 @@ type JavaInfo struct { DexJarBuildPath OptionalDexJarPath DexpreopterInfo *DexpreopterInfo + + XrefJavaFiles android.Paths + XrefKotlinFiles android.Paths } var JavaInfoProvider = blueprint.NewProvider[*JavaInfo]() @@ -575,6 +578,7 @@ var ( extraLintCheckTag = dependencyTag{name: "extra-lint-check", toolchain: true} jniLibTag = dependencyTag{name: "jnilib", runtimeLinked: true} r8LibraryJarTag = dependencyTag{name: "r8-libraryjar", runtimeLinked: true} + traceReferencesTag = dependencyTag{name: "trace-references"} syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"} javaApiContributionTag = dependencyTag{name: "java-api-contribution"} aconfigDeclarationTag = dependencyTag{name: "aconfig-declaration"} @@ -605,6 +609,7 @@ var ( kotlinPluginTag, syspropPublicStubDepTag, instrumentationForTag, + traceReferencesTag, } ) @@ -1951,6 +1956,10 @@ func (j *Test) generateAndroidBuildActionsWithConfig(ctx android.ModuleContext, ctx.InstallFile(pathInTestCases, ctx.ModuleName()+".jar", j.outputFile) } } + + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: j.testProperties.Test_suites, + }) } func (j *TestHelperLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -1967,6 +1976,10 @@ func (j *TestHelperLibrary) GenerateAndroidBuildActions(ctx android.ModuleContex if optionalConfig.Valid() { moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, optionalConfig.String()) } + + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: j.testHelperLibraryProperties.Test_suites, + }) } func (j *JavaTestImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -2222,7 +2235,7 @@ func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) { // install these alongside the java binary. ctx.VisitDirectDepsProxyWithTag(jniInstallTag, func(jni android.ModuleProxy) { // Use the BaseModuleName of the dependency (without any prebuilt_ prefix) - commonInfo, _ := android.OtherModuleProvider(ctx, jni, android.CommonModuleInfoKey) + commonInfo := android.OtherModulePointerProviderOrDefault(ctx, jni, android.CommonModuleInfoProvider) j.androidMkNamesOfJniLibs = append(j.androidMkNamesOfJniLibs, commonInfo.BaseModuleName+":"+commonInfo.Target.Arch.ArchType.Bitness()) }) // Check that native libraries are not listed in `required`. Prompt users to use `jni_libs` instead. @@ -2527,6 +2540,7 @@ func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { apiContributions := al.properties.Api_contributions addValidations := !ctx.Config().IsEnvTrue("DISABLE_STUB_VALIDATION") && !ctx.Config().IsEnvTrue("WITHOUT_CHECK_API") && + !ctx.Config().PartialCompileFlags().Disable_stub_validation && proptools.BoolDefault(al.properties.Enable_validation, true) for _, apiContributionName := range apiContributions { ctx.AddDependency(ctx.Module(), javaApiContributionTag, apiContributionName) @@ -3360,21 +3374,12 @@ func (j *Import) UseProfileGuidedDexpreopt() bool { // Add compile time check for interface implementation var _ android.IDEInfo = (*Import)(nil) -var _ android.IDECustomizedModuleName = (*Import)(nil) // Collect information for opening IDE project files in java/jdeps.go. - func (j *Import) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) { dpInfo.Jars = append(dpInfo.Jars, j.combinedImplementationFile.String()) } -func (j *Import) IDECustomizedModuleName() string { - // TODO(b/113562217): Extract the base module name from the Import name, often the Import name - // has a prefix "prebuilt_". Remove the prefix explicitly if needed until we find a better - // solution to get the Import name. - return android.RemoveOptionalPrebuiltPrefix(j.Name()) -} - var _ android.PrebuiltInterface = (*Import)(nil) func (j *Import) IsInstallable() bool { @@ -3649,10 +3654,10 @@ type kytheExtractJavaSingleton struct { func (ks *kytheExtractJavaSingleton) GenerateBuildActions(ctx android.SingletonContext) { var xrefTargets android.Paths var xrefKotlinTargets android.Paths - ctx.VisitAllModules(func(module android.Module) { - if javaModule, ok := module.(xref); ok { - xrefTargets = append(xrefTargets, javaModule.XrefJavaFiles()...) - xrefKotlinTargets = append(xrefKotlinTargets, javaModule.XrefKotlinFiles()...) + ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { + if javaInfo, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok { + xrefTargets = append(xrefTargets, javaInfo.XrefJavaFiles...) + xrefKotlinTargets = append(xrefKotlinTargets, javaInfo.XrefKotlinFiles...) } }) // TODO(asmundak): perhaps emit a rule to output a warning if there were no xrefTargets @@ -3853,4 +3858,9 @@ func setExtraJavaInfo(ctx android.ModuleContext, module android.Module, javaInfo ApexSystemServerDexJars: di.ApexSystemServerDexJars(), } } + + if xr, ok := module.(xref); ok { + javaInfo.XrefJavaFiles = xr.XrefJavaFiles() + javaInfo.XrefKotlinFiles = xr.XrefKotlinFiles() + } } diff --git a/java/java_test.go b/java/java_test.go index a6290a628..1ba78d49b 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -2912,12 +2912,12 @@ func TestApiLibraryAconfigDeclarations(t *testing.T) { m := result.ModuleForTests(t, "foo", "android_common") android.AssertStringDoesContain(t, "foo generates revert annotations file", - strings.Join(m.AllOutputs(), ""), "revert-annotations-exportable.txt") + strings.Join(m.AllOutputs(), ""), "flags-config-exportable.xml") // revert-annotations.txt passed to exportable stubs generation metalava command manifest := m.Output("metalava.sbox.textproto") cmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest).Commands[0].Command) - android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "revert-annotations-exportable.txt") + android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "flags-config-exportable.xml") } func TestTestOnly(t *testing.T) { @@ -3193,3 +3193,72 @@ cc_library_shared { deps := findDepsOfModule(res, res.ModuleForTests(t, "myjavabin", "android_common").Module(), "mynativelib") android.AssertIntEquals(t, "Create a dep on the first variant", 1, len(deps)) } + +func TestBootJarNotInUsesLibs(t *testing.T) { + t.Parallel() + result := android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + PrepareForTestWithJavaSdkLibraryFiles, + FixtureWithLastReleaseApis("mysdklibrary", "myothersdklibrary"), + FixtureConfigureApexBootJars("myapex:mysdklibrary"), + ).RunTestWithBp(t, ` + bootclasspath_fragment { + name: "myfragment", + contents: ["mysdklibrary"], + hidden_api: { + split_packages: ["*"], + }, + } + + java_sdk_library { + name: "mysdklibrary", + srcs: ["Test.java"], + compile_dex: true, + public: {enabled: true}, + min_sdk_version: "2", + permitted_packages: ["mysdklibrary"], + sdk_version: "current", + } + + java_sdk_library { + name: "myothersdklibrary", + srcs: ["Test.java"], + compile_dex: true, + public: {enabled: true}, + min_sdk_version: "2", + permitted_packages: ["myothersdklibrary"], + sdk_version: "current", + } + + java_library { + name: "foo", + libs: [ + "bar", + "mysdklibrary.stubs", + ], + srcs: ["A.java"], + } + + java_library { + name: "bar", + libs: [ + "myothersdklibrary.stubs" + ], + } + `) + ctx := result.TestContext + fooModule := ctx.ModuleForTests(t, "foo", "android_common") + + androidMkEntries := android.AndroidMkEntriesForTest(t, ctx, fooModule.Module())[0] + localExportSdkLibraries := androidMkEntries.EntryMap["LOCAL_EXPORT_SDK_LIBRARIES"] + android.AssertStringListDoesNotContain(t, + "boot jar should not be included in uses libs entries", + localExportSdkLibraries, + "mysdklibrary", + ) + android.AssertStringListContains(t, + "non boot jar is included in uses libs entries", + localExportSdkLibraries, + "myothersdklibrary", + ) +} diff --git a/java/jdeps.go b/java/jdeps.go index 07f8c4378..56142c89b 100644 --- a/java/jdeps.go +++ b/java/jdeps.go @@ -45,13 +45,13 @@ func (j *jdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCont // (b/204397180) Generate module_bp_java_deps.json by default. moduleInfos := make(map[string]android.IdeInfo) - ctx.VisitAllModules(func(module android.Module) { - if !module.Enabled(ctx) { + ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { + if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled { return } // Prevent including both prebuilts and matching source modules when one replaces the other. - if !android.IsModulePreferred(module) { + if !android.IsModulePreferredProxy(ctx, module) { return } @@ -60,9 +60,11 @@ func (j *jdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCont return } name := ideInfoProvider.BaseModuleName - ideModuleNameProvider, ok := module.(android.IDECustomizedModuleName) - if ok { - name = ideModuleNameProvider.IDECustomizedModuleName() + if info, ok := android.OtherModuleProvider(ctx, module, JavaLibraryInfoProvider); ok && info.Prebuilt { + // TODO(b/113562217): Extract the base module name from the Import name, often the Import name + // has a prefix "prebuilt_". Remove the prefix explicitly if needed until we find a better + // solution to get the Import name. + name = android.RemoveOptionalPrebuiltPrefix(module.Name()) } dpInfo := moduleInfos[name] @@ -70,13 +72,12 @@ func (j *jdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCont dpInfo.Paths = []string{ctx.ModuleDir(module)} moduleInfos[name] = dpInfo - mkProvider, ok := module.(android.AndroidMkDataProvider) + mkProvider, ok := android.OtherModuleProvider(ctx, module, android.AndroidMkDataInfoProvider) if !ok { return } - data := mkProvider.AndroidMk() - if data.Class != "" { - dpInfo.Classes = append(dpInfo.Classes, data.Class) + if mkProvider.Class != "" { + dpInfo.Classes = append(dpInfo.Classes, mkProvider.Class) } if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok { diff --git a/java/lint.go b/java/lint.go index 66f7f8549..dc1e51ffb 100644 --- a/java/lint.go +++ b/java/lint.go @@ -595,12 +595,12 @@ func (l *lintSingleton) GenerateBuildActions(ctx android.SingletonContext) { l.copyLintDependencies(ctx) } -func findModuleOrErr(ctx android.SingletonContext, moduleName string) android.Module { - var res android.Module - ctx.VisitAllModules(func(m android.Module) { +func findModuleOrErr(ctx android.SingletonContext, moduleName string) *android.ModuleProxy { + var res *android.ModuleProxy + ctx.VisitAllModuleProxies(func(m android.ModuleProxy) { if ctx.ModuleName(m) == moduleName { if res == nil { - res = m + res = &m } else { ctx.Errorf("lint: multiple %s modules found: %s and %s", moduleName, ctx.ModuleSubDir(m), ctx.ModuleSubDir(res)) @@ -635,13 +635,13 @@ func (l *lintSingleton) copyLintDependencies(ctx android.SingletonContext) { ctx.Build(pctx, android.BuildParams{ Rule: android.CpIfChanged, - Input: android.OutputFileForModule(ctx, sdkAnnotations, ""), + Input: android.OutputFileForModule(ctx, *sdkAnnotations, ""), Output: copiedLintDatabaseFilesPath(ctx, files.annotationCopiedName), }) ctx.Build(pctx, android.BuildParams{ Rule: android.CpIfChanged, - Input: android.OutputFileForModule(ctx, apiVersionsDb, ".api_versions.xml"), + Input: android.OutputFileForModule(ctx, *apiVersionsDb, ".api_versions.xml"), Output: copiedLintDatabaseFilesPath(ctx, files.apiVersionsCopiedName), }) } @@ -658,12 +658,13 @@ func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) { var outputs []*LintInfo var dirs []string - ctx.VisitAllModules(func(m android.Module) { - if ctx.Config().KatiEnabled() && !m.ExportedToMake() { + ctx.VisitAllModuleProxies(func(m android.ModuleProxy) { + commonInfo := android.OtherModulePointerProviderOrDefault(ctx, m, android.CommonModuleInfoProvider) + if ctx.Config().KatiEnabled() && !commonInfo.ExportedToMake { return } - if apex, ok := m.(android.ApexModule); ok && apex.NotAvailableForPlatform() { + if commonInfo.IsApexModule && commonInfo.NotAvailableForPlatform { apexInfo, _ := android.OtherModuleProvider(ctx, m, android.ApexInfoProvider) if apexInfo.IsForPlatform() { // There are stray platform variants of modules in apexes that are not available for diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go index 363521a7f..d2ec8bd4f 100644 --- a/java/platform_compat_config.go +++ b/java/platform_compat_config.go @@ -99,6 +99,14 @@ type platformCompatConfigMetadataProvider interface { includeInMergedXml() bool } +type PlatformCompatConfigMetadataInfo struct { + CompatConfigMetadata android.Path + // Whether to include it in the "merged" XML (merged_compat_config.xml) or not. + IncludeInMergedXml bool +} + +var PlatformCompatConfigMetadataInfoProvider = blueprint.NewProvider[PlatformCompatConfigMetadataInfo]() + type PlatformCompatConfigIntf interface { android.Module @@ -136,6 +144,11 @@ func (p *platformCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleCon CompatConfig: p.CompatConfig(), SubDir: p.SubDir(), }) + + android.SetProvider(ctx, PlatformCompatConfigMetadataInfoProvider, PlatformCompatConfigMetadataInfo{ + CompatConfigMetadata: p.compatConfigMetadata(), + IncludeInMergedXml: p.includeInMergedXml(), + }) } func (p *platformCompatConfig) AndroidMkEntries() []android.AndroidMkEntries { @@ -238,6 +251,11 @@ var _ platformCompatConfigMetadataProvider = (*prebuiltCompatConfigModule)(nil) func (module *prebuiltCompatConfigModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { module.metadataFile = module.prebuilt.SingleSourcePath(ctx) + + android.SetProvider(ctx, PlatformCompatConfigMetadataInfoProvider, PlatformCompatConfigMetadataInfo{ + CompatConfigMetadata: module.compatConfigMetadata(), + IncludeInMergedXml: module.includeInMergedXml(), + }) } // A prebuilt version of platform_compat_config that provides the metadata. @@ -258,18 +276,18 @@ func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.Singlet var compatConfigMetadata android.Paths - ctx.VisitAllModules(func(module android.Module) { - if !module.Enabled(ctx) { + ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { + if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled { return } - if c, ok := module.(platformCompatConfigMetadataProvider); ok { - if !android.IsModulePreferred(module) { + if c, ok := android.OtherModuleProvider(ctx, module, PlatformCompatConfigMetadataInfoProvider); ok { + if !android.IsModulePreferredProxy(ctx, module) { return } - if !c.includeInMergedXml() { + if !c.IncludeInMergedXml { return } - metadata := c.compatConfigMetadata() + metadata := c.CompatConfigMetadata compatConfigMetadata = append(compatConfigMetadata, metadata) } }) diff --git a/java/ravenwood.go b/java/ravenwood.go index c4078c587..a942dc653 100644 --- a/java/ravenwood.go +++ b/java/ravenwood.go @@ -117,6 +117,8 @@ func ravenwoodTestFactory() android.Module { "ravenwood-tests", } module.testProperties.Test_options.Unit_test = proptools.BoolPtr(false) + module.Module.sourceProperties.Test_only = proptools.BoolPtr(true) + module.Module.sourceProperties.Top_level_test_target = true InitJavaModule(module, android.DeviceSupported) android.InitDefaultableModule(module) diff --git a/java/ravenwood_test.go b/java/ravenwood_test.go index 24a02bbdc..d6493bcfa 100644 --- a/java/ravenwood_test.go +++ b/java/ravenwood_test.go @@ -230,4 +230,15 @@ func TestRavenwoodTest(t *testing.T) { android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-runtime/lib64/libred.so") android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-runtime/lib64/ravenwood-runtime-jni3.so") android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-utils/framework-rules.ravenwood.jar") + + // Ensure they are listed as "test" modules for code coverage + expectedTestOnlyModules := []string{ + "ravenwood-test", + "ravenwood-test-empty", + } + expectedTopLevelTests := []string{ + "ravenwood-test", + "ravenwood-test-empty", + } + assertTestOnlyAndTopLevel(t, ctx, expectedTestOnlyModules, expectedTopLevelTests) } diff --git a/java/robolectric.go b/java/robolectric.go index be369f780..1d204a4e0 100644 --- a/java/robolectric.go +++ b/java/robolectric.go @@ -284,6 +284,11 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ TestSuites: r.TestSuites(), }) + + android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{ + TestOnly: Bool(r.sourceProperties.Test_only), + TopLevelTarget: r.sourceProperties.Top_level_test_target, + }) } func generateSameDirRoboTestConfigJar(ctx android.ModuleContext, outputFile android.ModuleOutPath) { @@ -335,7 +340,8 @@ func RobolectricTestFactory() android.Module { module.Module.dexpreopter.isTest = true module.Module.linter.properties.Lint.Test_module_type = proptools.BoolPtr(true) - + module.Module.sourceProperties.Test_only = proptools.BoolPtr(true) + module.Module.sourceProperties.Top_level_test_target = true module.testProperties.Test_suites = []string{"robolectric-tests"} InitJavaModule(module, android.DeviceSupported) diff --git a/java/robolectric_test.go b/java/robolectric_test.go index 4bf224b4f..cc16c6a26 100644 --- a/java/robolectric_test.go +++ b/java/robolectric_test.go @@ -107,4 +107,15 @@ func TestRobolectricJniTest(t *testing.T) { // Check that the .so files make it into the output. module := ctx.ModuleForTests(t, "robo-test", "android_common") module.Output(installPathPrefix + "/robo-test/lib64/jni-lib1.so") + + // Ensure they are listed as "test" modules for code coverage + expectedTestOnlyModules := []string{ + "robo-test", + } + + expectedTopLevelTests := []string{ + "robo-test", + } + assertTestOnlyAndTopLevel(t, ctx, expectedTestOnlyModules, expectedTopLevelTests) + } diff --git a/java/rro.go b/java/rro.go index f7f85f001..4ae8d7fc7 100644 --- a/java/rro.go +++ b/java/rro.go @@ -99,15 +99,6 @@ type RuntimeResourceOverlayProperties struct { Overrides []string } -// RuntimeResourceOverlayModule interface is used by the apex package to gather information from -// a RuntimeResourceOverlay module. -type RuntimeResourceOverlayModule interface { - android.Module - OutputFile() android.Path - Certificate() Certificate - Theme() string -} - // RRO's partition logic is different from the partition logic of other modules defined in soong/android/paths.go // The default partition for RRO is "/product" and not "/system" func rroPartition(ctx android.ModuleContext) string { @@ -217,11 +208,13 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC }) android.SetProvider(ctx, RuntimeResourceOverlayInfoProvider, RuntimeResourceOverlayInfo{ - OutputFile: r.OutputFile(), + OutputFile: r.outputFile, Certificate: r.Certificate(), Theme: r.Theme(), }) + ctx.SetOutputFiles([]android.Path{r.outputFile}, "") + buildComplianceMetadata(ctx) } @@ -252,10 +245,6 @@ func (r *RuntimeResourceOverlay) Certificate() Certificate { return r.certificate } -func (r *RuntimeResourceOverlay) OutputFile() android.Path { - return r.outputFile -} - func (r *RuntimeResourceOverlay) Theme() string { return String(r.properties.Theme) } @@ -406,10 +395,11 @@ func (a *AutogenRuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android. a.aapt.buildActions(ctx, aaptBuildActionOptions{ - sdkContext: a, - extraLinkFlags: aaptLinkFlags, - rroDirs: &rroDirs, - manifestForAapt: genManifest, + sdkContext: a, + extraLinkFlags: aaptLinkFlags, + rroDirs: &rroDirs, + manifestForAapt: genManifest, + aconfigTextFiles: getAconfigFilePaths(ctx), }, ) @@ -426,6 +416,11 @@ func (a *AutogenRuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android. // Install the signed apk installDir := android.PathForModuleInstall(ctx, "overlay") ctx.InstallFile(installDir, signed.Base(), signed) + + android.SetProvider(ctx, RuntimeResourceOverlayInfoProvider, RuntimeResourceOverlayInfo{ + OutputFile: signed, + Certificate: a.certificate, + }) } func (a *AutogenRuntimeResourceOverlay) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { diff --git a/java/rro_test.go b/java/rro_test.go index 0ccc8e707..3e4fed51e 100644 --- a/java/rro_test.go +++ b/java/rro_test.go @@ -358,3 +358,21 @@ func TestRuntimeResourceOverlayFlagsPackages(t *testing.T) { "--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt", ) } + +func TestCanBeDataOfTest(t *testing.T) { + android.GroupFixturePreparers( + prepareForJavaTest, + ).RunTestWithBp(t, ` + runtime_resource_overlay { + name: "foo", + sdk_version: "current", + } + android_test { + name: "bar", + data: [ + ":foo", + ], + } + `) + // Just test that this doesn't get errors +} diff --git a/java/sdk.go b/java/sdk.go index 8510959df..73262dab3 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -274,7 +274,7 @@ func createNonUpdatableFrameworkAidl(ctx android.SingletonContext) { func createFrameworkAidl(stubsModules []string, path android.WritablePath, ctx android.SingletonContext) *android.RuleBuilder { stubsJars := make([]android.Paths, len(stubsModules)) - ctx.VisitAllModules(func(module android.Module) { + ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { // Collect dex jar paths for the modules listed above. if j, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok { name := ctx.ModuleName(module) @@ -382,7 +382,7 @@ func createAPIFingerprint(ctx android.SingletonContext) { rule.Build("api_fingerprint", "generate api_fingerprint.txt") - if ctx.Config().BuildOS == android.Linux { + if ctx.Config().BuildOS.Linux() { ctx.DistForGoals([]string{"sdk", "droidcore"}, out) } } diff --git a/java/sdk_library.go b/java/sdk_library.go index 7944bb2a8..00ba8b2fb 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -1337,10 +1337,10 @@ func (module *SdkLibrary) CheckMinSdkVersion(ctx android.ModuleContext) { func CheckMinSdkVersion(ctx android.ModuleContext, module *Library) { android.CheckMinSdkVersion(ctx, module.MinSdkVersion(ctx), func(c android.BaseModuleContext, do android.PayloadDepsCallback) { - ctx.WalkDeps(func(child android.Module, parent android.Module) bool { + ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool { isExternal := !android.IsDepInSameApex(ctx, module, child) - if am, ok := child.(android.ApexModule); ok { - if !do(ctx, parent, am, isExternal) { + if am, ok := android.OtherModuleProvider(ctx, child, android.CommonModuleInfoProvider); ok && am.IsApexModule { + if !do(ctx, parent, child, isExternal) { return false } } @@ -1580,7 +1580,9 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) setOutputFilesFromJavaInfo(ctx, module.implLibraryInfo) } - javaInfo := &JavaInfo{} + javaInfo := &JavaInfo{ + JacocoReportClassesFile: module.jacocoReportClassesFile, + } setExtraJavaInfo(ctx, ctx.Module(), javaInfo) android.SetProvider(ctx, JavaInfoProvider, javaInfo) @@ -2240,6 +2242,10 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo } javaInfo := &JavaInfo{} + if module.implLibraryInfo != nil { + javaInfo.JacocoReportClassesFile = module.implLibraryInfo.JacocoReportClassesFile + } + setExtraJavaInfo(ctx, ctx.Module(), javaInfo) android.SetProvider(ctx, JavaInfoProvider, javaInfo) diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go index 431bbacfd..6d27e54d0 100644 --- a/java/sdk_library_test.go +++ b/java/sdk_library_test.go @@ -494,7 +494,7 @@ func TestJavaSdkLibrary_AccessOutputFiles_NoAnnotations(t *testing.T) { PrepareForTestWithJavaSdkLibraryFiles, FixtureWithLastReleaseApis("foo"), ). - ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "bar" variant "android_common": unsupported module reference tag ".public.annotations.zip"`)). + ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "bar" variant "android_common": unsupported output tag ".public.annotations.zip"`)). RunTestWithBp(t, ` java_sdk_library { name: "foo", @@ -520,7 +520,7 @@ func TestJavaSdkLibrary_AccessOutputFiles_MissingScope(t *testing.T) { PrepareForTestWithJavaSdkLibraryFiles, FixtureWithLastReleaseApis("foo"), ). - ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "bar" variant "android_common": unsupported module reference tag ".system.stubs.source"`)). + ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "bar" variant "android_common": unsupported output tag ".system.stubs.source"`)). RunTestWithBp(t, ` java_sdk_library { name: "foo", diff --git a/java/support_libraries.go b/java/support_libraries.go index c483fc17a..f76eb116e 100644 --- a/java/support_libraries.go +++ b/java/support_libraries.go @@ -28,7 +28,7 @@ func init() { func supportLibrariesMakeVarsProvider(ctx android.MakeVarsContext) { var supportAars, supportJars []string - ctx.VisitAllModules(func(module android.Module) { + ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { dir := ctx.ModuleDir(module) switch { case strings.HasPrefix(dir, "prebuilts/sdk/current/extras"), @@ -47,11 +47,16 @@ func supportLibrariesMakeVarsProvider(ctx android.MakeVarsContext) { return } - switch module.(type) { - case *AndroidLibrary, *AARImport: + _, isAndroidLibrary := android.OtherModuleProvider(ctx, module, AndroidLibraryInfoProvider) + _, isAARImport := android.OtherModuleProvider(ctx, module, AARImportInfoProvider) + if isAndroidLibrary || isAARImport { supportAars = append(supportAars, name) - case *Library, *Import: - supportJars = append(supportJars, name) + } else { + _, isJavaLibrary := android.OtherModuleProvider(ctx, module, JavaLibraryInfoProvider) + _, isJavaPlugin := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider) + if isJavaLibrary && !isJavaPlugin { + supportJars = append(supportJars, name) + } } }) diff --git a/java/testing.go b/java/testing.go index 3abbb8453..d7878d68d 100644 --- a/java/testing.go +++ b/java/testing.go @@ -424,7 +424,6 @@ func gatherRequiredDepsForTest() string { "kotlin-stdlib-jdk8", "kotlin-annotations", "stub-annotations", - "aconfig-annotations-lib", "aconfig_storage_stub", "unsupportedappusage", diff --git a/java/tracereferences.go b/java/tracereferences.go new file mode 100644 index 000000000..342b6a630 --- /dev/null +++ b/java/tracereferences.go @@ -0,0 +1,54 @@ +// Copyright 2025 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 java + +import ( + "android/soong/android" + + "github.com/google/blueprint" +) + +var traceReferences = pctx.AndroidStaticRule("traceReferences", + blueprint.RuleParams{ + Command: `${config.TraceReferencesCmd} ` + + // Note that we suppress missing def errors, as we're only interested + // in the direct deps between the sources and target. + `--map-diagnostics:MissingDefinitionsDiagnostic error none ` + + `--keep-rules ` + + `--output ${out} ` + + `--target ${in} ` + + // `--source` and `--lib` are already prepended to each + // jar reference in the sources and libs joined string args. + `${sources} ` + + `${libs}`, + CommandDeps: []string{"${config.TraceReferencesCmd}"}, + }, "sources", "libs") + +// Generates keep rules in output corresponding to any references from sources +// (a list of jars) onto target (the referenced jar) that are not included in +// libs (a list of external jars). +func TraceReferences(ctx android.ModuleContext, sources android.Paths, target android.Path, libs android.Paths, + output android.WritablePath) { + ctx.Build(pctx, android.BuildParams{ + Rule: traceReferences, + Input: target, + Output: output, + Implicits: append(sources, libs...), + Args: map[string]string{ + "sources": android.JoinWithPrefix(sources.Strings(), "--source "), + "libs": android.JoinWithPrefix(libs.Strings(), "--lib "), + }, + }) +} diff --git a/linkerconfig/linkerconfig.go b/linkerconfig/linkerconfig.go index 43fe8aa33..925d7b163 100644 --- a/linkerconfig/linkerconfig.go +++ b/linkerconfig/linkerconfig.go @@ -127,7 +127,7 @@ func BuildLinkerConfig( for _, m := range requireModules { if _, ok := android.OtherModuleProvider(ctx, m, cc.CcInfoProvider); ok { if android.OtherModuleProviderOrDefault(ctx, m, cc.LinkableInfoProvider).HasStubsVariants && - !android.OtherModuleProviderOrDefault(ctx, m, android.CommonModuleInfoKey).Host { + !android.OtherModulePointerProviderOrDefault(ctx, m, android.CommonModuleInfoProvider).Host { name := ctx.OtherModuleName(m) if ccInfo, ok := android.OtherModuleProvider(ctx, m, cc.CcInfoProvider); ok && ccInfo.LinkerInfo != nil && ccInfo.LinkerInfo.ImplementationModuleName != nil { name = *ccInfo.LinkerInfo.ImplementationModuleName diff --git a/phony/phony.go b/phony/phony.go index 4f61c4583..e75f4c809 100644 --- a/phony/phony.go +++ b/phony/phony.go @@ -104,8 +104,7 @@ type PhonyRule struct { android.ModuleBase android.DefaultableModuleBase - phonyDepsModuleNames []string - properties PhonyProperties + properties PhonyProperties } type PhonyProperties struct { @@ -126,18 +125,8 @@ func PhonyRuleFactory() android.Module { } func (p *PhonyRule) GenerateAndroidBuildActions(ctx android.ModuleContext) { - p.phonyDepsModuleNames = p.properties.Phony_deps.GetOrDefault(ctx, nil) -} - -func (p *PhonyRule) AndroidMk() android.AndroidMkData { - return android.AndroidMkData{ - Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { - if len(p.phonyDepsModuleNames) > 0 { - depModulesStr := strings.Join(p.phonyDepsModuleNames, " ") - fmt.Fprintln(w, ".PHONY:", name) - fmt.Fprintln(w, name, ":", depModulesStr) - } - }, + for _, dep := range p.properties.Phony_deps.GetOrDefault(ctx, nil) { + ctx.Phony(ctx.ModuleName(), android.PathForPhony(ctx, dep)) } } diff --git a/provenance/provenance_metadata_proto/Android.bp b/provenance/provenance_metadata_proto/Android.bp index 7fc47a935..b4176a5e5 100644 --- a/provenance/provenance_metadata_proto/Android.bp +++ b/provenance/provenance_metadata_proto/Android.bp @@ -20,11 +20,6 @@ package { python_library_host { name: "provenance_metadata_proto", - version: { - py3: { - enabled: true, - }, - }, srcs: [ "provenance_metadata.proto", ], diff --git a/python/binary.go b/python/binary.go index feac72a26..f894299f9 100644 --- a/python/binary.go +++ b/python/binary.go @@ -125,6 +125,7 @@ func (p *PythonBinaryModule) GenerateAndroidBuildActions(ctx android.ModuleConte func (p *PythonBinaryModule) buildBinary(ctx android.ModuleContext) { embeddedLauncher := p.isEmbeddedLauncherEnabled() depsSrcsZips := p.collectPathsFromTransitiveDeps(ctx, embeddedLauncher) + bundleSharedLibs := p.collectSharedLibDeps(ctx) main := "" if p.autorun() { main = p.getPyMainFile(ctx, p.srcsPathMappings) @@ -149,6 +150,11 @@ func (p *PythonBinaryModule) buildBinary(ctx android.ModuleContext) { srcsZips = append(srcsZips, p.srcsZip) } srcsZips = append(srcsZips, depsSrcsZips...) + if ctx.Host() && len(bundleSharedLibs) > 0 { + // only bundle shared libs for host binaries + sharedLibZip := p.zipSharedLibs(ctx, bundleSharedLibs) + srcsZips = append(srcsZips, sharedLibZip) + } p.installSource = registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath, "python3", main, p.getStem(ctx), srcsZips) @@ -159,6 +165,10 @@ func (p *PythonBinaryModule) buildBinary(ctx android.ModuleContext) { sharedLibs = append(sharedLibs, ctx.OtherModuleName(dep)) } p.androidMkSharedLibs = sharedLibs + + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: p.binaryProperties.Test_suites, + }) } func (p *PythonBinaryModule) AndroidMkEntries() []android.AndroidMkEntries { diff --git a/python/python.go b/python/python.go index f8f41658f..de21e39bd 100644 --- a/python/python.go +++ b/python/python.go @@ -20,11 +20,13 @@ import ( "fmt" "path/filepath" "regexp" + "sort" "strings" "android/soong/cc" "github.com/google/blueprint" + "github.com/google/blueprint/depset" "github.com/google/blueprint/proptools" "android/soong/android" @@ -36,6 +38,7 @@ type PythonLibraryInfo struct { SrcsZip android.Path PrecompiledSrcsZip android.Path PkgPath string + BundleSharedLibs android.Paths } var PythonLibraryInfoProvider = blueprint.NewProvider[PythonLibraryInfo]() @@ -105,6 +108,10 @@ type BaseProperties struct { // list of the Python libraries compatible both with Python2 and Python3. Libs []string `android:"arch_variant"` + // TODO: b/403060602 - add unit tests for this property and related code + // list of shared libraries that should be packaged with the python code for this module. + Shared_libs []string `android:"arch_variant"` + Version struct { // Python2-specific properties, including whether Python2 is supported for this module // and version-specific sources, exclusions and dependencies. @@ -158,6 +165,10 @@ type PythonLibraryModule struct { precompiledSrcsZip android.Path sourceProperties android.SourceProperties + + // The shared libraries that should be bundled with the python code for + // any standalone python binaries that depend on this module. + bundleSharedLibs android.Paths } // newModule generates new Python base module @@ -197,6 +208,10 @@ func (p *PythonLibraryModule) getBaseProperties() *BaseProperties { return &p.properties } +func (p *PythonLibraryModule) getBundleSharedLibs() android.Paths { + return p.bundleSharedLibs +} + func (p *PythonLibraryModule) init() android.Module { p.AddProperties(&p.properties, &p.protoProperties, &p.sourceProperties) android.InitAndroidArchModule(p, p.hod, p.multilib) @@ -224,6 +239,7 @@ type installDependencyTag struct { var ( pythonLibTag = dependencyTag{name: "pythonLib"} javaDataTag = dependencyTag{name: "javaData"} + sharedLibTag = dependencyTag{name: "sharedLib"} // The python interpreter, with soong module name "py3-launcher" or "py3-launcher-autorun". launcherTag = dependencyTag{name: "launcher"} launcherSharedLibTag = installDependencyTag{name: "launcherSharedLib"} @@ -288,6 +304,12 @@ func (p *PythonLibraryModule) DepsMutator(ctx android.BottomUpMutatorContext) { javaDataVariation := []blueprint.Variation{{"arch", android.Common.String()}} ctx.AddVariationDependencies(javaDataVariation, javaDataTag, p.properties.Java_data...) + if ctx.Host() { + ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), sharedLibTag, p.properties.Shared_libs...) + } else if len(p.properties.Shared_libs) > 0 { + ctx.PropertyErrorf("shared_libs", "shared_libs is not supported for device builds") + } + p.AddDepsOnPythonLauncherAndStdlib(ctx, hostStdLibTag, hostLauncherTag, hostlauncherSharedLibTag, false, ctx.Config().BuildOSTarget) } @@ -377,6 +399,25 @@ func (p *PythonLibraryModule) GenerateAndroidBuildActions(ctx android.ModuleCont expandedData = append(expandedData, android.OutputFilesForModule(ctx, javaData, "")...) } + var directImplementationDeps android.Paths + var transitiveImplementationDeps []depset.DepSet[android.Path] + ctx.VisitDirectDepsProxyWithTag(sharedLibTag, func(dep android.ModuleProxy) { + sharedLibInfo, _ := android.OtherModuleProvider(ctx, dep, cc.SharedLibraryInfoProvider) + if sharedLibInfo.SharedLibrary != nil { + expandedData = append(expandedData, android.OutputFilesForModule(ctx, dep, "")...) + directImplementationDeps = append(directImplementationDeps, android.OutputFilesForModule(ctx, dep, "")...) + if info, ok := android.OtherModuleProvider(ctx, dep, cc.ImplementationDepInfoProvider); ok { + transitiveImplementationDeps = append(transitiveImplementationDeps, info.ImplementationDeps) + p.bundleSharedLibs = append(p.bundleSharedLibs, info.ImplementationDeps.ToList()...) + } + } else { + ctx.PropertyErrorf("shared_libs", "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep)) + } + }) + android.SetProvider(ctx, cc.ImplementationDepInfoProvider, &cc.ImplementationDepInfo{ + ImplementationDeps: depset.New(depset.PREORDER, directImplementationDeps, transitiveImplementationDeps), + }) + // Validate pkg_path property pkgPath := String(p.properties.Pkg_path) if pkgPath != "" { @@ -400,8 +441,7 @@ func (p *PythonLibraryModule) GenerateAndroidBuildActions(ctx android.ModuleCont // generate the zipfile of all source and data files p.srcsZip = p.createSrcsZip(ctx, pkgPath) - // TODO(b/388344853): precompilation temporarily disabled for python3.13 upgrade - p.precompiledSrcsZip = p.srcsZip //p.precompileSrcs(ctx) + p.precompiledSrcsZip = p.precompileSrcs(ctx) android.SetProvider(ctx, PythonLibraryInfoProvider, PythonLibraryInfo{ SrcsPathMappings: p.getSrcsPathMappings(), @@ -409,6 +449,7 @@ func (p *PythonLibraryModule) GenerateAndroidBuildActions(ctx android.ModuleCont SrcsZip: p.getSrcsZip(), PkgPath: p.getPkgPath(), PrecompiledSrcsZip: p.getPrecompiledSrcsZip(), + BundleSharedLibs: p.getBundleSharedLibs(), }) } @@ -685,6 +726,56 @@ func (p *PythonLibraryModule) collectPathsFromTransitiveDeps(ctx android.ModuleC return result } +func (p *PythonLibraryModule) collectSharedLibDeps(ctx android.ModuleContext) android.Paths { + seen := make(map[android.Module]bool) + + var result android.Paths + + ctx.WalkDepsProxy(func(child, _ android.ModuleProxy) bool { + // we only collect dependencies tagged as python library deps + if ctx.OtherModuleDependencyTag(child) != pythonLibTag { + return false + } + if seen[child] { + return false + } + seen[child] = true + dep, isLibrary := android.OtherModuleProvider(ctx, child, PythonLibraryInfoProvider) + if isLibrary { + result = append(result, dep.BundleSharedLibs...) + } + return true + }) + return result +} + +func (p *PythonLibraryModule) zipSharedLibs(ctx android.ModuleContext, bundleSharedLibs android.Paths) android.Path { + // sort the paths to keep the output deterministic + sort.Slice(bundleSharedLibs, func(i, j int) bool { + return bundleSharedLibs[i].String() < bundleSharedLibs[j].String() + }) + + parArgs := []string{"-symlinks=false", "-P lib64"} + paths := android.Paths{} + for _, path := range bundleSharedLibs { + // specify relative root of file in following -f arguments + parArgs = append(parArgs, `-C `+filepath.Dir(path.String())) + parArgs = append(parArgs, `-f `+path.String()) + paths = append(paths, path) + } + srcsZip := android.PathForModuleOut(ctx, ctx.ModuleName()+".sharedlibs.srcszip") + ctx.Build(pctx, android.BuildParams{ + Rule: zip, + Description: "bundle shared libraries for python binary", + Output: srcsZip, + Implicits: paths, + Args: map[string]string{ + "args": strings.Join(parArgs, " "), + }, + }) + return srcsZip +} + // chckForDuplicateOutputPath checks whether outputPath has already been included in map m, which // would result in two files being placed in the same location. // If there is a duplicate path, an error is thrown and true is returned diff --git a/python/scripts/main.py b/python/scripts/main.py index 225dbe4c1..35cdfc47e 100644 --- a/python/scripts/main.py +++ b/python/scripts/main.py @@ -1,5 +1,13 @@ + +import os import runpy +import shutil import sys +import tempfile +import zipfile + +from pathlib import PurePath + sys.argv[0] = __loader__.archive @@ -9,4 +17,32 @@ sys.argv[0] = __loader__.archive # when people try to use it. sys.executable = None -runpy._run_module_as_main("ENTRY_POINT", alter_argv=False) +# Extract the shared libraries from the zip file into a temporary directory. +# This works around the limitations of dynamic linker. Some Python libraries +# reference the .so files relatively and so extracting only the .so files +# does not work, so we extract the entire parent directory of the .so files to a +# tempdir and then add that to sys.path. +tempdir = None +with zipfile.ZipFile(__loader__.archive) as z: + # any root so files or root directories that contain so files will be + # extracted to the tempdir so the linker load them, this minimizes the + # number of files that need to be extracted to a tempdir + extract_paths = {} + for member in z.infolist(): + if member.filename.endswith('.so'): + extract_paths[PurePath(member.filename).parts[0]] = member.filename + if extract_paths: + tempdir = tempfile.mkdtemp() + for member in z.infolist(): + if not PurePath(member.filename).parts[0] in extract_paths.keys(): + continue + if member.is_dir(): + os.makedirs(os.path.join(tempdir, member.filename)) + else: + z.extract(member, tempdir) + sys.path.insert(0, tempdir) +try: + runpy._run_module_as_main("ENTRY_POINT", alter_argv=False) +finally: + if tempdir is not None: + shutil.rmtree(tempdir) diff --git a/rust/benchmark.go b/rust/benchmark.go index daba9642e..3aa2f1779 100644 --- a/rust/benchmark.go +++ b/rust/benchmark.go @@ -146,4 +146,8 @@ func (benchmark *benchmarkDecorator) moduleInfoJSON(ctx ModuleContext, moduleInf } else { moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite") } + + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: benchmark.Properties.Test_suites, + }) } diff --git a/rust/config/OWNERS b/rust/config/OWNERS index dfff87354..e4bf5e60c 100644 --- a/rust/config/OWNERS +++ b/rust/config/OWNERS @@ -1,2 +1,2 @@ -per-file global.go = srhines@google.com, chh@google.com, pirama@google.com, yikong@google.com +per-file global.go = srhines@google.com, pirama@google.com, yikong@google.com diff --git a/rust/doc.go b/rust/doc.go index fe205233d..3616c8ed5 100644 --- a/rust/doc.go +++ b/rust/doc.go @@ -37,14 +37,14 @@ func (n *rustdocSingleton) GenerateBuildActions(ctx android.SingletonContext) { FlagWithArg("-C ", docDir.String()). FlagWithArg("-D ", docDir.String()) - ctx.VisitAllModules(func(module android.Module) { - if !module.Enabled(ctx) { + ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { + if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled { return } - if m, ok := module.(*Module); ok { - if m.docTimestampFile.Valid() { - zipCmd.Implicit(m.docTimestampFile.Path()) + if m, ok := android.OtherModuleProvider(ctx, module, RustInfoProvider); ok { + if m.DocTimestampFile.Valid() { + zipCmd.Implicit(m.DocTimestampFile.Path()) } } }) diff --git a/rust/library_test.go b/rust/library_test.go index 6db95253f..6cc4f2517 100644 --- a/rust/library_test.go +++ b/rust/library_test.go @@ -426,6 +426,45 @@ func TestRustFFIExportedIncludes(t *testing.T) { android.AssertStringDoesContain(t, "cFlags for lib module", libfooStatic.Args["cFlags"], " -Irust_includes ") } +// Make sure cc_rustlibs_for_make has the expected behavior, and that +// cc_library_static does as well. +// This is here instead of cc/library_test.go because the test needs to +// define a rust_ffi module which can't be done in soong-cc to avoid the +// circular dependency. +func TestCCRustlibsForMake(t *testing.T) { + t.Parallel() + result := testRust(t, ` + rust_ffi_static { + name: "libbar", + srcs: ["foo.rs"], + crate_name: "bar", + export_include_dirs: ["rust_includes"], + host_supported: true, + } + + cc_rustlibs_for_make { + name: "libmakerustlibs", + whole_static_libs: ["libbar"], + } + + cc_library_static { + name: "libccstatic", + whole_static_libs: ["libbar"], + } + `) + + libmakerustlibs := result.ModuleForTests(t, "libmakerustlibs", "android_arm64_armv8-a_static").MaybeRule("rustc") + libccstatic := result.ModuleForTests(t, "libccstatic", "android_arm64_armv8-a_static").MaybeRule("rustc") + + if libmakerustlibs.Output == nil { + t.Errorf("cc_rustlibs_for_make is not generating a Rust staticlib when it should") + } + + if libccstatic.Output != nil { + t.Errorf("cc_library_static is generating a Rust staticlib when it should not") + } +} + func TestRustVersionScript(t *testing.T) { ctx := testRust(t, ` rust_library { diff --git a/rust/rust.go b/rust/rust.go index 4eebda301..54b5d92e3 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -60,6 +60,8 @@ type RustInfo struct { CompilerInfo *CompilerInfo SnapshotInfo *cc.SnapshotInfo SourceProviderInfo *SourceProviderInfo + XrefRustFiles android.Paths + DocTimestampFile android.OptionalPath } var RustInfoProvider = blueprint.NewProvider[*RustInfo]() @@ -1171,6 +1173,8 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { AndroidMkSuffix: mod.AndroidMkSuffix(), RustSubName: mod.Properties.RustSubName, TransitiveAndroidMkSharedLibs: mod.transitiveAndroidMkSharedLibs, + XrefRustFiles: mod.XrefRustFiles(), + DocTimestampFile: mod.docTimestampFile, } if mod.compiler != nil { rustInfo.CompilerInfo = &CompilerInfo{ @@ -1476,10 +1480,10 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { rustInfo, hasRustInfo := android.OtherModuleProvider(ctx, dep, RustInfoProvider) ccInfo, _ := android.OtherModuleProvider(ctx, dep, cc.CcInfoProvider) linkableInfo, hasLinkableInfo := android.OtherModuleProvider(ctx, dep, cc.LinkableInfoProvider) - commonInfo := android.OtherModuleProviderOrDefault(ctx, dep, android.CommonModuleInfoKey) + commonInfo := android.OtherModulePointerProviderOrDefault(ctx, dep, android.CommonModuleInfoProvider) if hasRustInfo && !linkableInfo.Static && !linkableInfo.Shared { //Handle Rust Modules - makeLibName := rustMakeLibName(rustInfo, linkableInfo, &commonInfo, depName+rustInfo.RustSubName) + makeLibName := rustMakeLibName(rustInfo, linkableInfo, commonInfo, depName+rustInfo.RustSubName) switch { case depTag == dylibDepTag: @@ -1624,7 +1628,7 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } } else if hasLinkableInfo { //Handle C dependencies - makeLibName := cc.MakeLibName(ccInfo, linkableInfo, &commonInfo, depName) + makeLibName := cc.MakeLibName(ccInfo, linkableInfo, commonInfo, depName) if !hasRustInfo { if commonInfo.Target.Os != ctx.Os() { ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName) @@ -2236,9 +2240,9 @@ type kytheExtractRustSingleton struct { func (k kytheExtractRustSingleton) GenerateBuildActions(ctx android.SingletonContext) { var xrefTargets android.Paths - ctx.VisitAllModules(func(module android.Module) { - if rustModule, ok := module.(xref); ok { - xrefTargets = append(xrefTargets, rustModule.XrefRustFiles()...) + ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { + if rustModule, ok := android.OtherModuleProvider(ctx, module, RustInfoProvider); ok { + xrefTargets = append(xrefTargets, rustModule.XrefRustFiles...) } }) if len(xrefTargets) > 0 { diff --git a/rust/test.go b/rust/test.go index 9833ffdb6..cedced260 100644 --- a/rust/test.go +++ b/rust/test.go @@ -165,7 +165,7 @@ func (test *testDecorator) install(ctx ModuleContext) { if linkableDep.OutputFile.Valid() { // Copy the output in "lib[64]" so that it's compatible with // the default rpath values. - commonInfo := android.OtherModuleProviderOrDefault(ctx, dep, android.CommonModuleInfoKey) + commonInfo := android.OtherModulePointerProviderOrDefault(ctx, dep, android.CommonModuleInfoProvider) libDir := "lib" if commonInfo.Target.Arch.ArchType.Multilib == "lib64" { libDir = "lib64" @@ -242,6 +242,10 @@ func (test *testDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags { flags.RustFlags = append(flags.RustFlags, "-Z panic_abort_tests") } + // Add a default rpath to allow tests to dlopen libraries specified in data_libs. + flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, `-Wl,-rpath,\$$ORIGIN/lib64`) + flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, `-Wl,-rpath,\$$ORIGIN/lib`) + return flags } @@ -316,6 +320,10 @@ func (test *testDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *and } else { moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite") } + + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: test.Properties.Test_suites, + }) } func rustTestHostMultilib(ctx android.LoadHookContext) { diff --git a/scripts/Android.bp b/scripts/Android.bp index 94163a5c2..c0e13d52f 100644 --- a/scripts/Android.bp +++ b/scripts/Android.bp @@ -287,9 +287,13 @@ python_test_host { ], } -sh_binary_host { - name: "keep-flagged-apis", - src: "keep-flagged-apis.sh", +python_binary_host { + name: "aconfig-to-metalava-flags", + main: "aconfig-to-metalava-flags.py", + srcs: ["aconfig-to-metalava-flags.py"], + libs: [ + "libaconfig_python_proto", + ], } python_binary_host { diff --git a/scripts/aconfig-to-metalava-flags.py b/scripts/aconfig-to-metalava-flags.py new file mode 100644 index 000000000..efa85ecb3 --- /dev/null +++ b/scripts/aconfig-to-metalava-flags.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2025 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. + +"""Converts a set of aconfig protobuf flags to a Metalava config file.""" + +# Formatted using `pyformat -i scripts/aconfig-to-metalava-flags.py` + +import argparse +import sys +import xml.etree.ElementTree as ET + +from protos import aconfig_pb2 + +_READ_ONLY = aconfig_pb2.flag_permission.READ_ONLY +_ENABLED = aconfig_pb2.flag_state.ENABLED +_DISABLED = aconfig_pb2.flag_state.DISABLED + +# The namespace of the Metalava config file. +CONFIG_NS = 'http://www.google.com/tools/metalava/config' + + +def config_name(tag: str): + """Create a QName in the config namespace. + + :param:tag the name of the entity in the config namespace. + """ + return f'{{{CONFIG_NS}}}{tag}' + + +def main(): + """Program entry point.""" + args_parser = argparse.ArgumentParser( + description='Generate Metalava flags config from aconfig protobuf', + ) + args_parser.add_argument( + 'input', + help='The path to the aconfig protobuf file', + ) + args = args_parser.parse_args(sys.argv[1:]) + + # Read the parsed_flags from the protobuf file. + with open(args.input, 'rb') as f: + parsed_flags = aconfig_pb2.parsed_flags.FromString(f.read()) + + # Create the structure of the XML config file. + config = ET.Element(config_name('config')) + api_flags = ET.SubElement(config, config_name('api-flags')) + # Create an <api-flag> element for each parsed_flag. + for flag in parsed_flags.parsed_flag: + if flag.permission == _READ_ONLY: + # Ignore any read only disabled flags as Metalava assumes that as the + # default when an <api-flags/> element is provided so this reduces the + # size of the file. + if flag.state == _DISABLED: + continue + mutability = 'immutable' + else: + mutability = 'mutable' + if flag.state == _ENABLED: + status = 'enabled' + else: + status = 'disabled' + attributes = { + 'package': flag.package, + 'name': flag.name, + 'mutability': mutability, + 'status': status, + } + # Convert the attribute names into qualified names in, what will become, the + # default namespace for the XML file. This is needed to ensure that the + # attribute will be written in the XML file without a prefix, e.g. + # `name="flag_name"`. Without it, a namespace prefix, e.g. `ns1`, will be + # synthesized for the attribute when writing the XML file, i.e. it + # will be written as `ns1:name="flag_name"`. Strictly speaking, that is + # unnecessary as the "Namespaces in XML 1.0 (Third Edition)" specification + # says that unprefixed attribute names have no namespace. + qualified_attributes = {config_name(k): v for (k, v) in attributes.items()} + ET.SubElement(api_flags, config_name('api-flag'), qualified_attributes) + + # Create a tree and add white space so it will pretty print when written out. + tree = ET.ElementTree(config) + ET.indent(tree) + + # Write the tree using the config namespace as the default. + tree.write(sys.stdout, encoding='unicode', default_namespace=CONFIG_NS) + sys.stdout.close() + + +if __name__ == '__main__': + main() diff --git a/scripts/gen_build_prop.py b/scripts/gen_build_prop.py index 74befd5de..a0d25465c 100644 --- a/scripts/gen_build_prop.py +++ b/scripts/gen_build_prop.py @@ -113,6 +113,7 @@ def generate_common_build_props(args): print("####################################") config = args.config + build_flags = config["BuildFlags"] partition = args.partition if partition == "system": @@ -164,6 +165,7 @@ def generate_common_build_props(args): print(f"ro.{partition}.build.version.release={config['Platform_version_last_stable']}") print(f"ro.{partition}.build.version.release_or_codename={config['Platform_version_name']}") print(f"ro.{partition}.build.version.sdk={config['Platform_sdk_version']}") + print(f"ro.{partition}.build.version.sdk_minor={build_flags['RELEASE_PLATFORM_SDK_MINOR_VERSION']}") def generate_build_info(args): print() @@ -196,6 +198,7 @@ def generate_build_info(args): print(f"ro.build.display.id?={config['BuildDesc']}") print(f"ro.build.version.incremental={config['BuildNumber']}") print(f"ro.build.version.sdk={config['Platform_sdk_version']}") + print(f"ro.build.version.sdk_minor={build_flags['RELEASE_PLATFORM_SDK_MINOR_VERSION']}") print(f"ro.build.version.preview_sdk={config['Platform_preview_sdk_version']}") print(f"ro.build.version.preview_sdk_fingerprint={config['PlatformPreviewSdkFingerprint']}") print(f"ro.build.version.codename={config['Platform_sdk_codename']}") diff --git a/scripts/keep-flagged-apis.sh b/scripts/keep-flagged-apis.sh deleted file mode 100755 index 48efb7a29..000000000 --- a/scripts/keep-flagged-apis.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash -e -# -# Copyright 2023 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. - -# Convert a list of flags in the input file to a list of metalava options -# that will keep the APIs for those flags will hiding all other flagged -# APIs. - -FLAGS="$1" - -FLAGGED="android.annotation.FlaggedApi" - -# Convert the list of feature flags in the input file to Metalava options -# of the form `--revert-annotation !android.annotation.FlaggedApi("<flag>")` -# to prevent the annotated APIs from being hidden, i.e. include the annotated -# APIs in the SDK snapshots. -while read -r line; do - # Escape and quote the key for sed - escaped_line=$(echo "$line" | sed "s/'/\\\'/g; s/ /\\ /g") - - echo "--revert-annotation '!$FLAGGED(\"$escaped_line\")'" -done < "$FLAGS" - -# Revert all flagged APIs, unless listed above. -echo "--revert-annotation $FLAGGED" diff --git a/scripts/manifest_check.py b/scripts/manifest_check.py index 175451e74..96dc5a6ce 100755 --- a/scripts/manifest_check.py +++ b/scripts/manifest_check.py @@ -132,7 +132,7 @@ def enforce_uses_libraries(manifest, required, optional, missing_optional, relax #pylint: disable=line-too-long errmsg = ''.join([ - 'mismatch in the <uses-library> tags between the build system and the ' + 'mismatch or misordering in the <uses-library> tags between the build system and the ' 'manifest:\n', '\t- required libraries in build system: %s[%s]%s\n' % (C_RED, ', '.join(required), C_OFF), '\t vs. in the manifest: %s[%s]%s\n' % (C_RED, ', '.join(manifest_required), C_OFF), diff --git a/scripts/microfactory.bash b/scripts/microfactory.bash index ce4a0e48a..49988fa29 100644 --- a/scripts/microfactory.bash +++ b/scripts/microfactory.bash @@ -23,7 +23,14 @@ # Ensure GOROOT is set to the in-tree version. case $(uname) in Linux) - export GOROOT="${TOP}/prebuilts/go/linux-x86/" + case $(uname -m) in + x86_64) + export GOROOT="${TOP}/prebuilts/go/linux-x86/" + ;; + aarch64) + export GOROOT="${TOP}/prebuilts/go/linux-arm64/" + ;; + esac ;; Darwin) export GOROOT="${TOP}/prebuilts/go/darwin-x86/" diff --git a/sh/sh_binary.go b/sh/sh_binary.go index f8d1ce523..57f5ad1c7 100644 --- a/sh/sh_binary.go +++ b/sh/sh_binary.go @@ -356,6 +356,8 @@ func (s *ShBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) { for _, symlink := range s.Symlinks() { ctx.InstallSymlink(installDir, symlink, s.installedFile) } + moduleInfoJSON := ctx.ModuleInfoJSON() + moduleInfoJSON.Class = []string{"EXECUTABLES"} } func (s *ShBinary) AndroidMkEntries() []android.AndroidMkEntries { @@ -508,7 +510,7 @@ func (s *ShTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { // so that it's compatible with the default rpath values. var relPath string linkableInfo := android.OtherModuleProviderOrDefault(ctx, dep, cc.LinkableInfoProvider) - commonInfo := android.OtherModuleProviderOrDefault(ctx, dep, android.CommonModuleInfoKey) + commonInfo := android.OtherModulePointerProviderOrDefault(ctx, dep, android.CommonModuleInfoProvider) if commonInfo.Target.Arch.ArchType.Multilib == "lib64" { relPath = filepath.Join("lib64", linkableInfo.OutputFile.Path().Base()) @@ -572,6 +574,10 @@ func (s *ShTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, s.testConfig.String()) } moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, s.extraTestConfigs.Strings()...) + + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: s.testProperties.Test_suites, + }) } func addArch(archType string, paths android.Paths) []string { @@ -607,6 +613,8 @@ func (s *ShTest) AndroidMkEntries() []android.AndroidMkEntries { entries.AddStrings("LOCAL_EXTRA_FULL_TEST_CONFIGS", s.extraTestConfigs.Strings()...) } + entries.SetBoolIfTrue("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", !proptools.BoolDefault(s.testProperties.Auto_gen_config, true)) + s.testProperties.Test_options.SetAndroidMkEntries(entries) }, }, diff --git a/tradefed_modules/test_module_config.go b/tradefed_modules/test_module_config.go index 988352cd2..2b341288a 100644 --- a/tradefed_modules/test_module_config.go +++ b/tradefed_modules/test_module_config.go @@ -162,6 +162,22 @@ func (m *testModuleConfigModule) GenerateAndroidBuildActions(ctx android.ModuleC m.validateBase(ctx, &testModuleConfigTag, "android_test", false) m.generateManifestAndConfig(ctx) + moduleInfoJSON := ctx.ModuleInfoJSON() + moduleInfoJSON.Class = []string{m.provider.MkAppClass} + if m.provider.MkAppClass != "NATIVE_TESTS" { + moduleInfoJSON.Tags = append(moduleInfoJSON.Tags, "tests") + } + if m.provider.IsUnitTest { + moduleInfoJSON.IsUnitTest = "true" + } + moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, m.tradefedProperties.Test_suites...) + moduleInfoJSON.SystemSharedLibs = []string{"none"} + moduleInfoJSON.ExtraRequired = append(moduleInfoJSON.ExtraRequired, m.provider.RequiredModuleNames...) + moduleInfoJSON.ExtraRequired = append(moduleInfoJSON.ExtraRequired, *m.Base) + moduleInfoJSON.ExtraHostRequired = append(moduleInfoJSON.ExtraRequired, m.provider.HostRequiredModuleNames...) + moduleInfoJSON.TestConfig = []string{m.testConfig.String()} + moduleInfoJSON.AutoTestConfig = []string{"true"} + moduleInfoJSON.TestModuleConfigBase = proptools.String(m.Base) } // Ensure at least one test_suite is listed. Ideally it should be general-tests @@ -410,6 +426,10 @@ func (m *testModuleConfigModule) generateManifestAndConfig(ctx android.ModuleCon LocalCertificate: m.provider.LocalCertificate, IsUnitTest: m.provider.IsUnitTest, }) + + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: m.tradefedProperties.Test_suites, + }) } var _ android.AndroidMkEntriesProvider = (*testModuleConfigHostModule)(nil) diff --git a/ui/build/androidmk_denylist.go b/ui/build/androidmk_denylist.go index 640a82d9a..cd49ec876 100644 --- a/ui/build/androidmk_denylist.go +++ b/ui/build/androidmk_denylist.go @@ -70,8 +70,8 @@ func blockAndroidMks(ctx Context, androidMks []string) { } } -// The Android.mk files in these directories are for NDK build system. -var external_ndk_androidmks []string = []string{ +var external_androidmks []string = []string{ + // The Android.mk files in these directories are for NDK build system. "external/fmtlib/", "external/google-breakpad/", "external/googletest/", @@ -83,6 +83,9 @@ var external_ndk_androidmks []string = []string{ "external/vulkan-validation-layers/", "external/walt/", "external/webp/", + // These directories hold the published Android SDK, used in Unbundled Gradle builds. + "prebuilts/fullsdk-darwin", + "prebuilts/fullsdk-linux", } var art_androidmks = []string{ @@ -90,8 +93,8 @@ var art_androidmks = []string{ } func ignoreSomeAndroidMks(androidMks []string) (filtered []string) { - ignore_androidmks := make([]string, 0, len(external_ndk_androidmks)+len(art_androidmks)) - ignore_androidmks = append(ignore_androidmks, external_ndk_androidmks...) + ignore_androidmks := make([]string, 0, len(external_androidmks)+len(art_androidmks)) + ignore_androidmks = append(ignore_androidmks, external_androidmks...) ignore_androidmks = append(ignore_androidmks, art_androidmks...) shouldKeep := func(androidmk string) bool { diff --git a/ui/build/config.go b/ui/build/config.go index a4f778d74..94b07811d 100644 --- a/ui/build/config.go +++ b/ui/build/config.go @@ -1117,11 +1117,18 @@ func (c *configImpl) ApiSurfacesOutDir() string { func (c *configImpl) PrebuiltOS() string { switch runtime.GOOS { case "linux": - return "linux-x86" + switch runtime.GOARCH { + case "amd64": + return "linux-x86" + case "arm64": + return "linux-arm64" + default: + panic(fmt.Errorf("Unknown GOARCH %s", runtime.GOARCH)) + } case "darwin": return "darwin-x86" default: - panic("Unknown GOOS") + panic(fmt.Errorf("Unknown GOOS %s", runtime.GOOS)) } } @@ -1711,13 +1718,7 @@ func (c *configImpl) hostCrossOut() string { } func (c *configImpl) HostPrebuiltTag() string { - if runtime.GOOS == "linux" { - return "linux-x86" - } else if runtime.GOOS == "darwin" { - return "darwin-x86" - } else { - panic("Unsupported OS") - } + return c.PrebuiltOS() } func (c *configImpl) KatiBin() string { diff --git a/ui/build/path.go b/ui/build/path.go index cc1d7e9c2..b92d79959 100644 --- a/ui/build/path.go +++ b/ui/build/path.go @@ -20,7 +20,6 @@ import ( "os" "os/exec" "path/filepath" - "runtime" "strings" "github.com/google/blueprint/microfactory" @@ -122,7 +121,7 @@ func SetupLitePath(ctx Context, config Config, tmpDir string) { myPath, _ = filepath.Abs(myPath) // Set up the checked-in prebuilts path directory for the current host OS. - prebuiltsPath, _ := filepath.Abs("prebuilts/build-tools/path/" + runtime.GOOS + "-x86") + prebuiltsPath, _ := filepath.Abs("prebuilts/build-tools/path/" + config.PrebuiltOS()) myPath = prebuiltsPath + string(os.PathListSeparator) + myPath // Set $PATH to be the directories containing the host tool symlinks, and @@ -258,7 +257,7 @@ func SetupPath(ctx Context, config Config) { // We put some prebuilts in $PATH, since it's infeasible to add dependencies // for all of them. - prebuiltsPath, _ := filepath.Abs("prebuilts/build-tools/path/" + runtime.GOOS + "-x86") + prebuiltsPath, _ := filepath.Abs("prebuilts/build-tools/path/" + config.PrebuiltOS()) myPath = prebuiltsPath + string(os.PathListSeparator) + myPath // Replace the $PATH variable with the path_interposer symlinks, and |