diff options
author | 2025-01-16 14:55:35 -0800 | |
---|---|---|
committer | 2025-01-16 16:20:24 -0800 | |
commit | 74ee4e0adc7fb37d648b86852cae93746556e02e (patch) | |
tree | 9b56d0230554e90486e7bd57d96a6978bb42b1a7 | |
parent | feb2479506afeb4bf1e8b52a0f5edd21a420280b (diff) |
Build system_other image in soong-only builds
This just builds an empty system_other image for now, the dexpreopt
files will be added in a followup change.
Bug: 390269431
Test: m --soong-only
Change-Id: Ic4a9bcb8b7ba1eb4444b3339d6c0b0cdfd485714
-rw-r--r-- | android/variable.go | 2 | ||||
-rw-r--r-- | filesystem/Android.bp | 1 | ||||
-rw-r--r-- | filesystem/filesystem.go | 33 | ||||
-rw-r--r-- | filesystem/super_image.go | 27 | ||||
-rw-r--r-- | filesystem/system_other.go | 122 | ||||
-rw-r--r-- | fsgen/filesystem_creator.go | 25 | ||||
-rw-r--r-- | fsgen/super_img.go | 11 |
7 files changed, 205 insertions, 16 deletions
diff --git a/android/variable.go b/android/variable.go index 08bcedf76..14094e2d8 100644 --- a/android/variable.go +++ b/android/variable.go @@ -623,6 +623,8 @@ type PartitionVariables struct { VendorDlkmSecurityPatch string `json:",omitempty"` OdmDlkmSecurityPatch string `json:",omitempty"` + BuildingSystemOtherImage bool `json:",omitempty"` + // Boot image stuff BuildingRamdiskImage bool `json:",omitempty"` ProductBuildBootImage bool `json:",omitempty"` diff --git a/filesystem/Android.bp b/filesystem/Android.bp index 986b72edb..cb76df2d9 100644 --- a/filesystem/Android.bp +++ b/filesystem/Android.bp @@ -28,6 +28,7 @@ bootstrap_go_package { "raw_binary.go", "super_image.go", "system_image.go", + "system_other.go", "vbmeta.go", "testing.go", ], diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index ad19cc6e0..e485e4fdb 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -378,6 +378,11 @@ type FilesystemInfo struct { // Name of the module that produced this FilesystemInfo origionally. (though it may be // re-exported by super images or boot images) ModuleName string + // The property file generated by this module and passed to build_image. + // It's exported here so that system_other can reuse system's property file. + BuildImagePropFile android.Path + // Paths to all the tools referenced inside of the build image property file. + BuildImagePropFileDeps android.Paths } var FilesystemProvider = blueprint.NewProvider[FilesystemInfo]() @@ -484,9 +489,11 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { var mapFile android.Path var outputHermetic android.Path + var buildImagePropFile android.Path + var buildImagePropFileDeps android.Paths switch f.fsType(ctx) { case ext4Type, erofsType, f2fsType: - f.output, outputHermetic = f.buildImageUsingBuildImage(ctx, builder, rootDir, rebasedDir) + f.output, outputHermetic, buildImagePropFile, buildImagePropFileDeps = f.buildImageUsingBuildImage(ctx, builder, rootDir, rebasedDir) mapFile = f.getMapFile(ctx) case compressedCpioType: f.output = f.buildCpioImage(ctx, builder, rootDir, true) @@ -508,17 +515,15 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { android.WriteFileRule(ctx, fileListFile, f.installedFilesList()) fsInfo := FilesystemInfo{ - Output: f.output, - FileListFile: fileListFile, - RootDir: rootDir, - RebasedDir: rebasedDir, - ModuleName: ctx.ModuleName(), - } - if mapFile != nil { - fsInfo.MapFile = mapFile - } - if outputHermetic != nil { - fsInfo.OutputHermetic = outputHermetic + Output: f.output, + OutputHermetic: outputHermetic, + FileListFile: fileListFile, + RootDir: rootDir, + RebasedDir: rebasedDir, + MapFile: mapFile, + ModuleName: ctx.ModuleName(), + BuildImagePropFile: buildImagePropFile, + BuildImagePropFileDeps: buildImagePropFileDeps, } android.SetProvider(ctx, FilesystemProvider, fsInfo) @@ -670,7 +675,7 @@ func (f *filesystem) buildImageUsingBuildImage( builder *android.RuleBuilder, rootDir android.OutputPath, rebasedDir android.OutputPath, -) (android.Path, android.Path) { +) (android.Path, android.Path, android.Path, android.Paths) { // run host_init_verifier // Ideally we should have a concept of pluggable linters that verify the generated image. // While such concept is not implement this will do. @@ -721,7 +726,7 @@ func (f *filesystem) buildImageUsingBuildImage( // rootDir is not deleted. Might be useful for quick inspection. builder.Build("build_filesystem_image", fmt.Sprintf("Creating filesystem %s", f.BaseModuleName())) - return output, outputHermetic + return output, outputHermetic, propFile, toolDeps } func (f *filesystem) buildFileContexts(ctx android.ModuleContext) android.Path { diff --git a/filesystem/super_image.go b/filesystem/super_image.go index 4419a2fbf..533246220 100644 --- a/filesystem/super_image.go +++ b/filesystem/super_image.go @@ -18,6 +18,7 @@ import ( "fmt" "path/filepath" "regexp" + "slices" "strconv" "strings" @@ -55,6 +56,9 @@ type SuperImageProperties struct { Sparse *bool // information about how partitions within the super partition are grouped together Partition_groups []PartitionGroupsInfo + // Name of the system_other partition filesystem module. This module will be installed to + // the "b" slot of the system partition in a/b partition builds. + System_other_partition *string // whether dynamic partitions is used Use_dynamic_partitions *bool Virtual_ab struct { @@ -127,6 +131,12 @@ type superImageDepTagType struct { var subImageDepTag superImageDepTagType +type systemOtherDepTagType struct { + blueprint.BaseDependencyTag +} + +var systemOtherDepTag systemOtherDepTagType + func (s *superImage) DepsMutator(ctx android.BottomUpMutatorContext) { addDependencyIfDefined := func(dep *string) { if dep != nil { @@ -143,6 +153,9 @@ func (s *superImage) DepsMutator(ctx android.BottomUpMutatorContext) { addDependencyIfDefined(s.partitionProps.Vendor_dlkm_partition) addDependencyIfDefined(s.partitionProps.Odm_partition) addDependencyIfDefined(s.partitionProps.Odm_dlkm_partition) + if s.properties.System_other_partition != nil { + ctx.AddDependency(ctx.Module(), systemOtherDepTag, *s.properties.System_other_partition) + } } func (s *superImage) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -299,6 +312,20 @@ func (s *superImage) buildMiscInfo(ctx android.ModuleContext) (android.Path, and } } + if s.properties.System_other_partition != nil { + if !slices.Contains(partitionList, "system") { + ctx.PropertyErrorf("system_other_partition", "Must have a system partition to use a system_other partition") + } + systemOther := ctx.GetDirectDepProxyWithTag(*s.properties.System_other_partition, systemOtherDepTag) + systemOtherFiles := android.OutputFilesForModule(ctx, systemOther, "") + if len(systemOtherFiles) != 1 { + ctx.PropertyErrorf("system_other_partition", "Expected 1 output file from module %q", *&s.properties.System_other_partition) + } else { + addStr("system_other_image", systemOtherFiles[0].String()) + deps = append(deps, systemOtherFiles[0]) + } + } + // Delay the error message until execution time because on aosp-main-future-without-vendor, // BUILDING_VENDOR_IMAGE is false so we don't get the vendor image, but it's still listed in // BOARD_GOOGLE_DYNAMIC_PARTITIONS_PARTITION_LIST. diff --git a/filesystem/system_other.go b/filesystem/system_other.go new file mode 100644 index 000000000..cad426337 --- /dev/null +++ b/filesystem/system_other.go @@ -0,0 +1,122 @@ +// Copyright (C) 2024 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package filesystem + +import ( + "android/soong/android" + "path/filepath" + "strings" + + "github.com/google/blueprint" + "github.com/google/blueprint/proptools" +) + +type SystemOtherImageProperties struct { + // The system_other image always requires a reference to the system image. The system_other + // partition gets built into the system partition's "b" slot in a/b partition builds. Thus, it + // copies most of its configuration from the system image, such as filesystem type, avb signing + // info, etc. Including it here does not automatically mean that it will pick up the system + // image's dexpropt files, it must also be listed in Preinstall_dexpreopt_files_from for that. + System_image *string + + // This system_other partition will include all the dexpreopt files from the apps on these + // partitions. + Preinstall_dexpreopt_files_from []string +} + +type systemOtherImage struct { + android.ModuleBase + android.DefaultableModuleBase + properties SystemOtherImageProperties +} + +// The system_other image is the default contents of the "b" slot of the system image. +// It contains the dexpreopt files of all the apps on the device, for a faster first boot. +// Afterwards, at runtime, it will be used as a regular b slot for OTA updates, and the initial +// dexpreopt files will be deleted. +func SystemOtherImageFactory() android.Module { + module := &systemOtherImage{} + module.AddProperties(&module.properties) + android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) + android.InitDefaultableModule(module) + return module +} + +type systemImageDeptag struct { + blueprint.BaseDependencyTag +} + +var systemImageDependencyTag = systemImageDeptag{} + +type dexpreoptDeptag struct { + blueprint.BaseDependencyTag +} + +var dexpreoptDependencyTag = dexpreoptDeptag{} + +func (m *systemOtherImage) DepsMutator(ctx android.BottomUpMutatorContext) { + if proptools.String(m.properties.System_image) == "" { + ctx.ModuleErrorf("system_image property must be set") + return + } + ctx.AddDependency(ctx.Module(), systemImageDependencyTag, *m.properties.System_image) + ctx.AddDependency(ctx.Module(), dexpreoptDependencyTag, m.properties.Preinstall_dexpreopt_files_from...) +} + +func (m *systemOtherImage) GenerateAndroidBuildActions(ctx android.ModuleContext) { + systemImage := ctx.GetDirectDepProxyWithTag(*m.properties.System_image, systemImageDependencyTag) + systemInfo, ok := android.OtherModuleProvider(ctx, systemImage, FilesystemProvider) + if !ok { + ctx.PropertyErrorf("system_image", "Expected system_image module to provide FilesystemProvider") + return + } + + output := android.PathForModuleOut(ctx, "system_other.img") + stagingDir := android.PathForModuleOut(ctx, "staging_dir") + + builder := android.NewRuleBuilder(pctx, ctx) + builder.Command().Textf("rm -rf %s && mkdir -p %s", stagingDir, stagingDir) + + for _, otherPartition := range m.properties.Preinstall_dexpreopt_files_from { + dexModule := ctx.GetDirectDepProxyWithTag(otherPartition, dexpreoptDependencyTag) + _, ok := android.OtherModuleProvider(ctx, dexModule, FilesystemProvider) + if !ok { + ctx.PropertyErrorf("preinstall_dexpreopt_files_from", "Expected module %q to provide FilesystemProvider", otherPartition) + return + } + // TODO(b/390269431): Install dex files to the staging dir + } + + // Most of the time, if build_image were to call a host tool, it accepts the path to the + // host tool in a field in the prop file. However, it doesn't have that option for fec, which + // it expects to just be on the PATH. Add fec to the PATH. + fec := ctx.Config().HostToolPath(ctx, "fec") + pathToolDirs := []string{filepath.Dir(fec.String())} + + builder.Command(). + Textf("PATH=%s:$PATH", strings.Join(pathToolDirs, ":")). + BuiltTool("build_image"). + Text(stagingDir.String()). // input directory + Input(systemInfo.BuildImagePropFile). + Implicits(systemInfo.BuildImagePropFileDeps). + Implicit(fec). + Output(output). + Text(stagingDir.String()) + + builder.Build("build_system_other", "build system other") + + ctx.SetOutputFiles(android.Paths{output}, "") + ctx.CheckbuildFile(output) +} diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go index d00ebb217..616607468 100644 --- a/fsgen/filesystem_creator.go +++ b/fsgen/filesystem_creator.go @@ -156,6 +156,23 @@ func (f *filesystemCreator) createInternalModules(ctx android.LoadHookContext) { } } + var systemOtherImageName string + if buildingSystemOtherImage(partitionVars) { + systemModule := generatedModuleNameForPartition(ctx.Config(), "system") + systemOtherImageName = generatedModuleNameForPartition(ctx.Config(), "system_other") + ctx.CreateModule( + filesystem.SystemOtherImageFactory, + &filesystem.SystemOtherImageProperties{ + System_image: &systemModule, + }, + &struct { + Name *string + }{ + Name: proptools.StringPtr(systemOtherImageName), + }, + ) + } + for _, x := range createVbmetaPartitions(ctx, finalSoongGeneratedPartitions) { f.properties.Vbmeta_module_names = append(f.properties.Vbmeta_module_names, x.moduleName) f.properties.Vbmeta_partition_names = append(f.properties.Vbmeta_partition_names, x.partitionName) @@ -163,7 +180,7 @@ func (f *filesystemCreator) createInternalModules(ctx android.LoadHookContext) { var superImageSubpartitions []string if buildingSuperImage(partitionVars) { - superImageSubpartitions = createSuperImage(ctx, finalSoongGeneratedPartitions, partitionVars) + superImageSubpartitions = createSuperImage(ctx, finalSoongGeneratedPartitions, partitionVars, systemOtherImageName) f.properties.Super_image = ":" + generatedModuleNameForPartition(ctx.Config(), "super") } @@ -183,6 +200,12 @@ func generatedModuleNameForPartition(cfg android.Config, partitionType string) s return generatedModuleName(cfg, fmt.Sprintf("%s_image", partitionType)) } +func buildingSystemOtherImage(partitionVars android.PartitionVariables) bool { + // TODO: Recreate this logic from make instead of just depending on the final result variable: + // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/board_config.mk;l=429;drc=15a0df840e7093f65518003ab80cf24a3d9e8e6a + return partitionVars.BuildingSystemOtherImage +} + func (f *filesystemCreator) createBootloaderFilegroup(ctx android.LoadHookContext) (string, bool) { bootloaderPath := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.PrebuiltBootloader if len(bootloaderPath) == 0 { diff --git a/fsgen/super_img.go b/fsgen/super_img.go index 5c23868b6..e3536888e 100644 --- a/fsgen/super_img.go +++ b/fsgen/super_img.go @@ -27,7 +27,12 @@ func buildingSuperImage(partitionVars android.PartitionVariables) bool { return partitionVars.ProductBuildSuperPartition } -func createSuperImage(ctx android.LoadHookContext, partitions []string, partitionVars android.PartitionVariables) []string { +func createSuperImage( + ctx android.LoadHookContext, + partitions []string, + partitionVars android.PartitionVariables, + systemOtherImageName string, +) []string { baseProps := &struct { Name *string }{ @@ -79,6 +84,10 @@ func createSuperImage(ctx android.LoadHookContext, partitions []string, partitio } superImageProps.Partition_groups = partitionGroupsInfo + if systemOtherImageName != "" { + superImageProps.System_other_partition = proptools.StringPtr(systemOtherImageName) + } + var superImageSubpartitions []string partitionNameProps := &filesystem.SuperImagePartitionNameProperties{} if android.InList("system", partitions) { |