diff options
31 files changed, 631 insertions, 104 deletions
diff --git a/Android.bp b/Android.bp index 47a195c1d..98552a779 100644 --- a/Android.bp +++ b/Android.bp @@ -256,5 +256,8 @@ build_prop { all_apex_certs { name: "all_apex_certs", - visibility: ["//cts/tests/tests/security"], + visibility: [ + "//cts/tests/tests/security", + "//cts/hostsidetests/appsecurity", + ], } diff --git a/android/android_info.go b/android/android_info.go index a8d3d4e2c..225c8f0ae 100644 --- a/android/android_info.go +++ b/android/android_info.go @@ -58,17 +58,19 @@ func (p *androidInfoModule) GenerateAndroidBuildActions(ctx ModuleContext) { androidInfoTxtName := proptools.StringDefault(p.properties.Stem, ctx.ModuleName()+".txt") androidInfoTxt := PathForModuleOut(ctx, androidInfoTxtName) androidInfoProp := androidInfoTxt.ReplaceExtension(ctx, "prop") + timestamp := PathForModuleOut(ctx, "timestamp") if boardInfoFiles := PathsForModuleSrc(ctx, p.properties.Board_info_files); len(boardInfoFiles) > 0 { ctx.Build(pctx, BuildParams{ - Rule: mergeAndRemoveComments, - Inputs: boardInfoFiles, - Output: androidInfoTxt, + Rule: mergeAndRemoveComments, + Inputs: boardInfoFiles, + Output: androidInfoTxt, + Validation: timestamp, }) } else if bootloaderBoardName := proptools.String(p.properties.Bootloader_board_name); bootloaderBoardName != "" { - WriteFileRule(ctx, androidInfoTxt, "board="+bootloaderBoardName) + WriteFileRule(ctx, androidInfoTxt, "board="+bootloaderBoardName, timestamp) } else { - WriteFileRule(ctx, androidInfoTxt, "") + WriteFileRule(ctx, androidInfoTxt, "", timestamp) } // Create android_info.prop @@ -79,6 +81,19 @@ func (p *androidInfoModule) GenerateAndroidBuildActions(ctx ModuleContext) { }) ctx.SetOutputFiles(Paths{androidInfoProp}, "") + ctx.SetOutputFiles(Paths{androidInfoTxt}, ".txt") + + builder := NewRuleBuilder(pctx, ctx) + builder.Command().Text("touch").Output(timestamp) + if !ctx.Config().KatiEnabled() { + cpPath := PathForModuleInPartitionInstall(ctx, "").Join(ctx, androidInfoTxtName) + builder.Command(). + Text("rsync"). + Flag("-a"). + Input(androidInfoTxt). + Text(cpPath.String()) + } + builder.Build("copy_android_info", "Copy android-info.txt") } // android_info module generate a file named android-info.txt that contains various information @@ -86,6 +101,6 @@ func (p *androidInfoModule) GenerateAndroidBuildActions(ctx ModuleContext) { func AndroidInfoFactory() Module { module := &androidInfoModule{} module.AddProperties(&module.properties) - InitAndroidModule(module) + InitAndroidArchModule(module, DeviceSupported, MultilibCommon) return module } diff --git a/android/androidmk.go b/android/androidmk.go index 590cce361..87a93e396 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -701,11 +701,6 @@ func AndroidMkSingleton() Singleton { type androidMkSingleton struct{} func (c *androidMkSingleton) GenerateBuildActions(ctx SingletonContext) { - // Skip if Soong wasn't invoked from Make. - if !ctx.Config().KatiEnabled() { - return - } - var androidMkModulesList []blueprint.Module ctx.VisitAllModulesBlueprint(func(module blueprint.Module) { @@ -718,6 +713,12 @@ func (c *androidMkSingleton) GenerateBuildActions(ctx SingletonContext) { return ctx.ModuleName(androidMkModulesList[i]) < ctx.ModuleName(androidMkModulesList[j]) }) + // If running in soong-only mode, do a different, more limited version of this singleton + if !ctx.Config().KatiEnabled() { + c.soongOnlyBuildActions(ctx, androidMkModulesList) + return + } + transMk := PathForOutput(ctx, "Android"+String(ctx.Config().productVariables.Make_suffix)+".mk") if ctx.Failed() { return @@ -736,6 +737,122 @@ func (c *androidMkSingleton) GenerateBuildActions(ctx SingletonContext) { }) } +// In soong-only mode, we don't do most of the androidmk stuff. But disted files are still largely +// defined through the androidmk mechanisms, so this function is an alternate implementation of +// the androidmk singleton that just focuses on getting the dist contributions +func (c *androidMkSingleton) soongOnlyBuildActions(ctx SingletonContext, mods []blueprint.Module) { + allDistContributions := getDistContributionsFromMods(ctx, mods) + + distMkFile := absolutePath(filepath.Join(ctx.Config().katiPackageMkDir(), "dist.mk")) + + var goalOutputPairs []string + var srcDstPairs []string + for _, contributions := range allDistContributions { + for _, copiesForGoal := range contributions.copiesForGoals { + goals := strings.Fields(copiesForGoal.goals) + for _, copy := range copiesForGoal.copies { + for _, goal := range goals { + goalOutputPairs = append(goalOutputPairs, fmt.Sprintf(" %s:%s", goal, copy.dest)) + } + srcDstPairs = append(srcDstPairs, fmt.Sprintf(" %s:%s", copy.from.String(), copy.dest)) + } + } + } + // There are duplicates in the lists that we need to remove + goalOutputPairs = SortedUniqueStrings(goalOutputPairs) + srcDstPairs = SortedUniqueStrings(srcDstPairs) + var buf strings.Builder + buf.WriteString("DIST_SRC_DST_PAIRS :=") + for _, srcDstPair := range srcDstPairs { + buf.WriteString(srcDstPair) + } + buf.WriteString("\nDIST_GOAL_OUTPUT_PAIRS :=") + for _, goalOutputPair := range goalOutputPairs { + buf.WriteString(goalOutputPair) + } + buf.WriteString("\n") + + writeValueIfChanged(ctx, distMkFile, buf.String()) +} + +func writeValueIfChanged(ctx SingletonContext, path string, value string) { + if err := os.MkdirAll(filepath.Dir(path), 0777); err != nil { + ctx.Errorf("%s\n", err) + return + } + previousValue := "" + rawPreviousValue, err := os.ReadFile(path) + if err == nil { + previousValue = string(rawPreviousValue) + } + + if previousValue != value { + if err = os.WriteFile(path, []byte(value), 0666); err != nil { + ctx.Errorf("Failed to write: %v", err) + } + } +} + +func getDistContributionsFromMods(ctx fillInEntriesContext, mods []blueprint.Module) []distContributions { + var allDistContributions []distContributions + for _, mod := range mods { + if amod, ok := mod.(Module); ok && shouldSkipAndroidMkProcessing(ctx, amod.base()) { + 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) + if info.PrimaryInfo.disabled() { + continue + } + if contribution := info.PrimaryInfo.getDistContributions(ctx, mod); contribution != nil { + allDistContributions = append(allDistContributions, *contribution) + } + for _, ei := range info.ExtraInfo { + ei.fillInEntries(ctx, mod) + if ei.disabled() { + continue + } + if contribution := ei.getDistContributions(ctx, mod); contribution != nil { + allDistContributions = append(allDistContributions, *contribution) + } + } + } else { + switch x := mod.(type) { + case AndroidMkDataProvider: + data := x.AndroidMk() + + if data.Include == "" { + data.Include = "$(BUILD_PREBUILT)" + } + + data.fillInData(ctx, mod) + if data.Entries.disabled() { + continue + } + if contribution := data.Entries.getDistContributions(mod); contribution != nil { + allDistContributions = append(allDistContributions, *contribution) + } + case AndroidMkEntriesProvider: + entriesList := x.AndroidMkEntries() + for _, entries := range entriesList { + entries.fillInEntries(ctx, mod) + if entries.disabled() { + continue + } + if contribution := entries.getDistContributions(mod); contribution != nil { + allDistContributions = append(allDistContributions, *contribution) + } + } + default: + // Not exported to make so no make variables to set. + } + } + } + return allDistContributions +} + func translateAndroidMk(ctx SingletonContext, absMkFile string, moduleInfoJSONPath WritablePath, mods []blueprint.Module) error { buf := &bytes.Buffer{} diff --git a/android/config.go b/android/config.go index e9cb2cd31..87aacd5cb 100644 --- a/android/config.go +++ b/android/config.go @@ -83,6 +83,7 @@ type CmdArgs struct { OutDir string SoongOutDir string SoongVariables string + KatiSuffix string ModuleGraphFile string ModuleActionsFile string @@ -349,6 +350,7 @@ type config struct { // Changes behavior based on whether Kati runs after soong_build, or if soong_build // runs standalone. katiEnabled bool + katiSuffix string captureBuild bool // true for tests, saves build parameters for each module ignoreEnvironment bool // true for tests, returns empty from all Getenv calls @@ -620,6 +622,7 @@ func NewConfig(cmdArgs CmdArgs, availableEnv map[string]string) (Config, error) outDir: cmdArgs.OutDir, soongOutDir: cmdArgs.SoongOutDir, runGoTests: cmdArgs.RunGoTests, + katiSuffix: cmdArgs.KatiSuffix, multilibConflicts: make(map[ArchType]bool), moduleListFile: cmdArgs.ModuleListFile, @@ -1512,6 +1515,10 @@ func (c *config) VendorApiLevelFrozen() bool { return c.productVariables.GetBuildFlagBool("RELEASE_BOARD_API_LEVEL_FROZEN") } +func (c *config) katiPackageMkDir() string { + return filepath.Join(c.soongOutDir, "kati_packaging"+c.katiSuffix) +} + func (c *deviceConfig) Arches() []Arch { var arches []Arch for _, target := range c.config.Targets[Android] { @@ -2182,7 +2189,7 @@ var ( "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "com.android.adservices", "RELEASE_APEX_CONTRIBUTIONS_APPSEARCH": "com.android.appsearch", "RELEASE_APEX_CONTRIBUTIONS_ART": "com.android.art", - "RELEASE_APEX_CONTRIBUTIONS_BLUETOOTH": "com.android.btservices", + "RELEASE_APEX_CONTRIBUTIONS_BLUETOOTH": "com.android.bt", "RELEASE_APEX_CONTRIBUTIONS_CAPTIVEPORTALLOGIN": "", "RELEASE_APEX_CONTRIBUTIONS_CELLBROADCAST": "com.android.cellbroadcast", "RELEASE_APEX_CONTRIBUTIONS_CONFIGINFRASTRUCTURE": "com.android.configinfrastructure", diff --git a/android/container_violations.go b/android/container_violations.go index ba8f7d598..e1583c570 100644 --- a/android/container_violations.go +++ b/android/container_violations.go @@ -32,22 +32,22 @@ var ContainerDependencyViolationAllowlist = map[string][]string{ }, "Bluetooth": { - "app-compat-annotations", // apex [com.android.btservices] -> system - "framework-bluetooth-pre-jarjar", // apex [com.android.btservices] -> system + "app-compat-annotations", // apex [com.android.bt] -> system + "framework-bluetooth-pre-jarjar", // apex [com.android.bt] -> system }, "bluetooth-nano-protos": { - "libprotobuf-java-nano", // apex [com.android.btservices] -> apex [com.android.wifi, test_com.android.wifi] + "libprotobuf-java-nano", // apex [com.android.bt] -> apex [com.android.wifi, test_com.android.wifi] }, "bluetooth.change-ids": { - "app-compat-annotations", // apex [com.android.btservices] -> system + "app-compat-annotations", // apex [com.android.bt] -> system }, "CarServiceUpdatable": { "modules-utils-os", // apex [com.android.car.framework] -> apex [com.android.permission, test_com.android.permission] "modules-utils-preconditions", // apex [com.android.car.framework] -> apex [com.android.adservices, com.android.appsearch, com.android.cellbroadcast, com.android.extservices, com.android.ondevicepersonalization, com.android.tethering, com.android.uwb, com.android.wifi, test_com.android.cellbroadcast, test_com.android.wifi] - "modules-utils-shell-command-handler", // apex [com.android.car.framework] -> apex [com.android.adservices, com.android.art, com.android.art.debug, com.android.art.testing, com.android.btservices, com.android.configinfrastructure, com.android.mediaprovider, com.android.nfcservices, com.android.permission, com.android.scheduling, com.android.tethering, com.android.uwb, com.android.wifi, test_com.android.mediaprovider, test_com.android.permission, test_com.android.wifi, test_imgdiag_com.android.art, test_jitzygote_com.android.art] + "modules-utils-shell-command-handler", // apex [com.android.car.framework] -> apex [com.android.adservices, com.android.art, com.android.art.debug, com.android.art.testing, com.android.bt, com.android.configinfrastructure, com.android.mediaprovider, com.android.nfcservices, com.android.permission, com.android.scheduling, com.android.tethering, com.android.uwb, com.android.wifi, test_com.android.mediaprovider, test_com.android.permission, test_com.android.wifi, test_imgdiag_com.android.art, test_jitzygote_com.android.art] }, "cellbroadcastreceiver_aconfig_flags_lib": { @@ -414,10 +414,6 @@ var ContainerDependencyViolationAllowlist = map[string][]string{ "framework", // cts -> unstable }, - "CtsMediaBetterTogetherTestCases": { - "framework", // cts -> unstable - }, - "CtsMediaCodecTestCases": { "framework", // cts -> unstable }, @@ -478,6 +474,11 @@ var ContainerDependencyViolationAllowlist = map[string][]string{ "framework", // cts -> unstable }, + // TODO(b/387499846): Remove once migrated to sdk_version. + "CtsMediaRouterTestCases": { + "framework", // cts -> unstable + }, + "CtsMediaRouterHostSideTestBluetoothPermissionsApp": { "framework", // cts -> unstable }, @@ -490,6 +491,11 @@ var ContainerDependencyViolationAllowlist = map[string][]string{ "framework", // cts -> unstable }, + // TODO(b/387500109): Remove once migrated to sdk_version. + "CtsMediaSessionTestCases": { + "framework", // cts -> unstable + }, + "CtsMediaV2TestCases": { "framework", // cts -> unstable }, @@ -824,7 +830,7 @@ var ContainerDependencyViolationAllowlist = map[string][]string{ }, "devicelockcontroller-lib": { - "modules-utils-expresslog", // apex [com.android.devicelock] -> apex [com.android.btservices, com.android.car.framework] + "modules-utils-expresslog", // apex [com.android.devicelock] -> apex [com.android.bt, com.android.car.framework] }, "FederatedCompute": { @@ -836,7 +842,7 @@ var ContainerDependencyViolationAllowlist = map[string][]string{ }, "framework-bluetooth.impl": { - "app-compat-annotations", // apex [com.android.btservices] -> system + "app-compat-annotations", // apex [com.android.bt] -> system }, "framework-configinfrastructure.impl": { @@ -907,10 +913,6 @@ var ContainerDependencyViolationAllowlist = map[string][]string{ "libnativeloader_vendor_shared_lib", // system -> vendor }, - "MctsMediaBetterTogetherTestCases": { - "framework", // cts -> unstable - }, - "MctsMediaCodecTestCases": { "framework", // cts -> unstable }, @@ -947,6 +949,16 @@ var ContainerDependencyViolationAllowlist = map[string][]string{ "framework", // cts -> unstable }, + // TODO(b/387499846): Remove once migrated to sdk_version. + "MctsMediaRouterTestCases": { + "framework", // cts -> unstable + }, + + // TODO(b/387500109): Remove once migrated to sdk_version. + "MctsMediaSessionTestCases": { + "framework", // cts -> unstable + }, + "MctsMediaTranscodingTestCases": { "framework", // cts -> unstable }, @@ -1005,7 +1017,7 @@ var ContainerDependencyViolationAllowlist = map[string][]string{ }, "PlatformProperties": { - "sysprop-library-stub-platform", // apex [com.android.btservices, com.android.nfcservices, com.android.tethering, com.android.virt, com.android.wifi, test_com.android.wifi] -> system + "sysprop-library-stub-platform", // apex [com.android.bt, com.android.nfcservices, com.android.tethering, com.android.virt, com.android.wifi, test_com.android.wifi] -> system }, "safety-center-config": { @@ -1041,8 +1053,8 @@ var ContainerDependencyViolationAllowlist = map[string][]string{ }, "service-bluetooth-pre-jarjar": { - "framework-bluetooth-pre-jarjar", // apex [com.android.btservices] -> system - "service-bluetooth.change-ids", // apex [com.android.btservices] -> system + "framework-bluetooth-pre-jarjar", // apex [com.android.bt] -> system + "service-bluetooth.change-ids", // apex [com.android.bt] -> system }, "service-connectivity": { diff --git a/android/module.go b/android/module.go index 8faaa9f3a..e4a590457 100644 --- a/android/module.go +++ b/android/module.go @@ -1679,14 +1679,13 @@ func (m *ModuleBase) generateModuleTarget(ctx *moduleContext) { } }) - var deps Paths - var namespacePrefix string nameSpace := ctx.Namespace().Path if nameSpace != "." { namespacePrefix = strings.ReplaceAll(nameSpace, "/", ".") + "-" } + var deps Paths var info FinalModuleBuildTargetsInfo if len(allInstalledFiles) > 0 { @@ -1853,9 +1852,9 @@ type SourceFilesInfo struct { var SourceFilesInfoKey = 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 { - // Used by buildTargetSingleton to create checkbuild and per-directory build targets - // Only set on the final variant of each module InstallTarget WritablePath CheckbuildTarget WritablePath BlueprintDir string diff --git a/android/neverallow.go b/android/neverallow.go index d2117849d..e12e8b771 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -230,7 +230,7 @@ func createCcStubsRule() Rule { func createUncompressDexRules() []Rule { return []Rule{ NeverAllow(). - NotIn("art"). + NotIn("art", "cts/hostsidetests/compilation"). WithMatcher("uncompress_dex", isSetMatcherInstance). Because("uncompress_dex is only allowed for certain jars for test in art."), } diff --git a/android/phony.go b/android/phony.go index f8db88d43..7bdd9d31d 100644 --- a/android/phony.go +++ b/android/phony.go @@ -15,6 +15,7 @@ package android import ( + "strings" "sync" "github.com/google/blueprint" @@ -68,13 +69,25 @@ func (p *phonySingleton) GenerateBuildActions(ctx SingletonContext) { } if !ctx.Config().KatiEnabled() { + // In soong-only builds, the phonies can conflict with dist targets that will + // be generated in the packaging step. Instead of emitting a blueprint/ninja phony directly, + // create a makefile that defines the phonies that will be included in the packaging step. + // Make will dedup the phonies there. + var buildPhonyFileContents strings.Builder for _, phony := range p.phonyList { - ctx.Build(pctx, BuildParams{ - Rule: blueprint.Phony, - Outputs: []WritablePath{PathForPhony(ctx, phony)}, - Implicits: p.phonyMap[phony], - }) + buildPhonyFileContents.WriteString(".PHONY: ") + buildPhonyFileContents.WriteString(phony) + buildPhonyFileContents.WriteString("\n") + buildPhonyFileContents.WriteString(phony) + buildPhonyFileContents.WriteString(":") + for _, dep := range p.phonyMap[phony] { + buildPhonyFileContents.WriteString(" ") + buildPhonyFileContents.WriteString(dep.String()) + } + buildPhonyFileContents.WriteString("\n") } + buildPhonyFile := PathForOutput(ctx, "soong_phony_targets.mk") + writeValueIfChanged(ctx, absolutePath(buildPhonyFile.String()), buildPhonyFileContents.String()) } } diff --git a/android/raw_files.go b/android/raw_files.go index 9d7f5e82d..fd371965c 100644 --- a/android/raw_files.go +++ b/android/raw_files.go @@ -18,7 +18,6 @@ import ( "crypto/sha1" "encoding/hex" "fmt" - "github.com/google/blueprint" "io" "io/fs" "os" @@ -26,25 +25,27 @@ import ( "strings" "testing" + "github.com/google/blueprint" + "github.com/google/blueprint/proptools" ) // WriteFileRule creates a ninja rule to write contents to a file by immediately writing the // contents, plus a trailing newline, to a file in out/soong/raw-${TARGET_PRODUCT}, and then creating // a ninja rule to copy the file into place. -func WriteFileRule(ctx BuilderContext, outputFile WritablePath, content string) { - writeFileRule(ctx, outputFile, content, true, false) +func WriteFileRule(ctx BuilderContext, outputFile WritablePath, content string, validations ...Path) { + writeFileRule(ctx, outputFile, content, true, false, validations) } // WriteFileRuleVerbatim creates a ninja rule to write contents to a file by immediately writing the // contents to a file in out/soong/raw-${TARGET_PRODUCT}, and then creating a ninja rule to copy the file into place. -func WriteFileRuleVerbatim(ctx BuilderContext, outputFile WritablePath, content string) { - writeFileRule(ctx, outputFile, content, false, false) +func WriteFileRuleVerbatim(ctx BuilderContext, outputFile WritablePath, content string, validations ...Path) { + writeFileRule(ctx, outputFile, content, false, false, validations) } // WriteExecutableFileRuleVerbatim is the same as WriteFileRuleVerbatim, but runs chmod +x on the result -func WriteExecutableFileRuleVerbatim(ctx BuilderContext, outputFile WritablePath, content string) { - writeFileRule(ctx, outputFile, content, false, true) +func WriteExecutableFileRuleVerbatim(ctx BuilderContext, outputFile WritablePath, content string, validations ...Path) { + writeFileRule(ctx, outputFile, content, false, true, validations) } // tempFile provides a testable wrapper around a file in out/soong/.temp. It writes to a temporary file when @@ -124,7 +125,7 @@ func writeContentToTempFileAndHash(ctx BuilderContext, content string, newline b return tempFile, hex.EncodeToString(hash.Sum(nil)) } -func writeFileRule(ctx BuilderContext, outputFile WritablePath, content string, newline bool, executable bool) { +func writeFileRule(ctx BuilderContext, outputFile WritablePath, content string, newline bool, executable bool, validations Paths) { // Write the contents to a temporary file while computing its hash. tempFile, hash := writeContentToTempFileAndHash(ctx, content, newline) @@ -186,6 +187,7 @@ func writeFileRule(ctx BuilderContext, outputFile WritablePath, content string, Input: rawPath, Output: outputFile, Description: "raw " + outputFile.Base(), + Validations: validations, }) } diff --git a/android/variable.go b/android/variable.go index 6e46e9dab..4b6182781 100644 --- a/android/variable.go +++ b/android/variable.go @@ -697,6 +697,8 @@ type PartitionVariables struct { TargetScreenDensity string `json:",omitempty"` PrivateRecoveryUiProperties map[string]string `json:",omitempty"` + + PrebuiltBootloader string `json:",omitempty"` } func boolPtr(v bool) *bool { diff --git a/apex/apex.go b/apex/apex.go index 58960aca6..d39a17fe7 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1056,7 +1056,7 @@ var ( "com.android.appsearch", "com.android.art", "com.android.art.debug", - "com.android.btservices", + "com.android.bt", "com.android.cellbroadcast", "com.android.configinfrastructure", "com.android.conscrypt", diff --git a/apex/key.go b/apex/key.go index 9fa9d1e02..1622c65e6 100644 --- a/apex/key.go +++ b/apex/key.go @@ -182,6 +182,7 @@ type allApexCerts struct { } func (_ *allApexCerts) GenerateAndroidBuildActions(ctx android.ModuleContext) { + var avbpubkeys android.Paths var certificatesPem android.Paths ctx.VisitDirectDeps(func(m android.Module) { if apex, ok := m.(*apexBundle); ok { @@ -194,9 +195,12 @@ func (_ *allApexCerts) GenerateAndroidBuildActions(ctx android.ModuleContext) { } } certificatesPem = append(certificatesPem, pem) + // avbpubkey for signing the apex payload + avbpubkeys = append(avbpubkeys, apex.publicKeyFile) } }) certificatesPem = android.SortedUniquePaths(certificatesPem) // For hermiticity + avbpubkeys = android.SortedUniquePaths(avbpubkeys) // For hermiticity var certificatesDer android.Paths for index, certificatePem := range certificatesPem { certificateDer := android.PathForModuleOut(ctx, fmt.Sprintf("x509.%v.der", index)) @@ -209,6 +213,7 @@ func (_ *allApexCerts) GenerateAndroidBuildActions(ctx android.ModuleContext) { } ctx.SetOutputFiles(certificatesPem, ".pem") ctx.SetOutputFiles(certificatesDer, ".der") + ctx.SetOutputFiles(avbpubkeys, ".avbpubkey") } func (_ *allApexCerts) GenerateSingletonBuildActions(ctx android.SingletonContext) { diff --git a/cc/library.go b/cc/library.go index de09d530f..05661828b 100644 --- a/cc/library.go +++ b/cc/library.go @@ -1386,6 +1386,11 @@ func (library *libraryDecorator) sourceAbiDiff(ctx android.ModuleContext, extraFlags = append(extraFlags, "-allow-unreferenced-changes", "-allow-unreferenced-elf-symbol-changes") + // The functions in standard libraries are not always declared in the headers. + // Allow them to be added or removed without changing the symbols. + if isBionic(ctx.ModuleName()) { + extraFlags = append(extraFlags, "-allow-adding-removing-referenced-apis") + } } if isLlndk { extraFlags = append(extraFlags, "-consider-opaque-types-different") diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go index 6642023a5..cd4e9bdc2 100644 --- a/cmd/soong_build/main.go +++ b/cmd/soong_build/main.go @@ -64,6 +64,7 @@ func init() { flag.StringVar(&usedEnvFile, "used_env", "", "File containing used environment variables") flag.StringVar(&cmdlineArgs.OutDir, "out", "", "the ninja builddir directory") flag.StringVar(&cmdlineArgs.ModuleListFile, "l", "", "file that lists filepaths to parse") + flag.StringVar(&cmdlineArgs.KatiSuffix, "kati_suffix", "", "the suffix for kati and ninja files, so that different configurations don't clobber each other") // Debug flags flag.StringVar(&delveListen, "delve_listen", "", "Delve port to listen on for debugging") diff --git a/filesystem/android_device.go b/filesystem/android_device.go index fd8e9152a..83d56c638 100644 --- a/filesystem/android_device.go +++ b/filesystem/android_device.go @@ -15,6 +15,9 @@ package filesystem import ( + "strings" + "sync/atomic" + "android/soong/android" "github.com/google/blueprint" @@ -52,19 +55,33 @@ type PartitionNameProperties struct { Odm_dlkm_partition_name *string } +type DeviceProperties struct { + // Path to the prebuilt bootloader that would be copied to PRODUCT_OUT + Bootloader *string `android:"path"` + // Path to android-info.txt file containing board specific info. + Android_info *string `android:"path"` +} + type androidDevice struct { android.ModuleBase partitionProps PartitionNameProperties + + deviceProps DeviceProperties + + // copyToProductOutTimestamp for copying necessary files to PRODUCT_OUT + copyToProductOutTimestamp android.WritablePath } func AndroidDeviceFactory() android.Module { module := &androidDevice{} - module.AddProperties(&module.partitionProps) + module.AddProperties(&module.partitionProps, &module.deviceProps) android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibFirst) return module } +var numAutogeneratedAndroidDevicesOnceKey android.OnceKey = android.NewOnceKey("num_auto_generated_anroid_devices") + type partitionDepTagType struct { blueprint.BaseDependencyTag } @@ -79,6 +96,8 @@ func (a *androidDevice) DepsMutator(ctx android.BottomUpMutatorContext) { } addDependencyIfDefined(a.partitionProps.Boot_partition_name) + addDependencyIfDefined(a.partitionProps.Init_boot_partition_name) + addDependencyIfDefined(a.partitionProps.Vendor_boot_partition_name) addDependencyIfDefined(a.partitionProps.System_partition_name) addDependencyIfDefined(a.partitionProps.System_ext_partition_name) addDependencyIfDefined(a.partitionProps.Product_partition_name) @@ -88,13 +107,79 @@ func (a *androidDevice) DepsMutator(ctx android.BottomUpMutatorContext) { addDependencyIfDefined(a.partitionProps.System_dlkm_partition_name) addDependencyIfDefined(a.partitionProps.Vendor_dlkm_partition_name) addDependencyIfDefined(a.partitionProps.Odm_dlkm_partition_name) + addDependencyIfDefined(a.partitionProps.Recovery_partition_name) for _, vbmetaPartition := range a.partitionProps.Vbmeta_partitions { ctx.AddDependency(ctx.Module(), filesystemDepTag, vbmetaPartition) } } +func (a *androidDevice) copyToProductOut(ctx android.ModuleContext, builder *android.RuleBuilder, src android.Path, dest string) { + destPath := android.PathForModuleInPartitionInstall(ctx, "").Join(ctx, dest) + builder.Command().Text("rsync").Flag("-a").Flag("--checksum").Input(src).Text(destPath.String()) +} + +func (a *androidDevice) copyFilesToProductOut(ctx android.ModuleContext) { + a.copyToProductOutTimestamp = android.PathForModuleOut(ctx, "timestamp") + builder := android.NewRuleBuilder(pctx, ctx) + builder.Command().Text("touch").Output(a.copyToProductOutTimestamp) + + // List all individual files to be copied to PRODUCT_OUT here + if a.deviceProps.Bootloader != nil { + a.copyToProductOut(ctx, builder, android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Bootloader)), "bootloader") + } + + builder.Build("copy_to_product_out", "Copy files to PRODUCT_OUT") +} + func (a *androidDevice) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.buildTargetFilesZip(ctx) + var deps []android.Path + ctx.VisitDirectDepsWithTag(filesystemDepTag, func(m android.Module) { + imageOutput, ok := android.OtherModuleProvider(ctx, m, android.OutputFilesProvider) + if !ok { + ctx.ModuleErrorf("Partition module %s doesn't set OutputfilesProvider", m.Name()) + } + if len(imageOutput.DefaultOutputFiles) != 1 { + ctx.ModuleErrorf("Partition module %s should provide exact 1 output file", m.Name()) + } + deps = append(deps, imageOutput.DefaultOutputFiles[0]) + }) + + a.copyFilesToProductOut(ctx) + + allImagesStamp := android.PathForModuleOut(ctx, "all_images_stamp") + ctx.Build(pctx, android.BuildParams{ + Rule: android.Touch, + Output: allImagesStamp, + Implicits: deps, + Validation: a.copyToProductOutTimestamp, + }) + ctx.SetOutputFiles(android.Paths{allImagesStamp}, "") + ctx.CheckbuildFile(allImagesStamp) + + if ctx.OtherModuleIsAutoGenerated(ctx.Module()) { + numAutogeneratedAndroidDevices := ctx.Config().Once(numAutogeneratedAndroidDevicesOnceKey, func() interface{} { + return &atomic.Int32{} + }).(*atomic.Int32) + total := numAutogeneratedAndroidDevices.Add(1) + if total > 1 { + // There should only be 1 autogenerated android_device module. That one will be + // made the default thing to build in soong-only builds. + ctx.ModuleErrorf("There cannot be more than 1 autogenerated android_device module") + } + } + + if !ctx.Config().KatiEnabled() && ctx.OtherModuleIsAutoGenerated(ctx.Module()) { + // In soong-only builds, build this module by default. + // This is the analogue to this make code: + // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/main.mk;l=1396;drc=6595459cdd8164a6008335f6372c9f97b9094060 + ctx.Phony("droidcore-unbundled", allImagesStamp) + } +} + +type targetFilesZipCopy struct { + srcModule *string + destSubdir string } func (a *androidDevice) buildTargetFilesZip(ctx android.ModuleContext) { @@ -104,27 +189,81 @@ func (a *androidDevice) buildTargetFilesZip(ctx android.ModuleContext) { builder := android.NewRuleBuilder(pctx, ctx) builder.Command().Textf("rm -rf %s", targetFilesDir.String()) builder.Command().Textf("mkdir -p %s", targetFilesDir.String()) - partitionToSubdir := map[*string]string{ - a.partitionProps.System_partition_name: "SYSTEM", - a.partitionProps.System_ext_partition_name: "SYSTEM_EXT", - a.partitionProps.Product_partition_name: "PRODUCT", - a.partitionProps.Vendor_partition_name: "VENDOR", - a.partitionProps.Odm_partition_name: "ODM", - a.partitionProps.System_dlkm_partition_name: "SYSTEM_DLKM", - a.partitionProps.Vendor_dlkm_partition_name: "VENDOR_DLKM", - a.partitionProps.Odm_dlkm_partition_name: "ODM_DLKM", + toCopy := []targetFilesZipCopy{ + targetFilesZipCopy{a.partitionProps.System_partition_name, "SYSTEM"}, + targetFilesZipCopy{a.partitionProps.System_ext_partition_name, "SYSTEM_EXT"}, + targetFilesZipCopy{a.partitionProps.Product_partition_name, "PRODUCT"}, + targetFilesZipCopy{a.partitionProps.Vendor_partition_name, "VENDOR"}, + targetFilesZipCopy{a.partitionProps.Odm_partition_name, "ODM"}, + targetFilesZipCopy{a.partitionProps.System_dlkm_partition_name, "SYSTEM_DLKM"}, + targetFilesZipCopy{a.partitionProps.Vendor_dlkm_partition_name, "VENDOR_DLKM"}, + targetFilesZipCopy{a.partitionProps.Odm_dlkm_partition_name, "ODM_DLKM"}, + targetFilesZipCopy{a.partitionProps.Init_boot_partition_name, "BOOT/RAMDISK"}, + targetFilesZipCopy{a.partitionProps.Init_boot_partition_name, "INIT_BOOT/RAMDISK"}, + targetFilesZipCopy{a.partitionProps.Vendor_boot_partition_name, "VENDOR_BOOT/RAMDISK"}, } - for partition, subdir := range partitionToSubdir { - if partition == nil { + // TODO: Handle cases where recovery files are copied to BOOT/ or RECOVERY/ + // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=6211-6219?q=core%2FMakefile&ss=android%2Fplatform%2Fsuperproject%2Fmain + if ctx.DeviceConfig().BoardMoveRecoveryResourcesToVendorBoot() { + toCopy = append(toCopy, targetFilesZipCopy{a.partitionProps.Recovery_partition_name, "VENDOR_BOOT/RAMDISK"}) + } + + for _, zipCopy := range toCopy { + if zipCopy.srcModule == nil { continue } - fsInfo := a.getFilesystemInfo(ctx, *partition) + fsInfo := a.getFilesystemInfo(ctx, *zipCopy.srcModule) + subdir := zipCopy.destSubdir + rootDirString := fsInfo.RootDir.String() + if subdir == "SYSTEM" { + rootDirString = rootDirString + "/system" + } builder.Command().Textf("mkdir -p %s/%s", targetFilesDir.String(), subdir) builder.Command(). BuiltTool("acp"). - Textf("-rd %s/. %s/%s", fsInfo.RootDir, targetFilesDir, subdir). + Textf("-rd %s/. %s/%s", rootDirString, targetFilesDir, subdir). Implicit(fsInfo.Output) // so that the staging dir is built + + if subdir == "SYSTEM" { + // Create the ROOT partition in target_files.zip + builder.Command().Textf("rsync --links --exclude=system/* %s/ -r %s/ROOT", fsInfo.RootDir, targetFilesDir.String()) + } } + // Copy cmdline, kernel etc. files of boot images + if a.partitionProps.Vendor_boot_partition_name != nil { + bootImg := ctx.GetDirectDepWithTag(proptools.String(a.partitionProps.Vendor_boot_partition_name), filesystemDepTag) + bootImgInfo, _ := android.OtherModuleProvider(ctx, bootImg, BootimgInfoProvider) + builder.Command().Textf("echo %s > %s/VENDOR_BOOT/cmdline", proptools.ShellEscape(strings.Join(bootImgInfo.Cmdline, " ")), targetFilesDir) + builder.Command().Textf("echo %s > %s/VENDOR_BOOT/vendor_cmdline", proptools.ShellEscape(strings.Join(bootImgInfo.Cmdline, " ")), targetFilesDir) + if bootImgInfo.Dtb != nil { + builder.Command().Textf("cp %s %s/VENDOR_BOOT/dtb", bootImgInfo.Dtb, targetFilesDir) + } + if bootImgInfo.Bootconfig != nil { + builder.Command().Textf("cp %s %s/VENDOR_BOOT/vendor_bootconfig", bootImgInfo.Bootconfig, targetFilesDir) + } + } + if a.partitionProps.Boot_partition_name != nil { + bootImg := ctx.GetDirectDepWithTag(proptools.String(a.partitionProps.Boot_partition_name), filesystemDepTag) + bootImgInfo, _ := android.OtherModuleProvider(ctx, bootImg, BootimgInfoProvider) + builder.Command().Textf("echo %s > %s/BOOT/cmdline", proptools.ShellEscape(strings.Join(bootImgInfo.Cmdline, " ")), targetFilesDir) + if bootImgInfo.Dtb != nil { + builder.Command().Textf("cp %s %s/BOOT/dtb", bootImgInfo.Dtb, targetFilesDir) + } + if bootImgInfo.Kernel != nil { + builder.Command().Textf("cp %s %s/BOOT/kernel", bootImgInfo.Kernel, targetFilesDir) + // Even though kernel is not used to build vendor_boot, copy the kernel to VENDOR_BOOT to match the behavior of make packaging. + builder.Command().Textf("cp %s %s/VENDOR_BOOT/kernel", bootImgInfo.Kernel, targetFilesDir) + } + if bootImgInfo.Bootconfig != nil { + builder.Command().Textf("cp %s %s/BOOT/bootconfig", bootImgInfo.Bootconfig, targetFilesDir) + } + } + + if a.deviceProps.Android_info != nil { + builder.Command().Textf("mkdir -p %s/OTA", targetFilesDir) + builder.Command().Textf("cp %s %s/OTA/android-info.txt", android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Android_info)), targetFilesDir) + } + builder.Command(). BuiltTool("soong_zip"). Text("-d"). diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go index 36b1a1870..0a3a1773f 100644 --- a/filesystem/bootimg.go +++ b/filesystem/bootimg.go @@ -197,12 +197,8 @@ func (b *bootimg) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.PropertyErrorf("kernel_prebuilt", "boot partition must have kernel") return } - var kernel android.Path - if kernelProp != "" { - kernel = android.PathForModuleSrc(ctx, kernelProp) - } - unsignedOutput := b.buildBootImage(ctx, kernel) + unsignedOutput := b.buildBootImage(ctx, b.getKernelPath(ctx)) output := unsignedOutput if proptools.Bool(b.properties.Use_avb) { @@ -213,7 +209,7 @@ func (b *bootimg) GenerateAndroidBuildActions(ctx android.ModuleContext) { case "default": output = b.signImage(ctx, unsignedOutput) case "make_legacy": - output = b.addAvbFooter(ctx, unsignedOutput, kernel) + output = b.addAvbFooter(ctx, unsignedOutput, b.getKernelPath(ctx)) default: ctx.PropertyErrorf("avb_mode", `Unknown value for avb_mode, expected "default" or "make_legacy", got: %q`, *b.properties.Avb_mode) } @@ -224,6 +220,58 @@ func (b *bootimg) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.SetOutputFiles([]android.Path{output}, "") b.output = output + + // Set the Filesystem info of the ramdisk dependency. + // `android_device` will use this info to package `target_files.zip` + if ramdisk := proptools.String(b.properties.Ramdisk_module); ramdisk != "" { + ramdiskModule := ctx.GetDirectDepWithTag(ramdisk, bootimgRamdiskDep) + fsInfo, _ := android.OtherModuleProvider(ctx, ramdiskModule, FilesystemProvider) + android.SetProvider(ctx, FilesystemProvider, fsInfo) + } + + // Set BootimgInfo for building target_files.zip + android.SetProvider(ctx, BootimgInfoProvider, BootimgInfo{ + Cmdline: b.properties.Cmdline, + Kernel: b.getKernelPath(ctx), + Dtb: b.getDtbPath(ctx), + Bootconfig: b.getBootconfigPath(ctx), + }) +} + +var BootimgInfoProvider = blueprint.NewProvider[BootimgInfo]() + +type BootimgInfo struct { + Cmdline []string + Kernel android.Path + Dtb android.Path + Bootconfig android.Path +} + +func (b *bootimg) getKernelPath(ctx android.ModuleContext) android.Path { + var kernelPath android.Path + kernelName := proptools.String(b.properties.Kernel_prebuilt) + if kernelName != "" { + kernelPath = android.PathForModuleSrc(ctx, kernelName) + } + return kernelPath +} + +func (b *bootimg) getDtbPath(ctx android.ModuleContext) android.Path { + var dtbPath android.Path + dtbName := proptools.String(b.properties.Dtb_prebuilt) + if dtbName != "" { + dtbPath = android.PathForModuleSrc(ctx, dtbName) + } + return dtbPath +} + +func (b *bootimg) getBootconfigPath(ctx android.ModuleContext) android.Path { + var bootconfigPath android.Path + bootconfigName := proptools.String(b.properties.Bootconfig) + if bootconfigName != "" { + bootconfigPath = android.PathForModuleSrc(ctx, bootconfigName) + } + return bootconfigPath } func (b *bootimg) buildBootImage(ctx android.ModuleContext, kernel android.Path) android.Path { @@ -242,10 +290,8 @@ func (b *bootimg) buildBootImage(ctx android.ModuleContext, kernel android.Path) cmd.FlagWithArg("--os_patch_level ", ctx.Config().PlatformSecurityPatch()) } - dtbName := proptools.String(b.properties.Dtb_prebuilt) - if dtbName != "" { - dtb := android.PathForModuleSrc(ctx, dtbName) - cmd.FlagWithInput("--dtb ", dtb) + if b.getDtbPath(ctx) != nil { + cmd.FlagWithInput("--dtb ", b.getDtbPath(ctx)) } cmdline := strings.Join(b.properties.Cmdline, " ") @@ -372,6 +418,10 @@ func (b *bootimg) addAvbFooter(ctx android.ModuleContext, unsignedImage android. cmd.FlagWithArg("--rollback_index ", strconv.FormatInt(*b.properties.Avb_rollback_index, 10)) } + if !ctx.Config().KatiEnabled() { + copyImageFileToProductOut(ctx, builder, b.bootImageType.String(), output) + } + builder.Build("add_avb_footer", fmt.Sprintf("Adding avb footer to %s", b.BaseModuleName())) return output } @@ -387,6 +437,10 @@ func (b *bootimg) signImage(ctx android.ModuleContext, unsignedImage android.Pat Implicits(toolDeps). Output(output) + if !ctx.Config().KatiEnabled() { + copyImageFileToProductOut(ctx, builder, b.bootImageType.String(), output) + } + builder.Build("sign_bootimg", fmt.Sprintf("Signing %s", b.BaseModuleName())) return output } diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index bd8018b80..b112568f6 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -459,6 +459,7 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { FileListFile: fileListFile, RootDir: rootDir, }) + f.fileListFile = fileListFile if proptools.Bool(f.properties.Unchecked_module) { @@ -593,11 +594,16 @@ func (f *filesystem) copyPackagingSpecs(ctx android.ModuleContext, builder *andr } func (f *filesystem) copyFilesToProductOut(ctx android.ModuleContext, builder *android.RuleBuilder, rebasedDir android.OutputPath) { - if f.Name() != ctx.Config().SoongDefinedSystemImage() { + if !(f.Name() == ctx.Config().SoongDefinedSystemImage() || proptools.Bool(f.properties.Is_auto_generated)) { return } installPath := android.PathForModuleInPartitionInstall(ctx, f.partitionName()) - builder.Command().Textf("cp -prf %s/* %s", rebasedDir, installPath) + builder.Command().Textf("rsync --checksum %s %s", rebasedDir, installPath) +} + +func copyImageFileToProductOut(ctx android.ModuleContext, builder *android.RuleBuilder, partition string, output android.Path) { + copyDir := android.PathForModuleInPartitionInstall(ctx, "").Join(ctx, fmt.Sprintf("%s.img", partition)) + builder.Command().Textf("rsync -a %s %s", output, copyDir) } func (f *filesystem) rootDirString() string { @@ -651,6 +657,10 @@ func (f *filesystem) buildImageUsingBuildImage(ctx android.ModuleContext) (andro Output(output). Text(rootDir.String()) // directory where to find fs_config_files|dirs + if !ctx.Config().KatiEnabled() { + copyImageFileToProductOut(ctx, builder, f.partitionName(), output) + } + // rootDir is not deleted. Might be useful for quick inspection. builder.Build("build_filesystem_image", fmt.Sprintf("Creating filesystem %s", f.BaseModuleName())) diff --git a/filesystem/vbmeta.go b/filesystem/vbmeta.go index 6a4785933..c8b467579 100644 --- a/filesystem/vbmeta.go +++ b/filesystem/vbmeta.go @@ -281,6 +281,10 @@ func (v *vbmeta) GenerateAndroidBuildActions(ctx android.ModuleContext) { FlagWithArg("-s ", strconv.Itoa(vbmetaMaxSize)). Output(output) + if !ctx.Config().KatiEnabled() { + copyImageFileToProductOut(ctx, builder, v.partitionName(), output) + } + builder.Build("vbmeta", fmt.Sprintf("vbmeta %s", ctx.ModuleName())) v.installDir = android.PathForModuleInstall(ctx, "etc") diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go index 41faf948a..590d33ae4 100644 --- a/fsgen/filesystem_creator.go +++ b/fsgen/filesystem_creator.go @@ -128,6 +128,8 @@ func (f *filesystemCreator) createInternalModules(ctx android.LoadHookContext) { f.properties.Unsupported_partition_types = append(f.properties.Unsupported_partition_types, partitionType) } } + // Create android_info.prop + f.createAndroidInfo(ctx) partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse dtbImg := createDtbImgFilegroup(ctx) @@ -161,7 +163,7 @@ func (f *filesystemCreator) createInternalModules(ctx android.LoadHookContext) { if buildingSuperImage(partitionVars) { createSuperImage(ctx, finalSoongGeneratedPartitions, partitionVars) - f.properties.Super_image = ":" + generatedModuleName(ctx.Config(), "super") + f.properties.Super_image = ":" + generatedModuleNameForPartition(ctx.Config(), "super") } ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).soongGeneratedPartitions = finalSoongGeneratedPartitions @@ -180,15 +182,37 @@ func generatedModuleNameForPartition(cfg android.Config, partitionType string) s return generatedModuleName(cfg, fmt.Sprintf("%s_image", partitionType)) } +func (f *filesystemCreator) createBootloaderFilegroup(ctx android.LoadHookContext) (string, bool) { + bootloaderPath := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.PrebuiltBootloader + if len(bootloaderPath) == 0 { + return "", false + } + + bootloaderFilegroupName := generatedModuleName(ctx.Config(), "bootloader") + filegroupProps := &struct { + Name *string + Srcs []string + Visibility []string + }{ + Name: proptools.StringPtr(bootloaderFilegroupName), + Srcs: []string{bootloaderPath}, + Visibility: []string{"//visibility:public"}, + } + ctx.CreateModuleInDirectory(android.FileGroupFactory, ".", filegroupProps) + return bootloaderFilegroupName, true +} + func (f *filesystemCreator) createDeviceModule( ctx android.LoadHookContext, generatedPartitionTypes []string, vbmetaPartitions []string, ) { baseProps := &struct { - Name *string + Name *string + Android_info *string }{ - Name: proptools.StringPtr(generatedModuleName(ctx.Config(), "device")), + Name: proptools.StringPtr(generatedModuleName(ctx.Config(), "device")), + Android_info: proptools.StringPtr(":" + generatedModuleName(ctx.Config(), "android_info.prop{.txt}")), } // Currently, only the system and system_ext partition module is created. @@ -234,7 +258,12 @@ func (f *filesystemCreator) createDeviceModule( } partitionProps.Vbmeta_partitions = vbmetaPartitions - ctx.CreateModule(filesystem.AndroidDeviceFactory, baseProps, partitionProps) + deviceProps := &filesystem.DeviceProperties{} + if bootloader, ok := f.createBootloaderFilegroup(ctx); ok { + deviceProps.Bootloader = proptools.StringPtr(":" + bootloader) + } + + ctx.CreateModule(filesystem.AndroidDeviceFactory, baseProps, partitionProps, deviceProps) } func partitionSpecificFsProps(ctx android.EarlyModuleContext, fsProps *filesystem.FilesystemProperties, partitionVars android.PartitionVariables, partitionType string) { @@ -575,8 +604,8 @@ func (f *filesystemCreator) createPrebuiltKernelModules(ctx android.LoadHookCont (*fsGenState.fsDeps[partitionType])[name] = defaultDepCandidateProps(ctx.Config()) } -// Create a build_prop and android_info module. This will be used to create /vendor/build.prop -func (f *filesystemCreator) createVendorBuildProp(ctx android.LoadHookContext) { +// Create an android_info module. This will be used to create /vendor/build.prop +func (f *filesystemCreator) createAndroidInfo(ctx android.LoadHookContext) { // Create a android_info for vendor // The board info files might be in a directory outside the root soong namespace, so create // the module in "." @@ -600,7 +629,9 @@ func (f *filesystemCreator) createVendorBuildProp(ctx android.LoadHookContext) { androidInfoProps, ) androidInfoProp.HideFromMake() - // Create a build prop for vendor +} + +func (f *filesystemCreator) createVendorBuildProp(ctx android.LoadHookContext) { vendorBuildProps := &struct { Name *string Vendor *bool @@ -613,7 +644,7 @@ func (f *filesystemCreator) createVendorBuildProp(ctx android.LoadHookContext) { Vendor: proptools.BoolPtr(true), Stem: proptools.StringPtr("build.prop"), Product_config: proptools.StringPtr(":product_config"), - Android_info: proptools.StringPtr(":" + androidInfoProp.Name()), + Android_info: proptools.StringPtr(":" + generatedModuleName(ctx.Config(), "android_info.prop")), Licenses: []string{"Android-Apache-2.0"}, } vendorBuildProp := ctx.CreateModule( diff --git a/fsgen/super_img.go b/fsgen/super_img.go index 8ee3bf2ee..a36f61444 100644 --- a/fsgen/super_img.go +++ b/fsgen/super_img.go @@ -19,6 +19,7 @@ import ( "android/soong/android" "android/soong/filesystem" + "github.com/google/blueprint/proptools" ) @@ -30,7 +31,7 @@ func createSuperImage(ctx android.LoadHookContext, partitions []string, partitio baseProps := &struct { Name *string }{ - Name: proptools.StringPtr(generatedModuleName(ctx.Config(), "super")), + Name: proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "super")), } superImageProps := &filesystem.SuperImageProperties{ diff --git a/java/app_import.go b/java/app_import.go index f593c0297..35a054fa0 100644 --- a/java/app_import.go +++ b/java/app_import.go @@ -43,6 +43,12 @@ var ( Description: "Uncompress embedded JNI libs", }) + stripEmbeddedJniLibsUnusedArchRule = pctx.AndroidStaticRule("strip-embedded-jni-libs-from-unused-arch", blueprint.RuleParams{ + Command: `${config.Zip2ZipCmd} -i $in -o $out -x 'lib/**/*.so' $extraArgs`, + CommandDeps: []string{"${config.Zip2ZipCmd}"}, + Description: "Remove all JNI libs from unused architectures", + }, "extraArgs") + uncompressDexRule = pctx.AndroidStaticRule("uncompress-dex", blueprint.RuleParams{ Command: `if (zipinfo $in '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then ` + `${config.Zip2ZipCmd} -i $in -o $out -0 'classes*.dex'` + @@ -150,6 +156,9 @@ type AndroidAppImportProperties struct { // the prebuilt is Name() without "prebuilt_" prefix Source_module_name *string + // Whether stripping all libraries from unused architectures. + Strip_unused_jni_arch *bool + // Path to the .prebuilt_info file of the prebuilt app. // In case of mainline modules, the .prebuilt_info file contains the build_id that was used // to generate the prebuilt. @@ -292,6 +301,26 @@ func (a *AndroidAppImport) shouldUncompressDex(ctx android.ModuleContext) bool { return shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), &a.dexpreopter) } +func (a *AndroidAppImport) stripEmbeddedJniLibsUnusedArch( + ctx android.ModuleContext, inputPath android.Path, outputPath android.WritablePath) { + var wantedJniLibSlice []string + for _, target := range ctx.MultiTargets() { + supported_abis := target.Arch.Abi + for _, arch := range supported_abis { + wantedJniLibSlice = append(wantedJniLibSlice, " -X lib/"+arch+"/*.so") + } + } + wantedJniLibString := strings.Join(wantedJniLibSlice, " ") + ctx.Build(pctx, android.BuildParams{ + Rule: stripEmbeddedJniLibsUnusedArchRule, + Input: inputPath, + Output: outputPath, + Args: map[string]string{ + "extraArgs": wantedJniLibString, + }, + }) +} + func (a *AndroidAppImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.generateAndroidBuildActions(ctx) } @@ -347,6 +376,13 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext jnisUncompressed := android.PathForModuleOut(ctx, "jnis-uncompressed", ctx.ModuleName()+".apk") a.uncompressEmbeddedJniLibs(ctx, srcApk, jnisUncompressed) + // Strip all embedded JNI libs and include only required ones accordingly to the module's compile_multilib + if Bool(a.properties.Strip_unused_jni_arch) { + jnisStripped := android.PathForModuleOut(ctx, "jnis-stripped", ctx.ModuleName()+".apk") + a.stripEmbeddedJniLibsUnusedArch(ctx, jnisUncompressed, jnisStripped) + jnisUncompressed = jnisStripped + } + var pathFragments []string relInstallPath := String(a.properties.Relative_install_path) diff --git a/java/base.go b/java/base.go index 1aef37ca4..a2fc29de7 100644 --- a/java/base.go +++ b/java/base.go @@ -90,6 +90,10 @@ type CommonProperties struct { // list of module-specific flags that will be used for kotlinc compiles Kotlincflags []string `android:"arch_variant"` + // Kotlin language version to target. Currently only 1.9 and 2 are supported. + // See kotlinc's `-language-version` flag. + Kotlin_lang_version *string + // list of java libraries that will be in the classpath Libs []string `android:"arch_variant"` @@ -1331,6 +1335,16 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath kotlincFlags := j.properties.Kotlincflags CheckKotlincFlags(ctx, kotlincFlags) + kotlin_lang_version := proptools.StringDefault(j.properties.Kotlin_lang_version, "1.9") + if kotlin_lang_version == "1.9" { + kotlincFlags = append(kotlincFlags, "-language-version 1.9") + } else if kotlin_lang_version == "2" { + kotlincFlags = append(kotlincFlags, "-Xsuppress-version-warnings", "-Xconsistent-data-class-copy-visibility") + } else { + ctx.PropertyErrorf("kotlin_lang_version", "Must be one of `1.9` or `2`") + + } + // Workaround for KT-46512 kotlincFlags = append(kotlincFlags, "-Xsam-conversions=class") @@ -2059,7 +2073,9 @@ func CheckKotlincFlags(ctx android.ModuleContext, flags []string) { } else if strings.HasPrefix(flag, "-Xintellij-plugin-root") { ctx.PropertyErrorf("kotlincflags", "Bad flag: `%s`, only use internal compiler for consistency.", flag) - } else if inList(flag, config.KotlincIllegalFlags) { + } else if slices.ContainsFunc(config.KotlincIllegalFlags, func(f string) bool { + return strings.HasPrefix(flag, f) + }) { ctx.PropertyErrorf("kotlincflags", "Flag `%s` already used by build system", flag) } else if flag == "-include-runtime" { ctx.PropertyErrorf("kotlincflags", "Bad flag: `%s`, do not include runtime.", flag) diff --git a/java/config/kotlin.go b/java/config/kotlin.go index bf4c886d1..ffb025d9c 100644 --- a/java/config/kotlin.go +++ b/java/config/kotlin.go @@ -21,6 +21,7 @@ var ( KotlincIllegalFlags = []string{ "-no-jdk", "-no-stdlib", + "-language-version", } ) @@ -49,12 +50,12 @@ func init() { "-J--add-opens=java.base/java.util=ALL-UNNAMED", // https://youtrack.jetbrains.com/issue/KT-43704 }, " ")) - pctx.StaticVariable("KotlincGlobalFlags", strings.Join([]string{"-language-version 1.9"}, " ")) + pctx.StaticVariable("KotlincGlobalFlags", strings.Join([]string{}, " ")) // Use KotlincKytheGlobalFlags to prevent kotlinc version skew issues between android and // g3 kythe indexers. // This is necessary because there might be instances of kotlin code in android // platform that are not fully compatible with the kotlinc used in g3 kythe indexers. // e.g. uninitialized variables are a warning in 1.*, but an error in 2.* // https://github.com/JetBrains/kotlin/blob/master/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt#L748 - pctx.StaticVariable("KotlincKytheGlobalFlags", strings.Join([]string{"-language-version 1.9"}, " ")) + pctx.StaticVariable("KotlincKytheGlobalFlags", strings.Join([]string{}, " ")) } diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index d09a02e50..152eb1eeb 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -172,7 +172,7 @@ func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.Mo // Do not add implLibModule to allModules as the impl lib is only used to collect the // transitive source files var implLibModule []android.Module - ctx.VisitDirectDepsWithTag(implLibraryTag, func(m android.Module) { + ctx.VisitDirectDepsWithTag(platformBootclasspathImplLibDepTag, func(m android.Module) { implLibModule = append(implLibModule, m) }) diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go index f2768dbe3..1f691a019 100644 --- a/java/platform_bootclasspath_test.go +++ b/java/platform_bootclasspath_test.go @@ -30,18 +30,23 @@ func TestPlatformBootclasspath(t *testing.T) { preparer := android.GroupFixturePreparers( prepareForTestWithPlatformBootclasspath, FixtureConfigureBootJars("platform:foo", "system_ext:bar"), + android.FixtureMergeMockFs(android.MockFS{ + "api/current.txt": nil, + "api/removed.txt": nil, + }), android.FixtureWithRootAndroidBp(` platform_bootclasspath { name: "platform-bootclasspath", } - java_library { + java_sdk_library { name: "bar", srcs: ["a.java"], system_modules: "none", sdk_version: "none", compile_dex: true, system_ext_specific: true, + unsafe_ignore_missing_latest_api: true, } `), ) diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go index 5b145c658..bb9894400 100644 --- a/java/platform_compat_config.go +++ b/java/platform_compat_config.go @@ -51,6 +51,10 @@ func platformCompatConfigPath(ctx android.PathContext) android.OutputPath { type platformCompatConfigProperties struct { Src *string `android:"path"` + + // If true, we include it in the "merged" XML (merged_compat_config.xml). + // Default is true. + Include_in_merged_xml *bool } type platformCompatConfig struct { @@ -60,6 +64,7 @@ type platformCompatConfig struct { installDirPath android.InstallPath configFile android.OutputPath metadataFile android.OutputPath + doMerge bool installConfigFile android.InstallPath } @@ -68,6 +73,10 @@ func (p *platformCompatConfig) compatConfigMetadata() android.Path { return p.metadataFile } +func (p *platformCompatConfig) includeInMergedXml() bool { + return p.doMerge +} + func (p *platformCompatConfig) CompatConfig() android.OutputPath { return p.configFile } @@ -78,6 +87,9 @@ func (p *platformCompatConfig) SubDir() string { type platformCompatConfigMetadataProvider interface { compatConfigMetadata() android.Path + + // Whether to include it in the "merged" XML (merged_compat_config.xml) or not. + includeInMergedXml() bool } type PlatformCompatConfigIntf interface { @@ -98,6 +110,7 @@ func (p *platformCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleCon metadataFileName := p.Name() + "_meta.xml" p.configFile = android.PathForModuleOut(ctx, configFileName).OutputPath p.metadataFile = android.PathForModuleOut(ctx, metadataFileName).OutputPath + p.doMerge = proptools.BoolDefault(p.properties.Include_in_merged_xml, true) path := android.PathForModuleSrc(ctx, String(p.properties.Src)) rule.Command(). @@ -201,6 +214,10 @@ func (module *prebuiltCompatConfigModule) compatConfigMetadata() android.Path { return module.metadataFile } +func (module *prebuiltCompatConfigModule) includeInMergedXml() bool { + return true // Always include in merged.xml +} + func (module *prebuiltCompatConfigModule) BaseModuleName() string { return proptools.StringDefault(module.properties.Source_module_name, module.ModuleBase.Name()) } @@ -237,6 +254,9 @@ func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.Singlet if !android.IsModulePreferred(module) { return } + if !c.includeInMergedXml() { + return + } metadata := c.compatConfigMetadata() compatConfigMetadata = append(compatConfigMetadata, metadata) } diff --git a/java/platform_compat_config_test.go b/java/platform_compat_config_test.go index 80d991c49..f7529a728 100644 --- a/java/platform_compat_config_test.go +++ b/java/platform_compat_config_test.go @@ -26,6 +26,7 @@ func TestPlatformCompatConfig(t *testing.T) { android.FixtureWithRootAndroidBp(` platform_compat_config { name: "myconfig2", + include_in_merged_xml: false, } platform_compat_config { name: "myconfig1", @@ -38,7 +39,6 @@ func TestPlatformCompatConfig(t *testing.T) { CheckMergedCompatConfigInputs(t, result, "myconfig", "out/soong/.intermediates/myconfig1/myconfig1_meta.xml", - "out/soong/.intermediates/myconfig2/myconfig2_meta.xml", "out/soong/.intermediates/myconfig3/myconfig3_meta.xml", ) } diff --git a/ui/build/build.go b/ui/build/build.go index 1dc6dbd8b..26f59692f 100644 --- a/ui/build/build.go +++ b/ui/build/build.go @@ -107,8 +107,11 @@ builddir = {{.OutDir}} {{end -}} pool highmem_pool depth = {{.HighmemParallel}} -{{if and (not .SkipKatiNinja) .HasKatiSuffix}}subninja {{.KatiBuildNinjaFile}} +{{if and (not .SkipKatiNinja) .HasKatiSuffix}} +subninja {{.KatiBuildNinjaFile}} subninja {{.KatiPackageNinjaFile}} +{{else}} +subninja {{.KatiSoongOnlyPackageNinjaFile}} {{end -}} subninja {{.SoongNinjaFile}} `)) @@ -346,25 +349,31 @@ func Build(ctx Context, config Config) { return } + // Still generate the kati suffix in soong-only builds because soong-only still uses kati for + // the packaging step. Also, the kati suffix is used for the combined ninja file. + genKatiSuffix(ctx, config) + if what&RunSoong != 0 { runSoong(ctx, config) } if what&RunKati != 0 { - genKatiSuffix(ctx, config) runKatiCleanSpec(ctx, config) runKatiBuild(ctx, config) - runKatiPackage(ctx, config) + runKatiPackage(ctx, config, false) - ioutil.WriteFile(config.LastKatiSuffixFile(), []byte(config.KatiSuffix()), 0666) // a+rw } else if what&RunKatiNinja != 0 { // Load last Kati Suffix if it exists - if katiSuffix, err := ioutil.ReadFile(config.LastKatiSuffixFile()); err == nil { + if katiSuffix, err := os.ReadFile(config.LastKatiSuffixFile()); err == nil { ctx.Verboseln("Loaded previous kati config:", string(katiSuffix)) config.SetKatiSuffix(string(katiSuffix)) } + } else if what&RunSoong != 0 { + runKatiPackage(ctx, config, true) } + os.WriteFile(config.LastKatiSuffixFile(), []byte(config.KatiSuffix()), 0666) // a+rw + // Write combined ninja file createCombinedBuildNinjaFile(ctx, config) diff --git a/ui/build/config.go b/ui/build/config.go index dc468c2e7..4f2d213b9 100644 --- a/ui/build/config.go +++ b/ui/build/config.go @@ -1592,6 +1592,10 @@ func (c *configImpl) KatiPackageNinjaFile() string { return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiPackageSuffix+".ninja") } +func (c *configImpl) KatiSoongOnlyPackageNinjaFile() string { + return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiSoongOnlyPackageSuffix+".ninja") +} + func (c *configImpl) SoongVarsFile() string { targetProduct, err := c.TargetProductOrErr() if err != nil { @@ -1647,7 +1651,7 @@ func (c *configImpl) DevicePreviousProductConfig() string { } func (c *configImpl) KatiPackageMkDir() string { - return filepath.Join(c.ProductOut(), "obj", "CONFIG", "kati_packaging") + return filepath.Join(c.SoongOutDir(), "kati_packaging"+c.KatiSuffix()) } func (c *configImpl) hostOutRoot() string { diff --git a/ui/build/kati.go b/ui/build/kati.go index acd52546f..6519573ac 100644 --- a/ui/build/kati.go +++ b/ui/build/kati.go @@ -31,6 +31,7 @@ var spaceSlashReplacer = strings.NewReplacer("/", "_", " ", "_") const katiBuildSuffix = "" const katiCleanspecSuffix = "-cleanspec" const katiPackageSuffix = "-package" +const katiSoongOnlyPackageSuffix = "-soong-only-package" // genKatiSuffix creates a filename suffix for kati-generated files so that we // can cache them based on their inputs. Such files include the generated Ninja @@ -40,8 +41,12 @@ const katiPackageSuffix = "-package" // Currently that includes the TARGET_PRODUCT and kati-processed command line // arguments. func genKatiSuffix(ctx Context, config Config) { + targetProduct := "unknown" + if p, err := config.TargetProductOrErr(); err == nil { + targetProduct = p + } // Construct the base suffix. - katiSuffix := "-" + config.TargetProduct() + config.CoverageSuffix() + katiSuffix := "-" + targetProduct + config.CoverageSuffix() // Append kati arguments to the suffix. if args := config.KatiArgs(); len(args) > 0 { @@ -68,13 +73,13 @@ func genKatiSuffix(ctx Context, config Config) { func writeValueIfChanged(ctx Context, config Config, dir string, filename string, value string) { filePath := filepath.Join(dir, filename) previousValue := "" - rawPreviousValue, err := ioutil.ReadFile(filePath) + rawPreviousValue, err := os.ReadFile(filePath) if err == nil { previousValue = string(rawPreviousValue) } if previousValue != value { - if err = ioutil.WriteFile(filePath, []byte(value), 0666); err != nil { + if err = os.WriteFile(filePath, []byte(value), 0666); err != nil { ctx.Fatalf("Failed to write: %v", err) } } @@ -334,10 +339,19 @@ func cleanOldInstalledFiles(ctx Context, config Config) { // Generate the Ninja file containing the packaging command lines for the dist // dir. -func runKatiPackage(ctx Context, config Config) { +func runKatiPackage(ctx Context, config Config, soongOnly bool) { ctx.BeginTrace(metrics.RunKati, "kati package") defer ctx.EndTrace() + entryPoint := "build/make/packaging/main.mk" + suffix := katiPackageSuffix + ninjaFile := config.KatiPackageNinjaFile() + if soongOnly { + entryPoint = "build/make/packaging/main_soong_only.mk" + suffix = katiSoongOnlyPackageSuffix + ninjaFile = config.KatiSoongOnlyPackageNinjaFile() + } + args := []string{ // Mark the dist dir as writable. "--writable", config.DistDir() + "/", @@ -346,14 +360,14 @@ func runKatiPackage(ctx Context, config Config) { // Fail when redefining / duplicating a target. "--werror_overriding_commands", // Entry point. - "-f", "build/make/packaging/main.mk", + "-f", entryPoint, // Directory containing .mk files for packaging purposes, such as // the dist.mk file, containing dist-for-goals data. "KATI_PACKAGE_MK_DIR=" + config.KatiPackageMkDir(), } // Run Kati against a restricted set of environment variables. - runKati(ctx, config, katiPackageSuffix, args, func(env *Environment) { + runKati(ctx, config, suffix, args, func(env *Environment) { env.Allow([]string{ // Some generic basics "LANG", @@ -381,7 +395,7 @@ func runKatiPackage(ctx Context, config Config) { }) // Compress and dist the packaging Ninja file. - distGzipFile(ctx, config, config.KatiPackageNinjaFile()) + distGzipFile(ctx, config, ninjaFile) } // Run Kati on the cleanspec files to clean the build. diff --git a/ui/build/soong.go b/ui/build/soong.go index 82e5c96db..58334a907 100644 --- a/ui/build/soong.go +++ b/ui/build/soong.go @@ -197,6 +197,8 @@ func getGlobPathNameFromPrimaryBuilderFactory(config Config, pb PrimaryBuilderFa func (pb PrimaryBuilderFactory) primaryBuilderInvocation(config Config) bootstrap.PrimaryBuilderInvocation { commonArgs := make([]string, 0, 0) + commonArgs = append(commonArgs, "--kati_suffix", config.KatiSuffix()) + if !pb.config.skipSoongTests { commonArgs = append(commonArgs, "-t") } |