1061 lines
42 KiB
Go
1061 lines
42 KiB
Go
// 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 fsgen
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"fmt"
|
|
"path/filepath"
|
|
"slices"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"android/soong/android"
|
|
"android/soong/filesystem"
|
|
"android/soong/kernel"
|
|
|
|
"github.com/google/blueprint"
|
|
"github.com/google/blueprint/parser"
|
|
"github.com/google/blueprint/proptools"
|
|
)
|
|
|
|
var pctx = android.NewPackageContext("android/soong/fsgen")
|
|
|
|
func init() {
|
|
registerBuildComponents(android.InitRegistrationContext)
|
|
}
|
|
|
|
func registerBuildComponents(ctx android.RegistrationContext) {
|
|
ctx.RegisterModuleType("soong_filesystem_creator", filesystemCreatorFactory)
|
|
ctx.PreDepsMutators(RegisterCollectFileSystemDepsMutators)
|
|
}
|
|
|
|
type filesystemCreatorProps struct {
|
|
Generated_partition_types []string `blueprint:"mutated"`
|
|
Unsupported_partition_types []string `blueprint:"mutated"`
|
|
|
|
Vbmeta_module_names []string `blueprint:"mutated"`
|
|
Vbmeta_partition_names []string `blueprint:"mutated"`
|
|
|
|
Boot_image string `blueprint:"mutated" android:"path_device_first"`
|
|
Vendor_boot_image string `blueprint:"mutated" android:"path_device_first"`
|
|
Init_boot_image string `blueprint:"mutated" android:"path_device_first"`
|
|
Super_image string `blueprint:"mutated" android:"path_device_first"`
|
|
}
|
|
|
|
type filesystemCreator struct {
|
|
android.ModuleBase
|
|
|
|
properties filesystemCreatorProps
|
|
}
|
|
|
|
func filesystemCreatorFactory() android.Module {
|
|
module := &filesystemCreator{}
|
|
|
|
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
|
|
module.AddProperties(&module.properties)
|
|
android.AddLoadHook(module, func(ctx android.LoadHookContext) {
|
|
generatedPrebuiltEtcModuleNames := createPrebuiltEtcModules(ctx)
|
|
avbpubkeyGenerated := createAvbpubkeyModule(ctx)
|
|
createFsGenState(ctx, generatedPrebuiltEtcModuleNames, avbpubkeyGenerated)
|
|
module.createAvbKeyFilegroups(ctx)
|
|
module.createMiscFilegroups(ctx)
|
|
module.createInternalModules(ctx)
|
|
})
|
|
|
|
return module
|
|
}
|
|
|
|
func generatedPartitions(ctx android.LoadHookContext) []string {
|
|
partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
|
|
generatedPartitions := []string{"system"}
|
|
if ctx.DeviceConfig().SystemExtPath() == "system_ext" {
|
|
generatedPartitions = append(generatedPartitions, "system_ext")
|
|
}
|
|
if ctx.DeviceConfig().BuildingVendorImage() && ctx.DeviceConfig().VendorPath() == "vendor" {
|
|
generatedPartitions = append(generatedPartitions, "vendor")
|
|
}
|
|
if ctx.DeviceConfig().BuildingProductImage() && ctx.DeviceConfig().ProductPath() == "product" {
|
|
generatedPartitions = append(generatedPartitions, "product")
|
|
}
|
|
if ctx.DeviceConfig().BuildingOdmImage() && ctx.DeviceConfig().OdmPath() == "odm" {
|
|
generatedPartitions = append(generatedPartitions, "odm")
|
|
}
|
|
if ctx.DeviceConfig().BuildingUserdataImage() && ctx.DeviceConfig().UserdataPath() == "data" {
|
|
generatedPartitions = append(generatedPartitions, "userdata")
|
|
}
|
|
if partitionVars.BuildingSystemDlkmImage {
|
|
generatedPartitions = append(generatedPartitions, "system_dlkm")
|
|
}
|
|
if partitionVars.BuildingVendorDlkmImage {
|
|
generatedPartitions = append(generatedPartitions, "vendor_dlkm")
|
|
}
|
|
if partitionVars.BuildingOdmDlkmImage {
|
|
generatedPartitions = append(generatedPartitions, "odm_dlkm")
|
|
}
|
|
if partitionVars.BuildingRamdiskImage {
|
|
generatedPartitions = append(generatedPartitions, "ramdisk")
|
|
}
|
|
if buildingVendorBootImage(partitionVars) {
|
|
generatedPartitions = append(generatedPartitions, "vendor_ramdisk")
|
|
}
|
|
if ctx.DeviceConfig().BuildingRecoveryImage() && ctx.DeviceConfig().RecoveryPath() == "recovery" {
|
|
generatedPartitions = append(generatedPartitions, "recovery")
|
|
}
|
|
return generatedPartitions
|
|
}
|
|
|
|
func (f *filesystemCreator) createInternalModules(ctx android.LoadHookContext) {
|
|
soongGeneratedPartitions := generatedPartitions(ctx)
|
|
finalSoongGeneratedPartitions := make([]string, 0, len(soongGeneratedPartitions))
|
|
for _, partitionType := range soongGeneratedPartitions {
|
|
if f.createPartition(ctx, partitionType) {
|
|
f.properties.Generated_partition_types = append(f.properties.Generated_partition_types, partitionType)
|
|
finalSoongGeneratedPartitions = append(finalSoongGeneratedPartitions, partitionType)
|
|
} else {
|
|
f.properties.Unsupported_partition_types = append(f.properties.Unsupported_partition_types, partitionType)
|
|
}
|
|
}
|
|
|
|
partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
|
|
dtbImg := createDtbImgFilegroup(ctx)
|
|
|
|
if buildingBootImage(partitionVars) {
|
|
if createBootImage(ctx, dtbImg) {
|
|
f.properties.Boot_image = ":" + generatedModuleNameForPartition(ctx.Config(), "boot")
|
|
} else {
|
|
f.properties.Unsupported_partition_types = append(f.properties.Unsupported_partition_types, "boot")
|
|
}
|
|
}
|
|
if buildingVendorBootImage(partitionVars) {
|
|
if createVendorBootImage(ctx, dtbImg) {
|
|
f.properties.Vendor_boot_image = ":" + generatedModuleNameForPartition(ctx.Config(), "vendor_boot")
|
|
} else {
|
|
f.properties.Unsupported_partition_types = append(f.properties.Unsupported_partition_types, "vendor_boot")
|
|
}
|
|
}
|
|
if buildingInitBootImage(partitionVars) {
|
|
if createInitBootImage(ctx) {
|
|
f.properties.Init_boot_image = ":" + generatedModuleNameForPartition(ctx.Config(), "init_boot")
|
|
} else {
|
|
f.properties.Unsupported_partition_types = append(f.properties.Unsupported_partition_types, "init_boot")
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
if buildingSuperImage(partitionVars) {
|
|
createSuperImage(ctx, finalSoongGeneratedPartitions, partitionVars)
|
|
f.properties.Super_image = ":" + generatedModuleName(ctx.Config(), "super")
|
|
}
|
|
|
|
ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).soongGeneratedPartitions = finalSoongGeneratedPartitions
|
|
f.createDeviceModule(ctx, finalSoongGeneratedPartitions, f.properties.Vbmeta_module_names)
|
|
}
|
|
|
|
func generatedModuleName(cfg android.Config, suffix string) string {
|
|
prefix := "soong"
|
|
if cfg.HasDeviceProduct() {
|
|
prefix = cfg.DeviceProduct()
|
|
}
|
|
return fmt.Sprintf("%s_generated_%s", prefix, suffix)
|
|
}
|
|
|
|
func generatedModuleNameForPartition(cfg android.Config, partitionType string) string {
|
|
return generatedModuleName(cfg, fmt.Sprintf("%s_image", partitionType))
|
|
}
|
|
|
|
func (f *filesystemCreator) createDeviceModule(
|
|
ctx android.LoadHookContext,
|
|
generatedPartitionTypes []string,
|
|
vbmetaPartitions []string,
|
|
) {
|
|
baseProps := &struct {
|
|
Name *string
|
|
}{
|
|
Name: proptools.StringPtr(generatedModuleName(ctx.Config(), "device")),
|
|
}
|
|
|
|
// Currently, only the system and system_ext partition module is created.
|
|
partitionProps := &filesystem.PartitionNameProperties{}
|
|
if android.InList("system", generatedPartitionTypes) {
|
|
partitionProps.System_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system"))
|
|
}
|
|
if android.InList("system_ext", generatedPartitionTypes) {
|
|
partitionProps.System_ext_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_ext"))
|
|
}
|
|
if android.InList("vendor", generatedPartitionTypes) {
|
|
partitionProps.Vendor_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor"))
|
|
}
|
|
if android.InList("product", generatedPartitionTypes) {
|
|
partitionProps.Product_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "product"))
|
|
}
|
|
if android.InList("odm", generatedPartitionTypes) {
|
|
partitionProps.Odm_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "odm"))
|
|
}
|
|
if android.InList("userdata", f.properties.Generated_partition_types) {
|
|
partitionProps.Userdata_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "userdata"))
|
|
}
|
|
partitionProps.Vbmeta_partitions = vbmetaPartitions
|
|
|
|
ctx.CreateModule(filesystem.AndroidDeviceFactory, baseProps, partitionProps)
|
|
}
|
|
|
|
func partitionSpecificFsProps(ctx android.EarlyModuleContext, fsProps *filesystem.FilesystemProperties, partitionVars android.PartitionVariables, partitionType string) {
|
|
switch partitionType {
|
|
case "system":
|
|
fsProps.Build_logtags = proptools.BoolPtr(true)
|
|
// https://source.corp.google.com/h/googleplex-android/platform/build//639d79f5012a6542ab1f733b0697db45761ab0f3:core/packaging/flags.mk;l=21;drc=5ba8a8b77507f93aa48cc61c5ba3f31a4d0cbf37;bpv=1;bpt=0
|
|
fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true)
|
|
// Identical to that of the aosp_shared_system_image
|
|
if partitionVars.ProductFsverityGenerateMetadata {
|
|
fsProps.Fsverity.Inputs = proptools.NewSimpleConfigurable([]string{
|
|
"etc/boot-image.prof",
|
|
"etc/dirty-image-objects",
|
|
"etc/preloaded-classes",
|
|
"etc/classpaths/*.pb",
|
|
"framework/*",
|
|
"framework/*/*", // framework/{arch}
|
|
"framework/oat/*/*", // framework/oat/{arch}
|
|
})
|
|
fsProps.Fsverity.Libs = proptools.NewSimpleConfigurable([]string{":framework-res{.export-package.apk}"})
|
|
}
|
|
// Most of the symlinks and directories listed here originate from create_root_structure.mk,
|
|
// but the handwritten generic system image also recreates them:
|
|
// https://cs.android.com/android/platform/superproject/main/+/main:build/make/target/product/generic/Android.bp;l=33;drc=db08311f1b6ef6cb0a4fbcc6263b89849360ce04
|
|
// TODO(b/377734331): only generate the symlinks if the relevant partitions exist
|
|
fsProps.Symlinks = []filesystem.SymlinkDefinition{
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/system/bin/init"),
|
|
Name: proptools.StringPtr("init"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/system/etc"),
|
|
Name: proptools.StringPtr("etc"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/system/bin"),
|
|
Name: proptools.StringPtr("bin"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/data/user_de/0/com.android.shell/files/bugreports"),
|
|
Name: proptools.StringPtr("bugreports"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/sys/kernel/debug"),
|
|
Name: proptools.StringPtr("d"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/storage/self/primary"),
|
|
Name: proptools.StringPtr("sdcard"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/product/etc/security/adb_keys"),
|
|
Name: proptools.StringPtr("adb_keys"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/vendor/odm/app"),
|
|
Name: proptools.StringPtr("odm/app"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/vendor/odm/bin"),
|
|
Name: proptools.StringPtr("odm/bin"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/vendor/odm/etc"),
|
|
Name: proptools.StringPtr("odm/etc"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/vendor/odm/firmware"),
|
|
Name: proptools.StringPtr("odm/firmware"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/vendor/odm/framework"),
|
|
Name: proptools.StringPtr("odm/framework"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/vendor/odm/lib"),
|
|
Name: proptools.StringPtr("odm/lib"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/vendor/odm/lib64"),
|
|
Name: proptools.StringPtr("odm/lib64"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/vendor/odm/overlay"),
|
|
Name: proptools.StringPtr("odm/overlay"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/vendor/odm/priv-app"),
|
|
Name: proptools.StringPtr("odm/priv-app"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/vendor/odm/usr"),
|
|
Name: proptools.StringPtr("odm/usr"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/product"),
|
|
Name: proptools.StringPtr("system/product"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/system_ext"),
|
|
Name: proptools.StringPtr("system/system_ext"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/vendor"),
|
|
Name: proptools.StringPtr("system/vendor"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/system_dlkm/lib/modules"),
|
|
Name: proptools.StringPtr("system/lib/modules"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/data/cache"),
|
|
Name: proptools.StringPtr("cache"),
|
|
},
|
|
// For Treble Generic System Image (GSI), system-as-root GSI needs to work on
|
|
// both devices with and without /odm_dlkm partition. Those symlinks are for
|
|
// devices without /odm_dlkm partition. For devices with /odm_dlkm
|
|
// partition, mount odm_dlkm.img under /odm_dlkm will hide those symlinks.
|
|
// Note that /odm_dlkm/lib is omitted because odm DLKMs should be accessed
|
|
// via /odm/lib/modules directly. All of this also applies to the vendor_dlkm symlink
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/odm/odm_dlkm/etc"),
|
|
Name: proptools.StringPtr("odm_dlkm/etc"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/vendor/vendor_dlkm/etc"),
|
|
Name: proptools.StringPtr("vendor_dlkm/etc"),
|
|
},
|
|
}
|
|
fsProps.Base_dir = proptools.StringPtr("system")
|
|
fsProps.Dirs = proptools.NewSimpleConfigurable([]string{
|
|
// From generic_rootdirs in build/make/target/product/generic/Android.bp
|
|
"acct",
|
|
"apex",
|
|
"bootstrap-apex",
|
|
"config",
|
|
"data",
|
|
"data_mirror",
|
|
"debug_ramdisk",
|
|
"dev",
|
|
"linkerconfig",
|
|
"metadata",
|
|
"mnt",
|
|
"odm",
|
|
"odm_dlkm",
|
|
"oem",
|
|
"postinstall",
|
|
"proc",
|
|
"second_stage_resources",
|
|
"storage",
|
|
"sys",
|
|
"system",
|
|
"system_dlkm",
|
|
"tmp",
|
|
"vendor",
|
|
"vendor_dlkm",
|
|
|
|
// from android_rootdirs in build/make/target/product/generic/Android.bp
|
|
"system_ext",
|
|
"product",
|
|
})
|
|
case "system_ext":
|
|
if partitionVars.ProductFsverityGenerateMetadata {
|
|
fsProps.Fsverity.Inputs = proptools.NewSimpleConfigurable([]string{
|
|
"framework/*",
|
|
"framework/*/*", // framework/{arch}
|
|
"framework/oat/*/*", // framework/oat/{arch}
|
|
})
|
|
fsProps.Fsverity.Libs = proptools.NewSimpleConfigurable([]string{":framework-res{.export-package.apk}"})
|
|
}
|
|
case "product":
|
|
fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true)
|
|
fsProps.Android_filesystem_deps.System = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system"))
|
|
if ctx.DeviceConfig().SystemExtPath() == "system_ext" {
|
|
fsProps.Android_filesystem_deps.System_ext = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_ext"))
|
|
}
|
|
case "vendor":
|
|
fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true)
|
|
fsProps.Symlinks = []filesystem.SymlinkDefinition{
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/odm"),
|
|
Name: proptools.StringPtr("odm"),
|
|
},
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/vendor_dlkm/lib/modules"),
|
|
Name: proptools.StringPtr("lib/modules"),
|
|
},
|
|
}
|
|
fsProps.Android_filesystem_deps.System = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system"))
|
|
if ctx.DeviceConfig().SystemExtPath() == "system_ext" {
|
|
fsProps.Android_filesystem_deps.System_ext = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_ext"))
|
|
}
|
|
case "odm":
|
|
fsProps.Symlinks = []filesystem.SymlinkDefinition{
|
|
filesystem.SymlinkDefinition{
|
|
Target: proptools.StringPtr("/odm_dlkm/lib/modules"),
|
|
Name: proptools.StringPtr("lib/modules"),
|
|
},
|
|
}
|
|
case "userdata":
|
|
fsProps.Base_dir = proptools.StringPtr("data")
|
|
case "ramdisk":
|
|
// Following the logic in https://cs.android.com/android/platform/superproject/main/+/c3c5063df32748a8806ce5da5dd0db158eab9ad9:build/make/core/Makefile;l=1307
|
|
fsProps.Dirs = android.NewSimpleConfigurable([]string{
|
|
"debug_ramdisk",
|
|
"dev",
|
|
"metadata",
|
|
"mnt",
|
|
"proc",
|
|
"second_stage_resources",
|
|
"sys",
|
|
})
|
|
if partitionVars.BoardUsesGenericKernelImage {
|
|
fsProps.Dirs.AppendSimpleValue([]string{
|
|
"first_stage_ramdisk/debug_ramdisk",
|
|
"first_stage_ramdisk/dev",
|
|
"first_stage_ramdisk/metadata",
|
|
"first_stage_ramdisk/mnt",
|
|
"first_stage_ramdisk/proc",
|
|
"first_stage_ramdisk/second_stage_resources",
|
|
"first_stage_ramdisk/sys",
|
|
})
|
|
}
|
|
case "recovery":
|
|
// Following https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=2826;drc=ad7cfb56010cb22c3aa0e70cf71c804352553526
|
|
fsProps.Dirs = android.NewSimpleConfigurable([]string{
|
|
"sdcard",
|
|
"tmp",
|
|
})
|
|
fsProps.Symlinks = []filesystem.SymlinkDefinition{
|
|
{
|
|
Target: proptools.StringPtr("/system/bin/init"),
|
|
Name: proptools.StringPtr("init"),
|
|
},
|
|
{
|
|
Target: proptools.StringPtr("prop.default"),
|
|
Name: proptools.StringPtr("default.prop"),
|
|
},
|
|
}
|
|
fsProps.Base_dir = proptools.StringPtr("recovery")
|
|
}
|
|
}
|
|
|
|
var (
|
|
dlkmPartitions = []string{
|
|
"system_dlkm",
|
|
"vendor_dlkm",
|
|
"odm_dlkm",
|
|
}
|
|
)
|
|
|
|
// Creates a soong module to build the given partition. Returns false if we can't support building
|
|
// it.
|
|
func (f *filesystemCreator) createPartition(ctx android.LoadHookContext, partitionType string) bool {
|
|
baseProps := generateBaseProps(proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), partitionType)))
|
|
|
|
fsProps, supported := generateFsProps(ctx, partitionType)
|
|
if !supported {
|
|
return false
|
|
}
|
|
|
|
if partitionType == "vendor" || partitionType == "product" || partitionType == "system" {
|
|
fsProps.Linker_config.Gen_linker_config = proptools.BoolPtr(true)
|
|
if partitionType != "system" {
|
|
fsProps.Linker_config.Linker_config_srcs = f.createLinkerConfigSourceFilegroups(ctx, partitionType)
|
|
}
|
|
}
|
|
|
|
if android.InList(partitionType, append(dlkmPartitions, "vendor_ramdisk")) {
|
|
f.createPrebuiltKernelModules(ctx, partitionType)
|
|
}
|
|
|
|
var module android.Module
|
|
if partitionType == "system" {
|
|
module = ctx.CreateModule(filesystem.SystemImageFactory, baseProps, fsProps)
|
|
} else {
|
|
// Explicitly set the partition.
|
|
fsProps.Partition_type = proptools.StringPtr(partitionType)
|
|
module = ctx.CreateModule(filesystem.FilesystemFactory, baseProps, fsProps)
|
|
}
|
|
module.HideFromMake()
|
|
if partitionType == "vendor" {
|
|
f.createVendorBuildProp(ctx)
|
|
}
|
|
return true
|
|
}
|
|
|
|
// Creates filegroups for the files specified in BOARD_(partition_)AVB_KEY_PATH
|
|
func (f *filesystemCreator) createAvbKeyFilegroups(ctx android.LoadHookContext) {
|
|
partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
|
|
var files []string
|
|
|
|
if len(partitionVars.BoardAvbKeyPath) > 0 {
|
|
files = append(files, partitionVars.BoardAvbKeyPath)
|
|
}
|
|
for _, partition := range android.SortedKeys(partitionVars.PartitionQualifiedVariables) {
|
|
specificPartitionVars := partitionVars.PartitionQualifiedVariables[partition]
|
|
if len(specificPartitionVars.BoardAvbKeyPath) > 0 {
|
|
files = append(files, specificPartitionVars.BoardAvbKeyPath)
|
|
}
|
|
}
|
|
|
|
fsGenState := ctx.Config().Get(fsGenStateOnceKey).(*FsGenState)
|
|
for _, file := range files {
|
|
if _, ok := fsGenState.avbKeyFilegroups[file]; ok {
|
|
continue
|
|
}
|
|
if file == "external/avb/test/data/testkey_rsa4096.pem" {
|
|
// There already exists a checked-in filegroup for this commonly-used key, just use that
|
|
fsGenState.avbKeyFilegroups[file] = "avb_testkey_rsa4096"
|
|
continue
|
|
}
|
|
dir := filepath.Dir(file)
|
|
base := filepath.Base(file)
|
|
name := fmt.Sprintf("avb_key_%x", strings.ReplaceAll(file, "/", "_"))
|
|
ctx.CreateModuleInDirectory(
|
|
android.FileGroupFactory,
|
|
dir,
|
|
&struct {
|
|
Name *string
|
|
Srcs []string
|
|
Visibility []string
|
|
}{
|
|
Name: proptools.StringPtr(name),
|
|
Srcs: []string{base},
|
|
Visibility: []string{"//visibility:public"},
|
|
},
|
|
)
|
|
fsGenState.avbKeyFilegroups[file] = name
|
|
}
|
|
}
|
|
|
|
// Creates filegroups for miscellaneous other files
|
|
func (f *filesystemCreator) createMiscFilegroups(ctx android.LoadHookContext) {
|
|
partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
|
|
|
|
if partitionVars.BoardErofsCompressorHints != "" {
|
|
dir := filepath.Dir(partitionVars.BoardErofsCompressorHints)
|
|
base := filepath.Base(partitionVars.BoardErofsCompressorHints)
|
|
ctx.CreateModuleInDirectory(
|
|
android.FileGroupFactory,
|
|
dir,
|
|
&struct {
|
|
Name *string
|
|
Srcs []string
|
|
Visibility []string
|
|
}{
|
|
Name: proptools.StringPtr("soong_generated_board_erofs_compress_hints_filegroup"),
|
|
Srcs: []string{base},
|
|
Visibility: []string{"//visibility:public"},
|
|
},
|
|
)
|
|
}
|
|
}
|
|
|
|
// createPrebuiltKernelModules creates `prebuilt_kernel_modules`. These modules will be added to deps of the
|
|
// autogenerated *_dlkm filsystem modules. Each _dlkm partition should have a single prebuilt_kernel_modules dependency.
|
|
// This ensures that the depmod artifacts (modules.* installed in /lib/modules/) are generated with a complete view.
|
|
func (f *filesystemCreator) createPrebuiltKernelModules(ctx android.LoadHookContext, partitionType string) {
|
|
fsGenState := ctx.Config().Get(fsGenStateOnceKey).(*FsGenState)
|
|
name := generatedModuleName(ctx.Config(), fmt.Sprintf("%s-kernel-modules", partitionType))
|
|
props := &struct {
|
|
Name *string
|
|
Srcs []string
|
|
System_deps []string
|
|
System_dlkm_specific *bool
|
|
Vendor_dlkm_specific *bool
|
|
Odm_dlkm_specific *bool
|
|
Vendor_ramdisk *bool
|
|
Load_by_default *bool
|
|
Blocklist_file *string
|
|
Options_file *string
|
|
}{
|
|
Name: proptools.StringPtr(name),
|
|
}
|
|
switch partitionType {
|
|
case "system_dlkm":
|
|
props.Srcs = android.ExistentPathsForSources(ctx, ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.SystemKernelModules).Strings()
|
|
props.System_dlkm_specific = proptools.BoolPtr(true)
|
|
if len(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.SystemKernelLoadModules) == 0 {
|
|
// Create empty modules.load file for system
|
|
// https://source.corp.google.com/h/googleplex-android/platform/build/+/ef55daac9954896161b26db4f3ef1781b5a5694c:core/Makefile;l=695-700;drc=549fe2a5162548bd8b47867d35f907eb22332023;bpv=1;bpt=0
|
|
props.Load_by_default = proptools.BoolPtr(false)
|
|
}
|
|
if blocklistFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.SystemKernelBlocklistFile; blocklistFile != "" {
|
|
props.Blocklist_file = proptools.StringPtr(blocklistFile)
|
|
}
|
|
case "vendor_dlkm":
|
|
props.Srcs = android.ExistentPathsForSources(ctx, ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorKernelModules).Strings()
|
|
if len(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.SystemKernelModules) > 0 {
|
|
props.System_deps = []string{":" + generatedModuleName(ctx.Config(), "system_dlkm-kernel-modules") + "{.modules}"}
|
|
}
|
|
props.Vendor_dlkm_specific = proptools.BoolPtr(true)
|
|
if blocklistFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorKernelBlocklistFile; blocklistFile != "" {
|
|
props.Blocklist_file = proptools.StringPtr(blocklistFile)
|
|
}
|
|
case "odm_dlkm":
|
|
props.Srcs = android.ExistentPathsForSources(ctx, ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.OdmKernelModules).Strings()
|
|
props.Odm_dlkm_specific = proptools.BoolPtr(true)
|
|
if blocklistFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.OdmKernelBlocklistFile; blocklistFile != "" {
|
|
props.Blocklist_file = proptools.StringPtr(blocklistFile)
|
|
}
|
|
case "vendor_ramdisk":
|
|
props.Srcs = android.ExistentPathsForSources(ctx, ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorRamdiskKernelModules).Strings()
|
|
props.Vendor_ramdisk = proptools.BoolPtr(true)
|
|
if blocklistFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorRamdiskKernelBlocklistFile; blocklistFile != "" {
|
|
props.Blocklist_file = proptools.StringPtr(blocklistFile)
|
|
}
|
|
if optionsFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorRamdiskKernelOptionsFile; optionsFile != "" {
|
|
props.Options_file = proptools.StringPtr(optionsFile)
|
|
}
|
|
|
|
default:
|
|
ctx.ModuleErrorf("DLKM is not supported for %s\n", partitionType)
|
|
}
|
|
|
|
if len(props.Srcs) == 0 {
|
|
return // do not generate `prebuilt_kernel_modules` if there are no sources
|
|
}
|
|
|
|
kernelModule := ctx.CreateModuleInDirectory(
|
|
kernel.PrebuiltKernelModulesFactory,
|
|
".", // create in root directory for now
|
|
props,
|
|
)
|
|
kernelModule.HideFromMake()
|
|
// Add to deps
|
|
(*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 a android_info for vendor
|
|
// The board info files might be in a directory outside the root soong namespace, so create
|
|
// the module in "."
|
|
partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
|
|
androidInfoProps := &struct {
|
|
Name *string
|
|
Board_info_files []string
|
|
Bootloader_board_name *string
|
|
}{
|
|
Name: proptools.StringPtr(generatedModuleName(ctx.Config(), "android-info.prop")),
|
|
Board_info_files: partitionVars.BoardInfoFiles,
|
|
}
|
|
if len(androidInfoProps.Board_info_files) == 0 {
|
|
androidInfoProps.Bootloader_board_name = proptools.StringPtr(partitionVars.BootLoaderBoardName)
|
|
}
|
|
androidInfoProp := ctx.CreateModuleInDirectory(
|
|
android.AndroidInfoFactory,
|
|
".",
|
|
androidInfoProps,
|
|
)
|
|
androidInfoProp.HideFromMake()
|
|
// Create a build prop for vendor
|
|
vendorBuildProps := &struct {
|
|
Name *string
|
|
Vendor *bool
|
|
Stem *string
|
|
Product_config *string
|
|
Android_info *string
|
|
}{
|
|
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(":" + androidInfoProp.Name()),
|
|
}
|
|
vendorBuildProp := ctx.CreateModule(
|
|
android.BuildPropFactory,
|
|
vendorBuildProps,
|
|
)
|
|
vendorBuildProp.HideFromMake()
|
|
}
|
|
|
|
// createLinkerConfigSourceFilegroups creates filegroup modules to generate linker.config.pb for the following partitions
|
|
// 1. vendor: Using PRODUCT_VENDOR_LINKER_CONFIG_FRAGMENTS (space separated file list)
|
|
// 1. product: Using PRODUCT_PRODUCT_LINKER_CONFIG_FRAGMENTS (space separated file list)
|
|
// It creates a filegroup for each file in the fragment list
|
|
// The filegroup modules are then added to `linker_config_srcs` of the autogenerated vendor `android_filesystem`.
|
|
func (f *filesystemCreator) createLinkerConfigSourceFilegroups(ctx android.LoadHookContext, partitionType string) []string {
|
|
ret := []string{}
|
|
partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
|
|
var linkerConfigSrcs []string
|
|
if partitionType == "vendor" {
|
|
linkerConfigSrcs = android.FirstUniqueStrings(partitionVars.VendorLinkerConfigSrcs)
|
|
} else if partitionType == "product" {
|
|
linkerConfigSrcs = android.FirstUniqueStrings(partitionVars.ProductLinkerConfigSrcs)
|
|
} else {
|
|
ctx.ModuleErrorf("linker.config.pb is only supported for vendor and product partitions. For system partition, use `android_system_image`")
|
|
}
|
|
|
|
if len(linkerConfigSrcs) > 0 {
|
|
// Create a filegroup, and add `:<filegroup_name>` to ret.
|
|
for index, linkerConfigSrc := range linkerConfigSrcs {
|
|
dir := filepath.Dir(linkerConfigSrc)
|
|
base := filepath.Base(linkerConfigSrc)
|
|
fgName := generatedModuleName(ctx.Config(), fmt.Sprintf("%s-linker-config-src%s", partitionType, strconv.Itoa(index)))
|
|
srcs := []string{base}
|
|
fgProps := &struct {
|
|
Name *string
|
|
Srcs proptools.Configurable[[]string]
|
|
}{
|
|
Name: proptools.StringPtr(fgName),
|
|
Srcs: proptools.NewSimpleConfigurable(srcs),
|
|
}
|
|
ctx.CreateModuleInDirectory(
|
|
android.FileGroupFactory,
|
|
dir,
|
|
fgProps,
|
|
)
|
|
ret = append(ret, ":"+fgName)
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
type filesystemBaseProperty struct {
|
|
Name *string
|
|
Compile_multilib *string
|
|
Visibility []string
|
|
}
|
|
|
|
func generateBaseProps(namePtr *string) *filesystemBaseProperty {
|
|
return &filesystemBaseProperty{
|
|
Name: namePtr,
|
|
Compile_multilib: proptools.StringPtr("both"),
|
|
// The vbmeta modules are currently in the root directory and depend on the partitions
|
|
Visibility: []string{"//.", "//build/soong:__subpackages__"},
|
|
}
|
|
}
|
|
|
|
func generateFsProps(ctx android.EarlyModuleContext, partitionType string) (*filesystem.FilesystemProperties, bool) {
|
|
fsProps := &filesystem.FilesystemProperties{}
|
|
|
|
partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
|
|
var avbInfo avbInfo
|
|
var fsType string
|
|
if strings.Contains(partitionType, "ramdisk") {
|
|
fsType = "compressed_cpio"
|
|
} else {
|
|
specificPartitionVars := partitionVars.PartitionQualifiedVariables[partitionType]
|
|
fsType = specificPartitionVars.BoardFileSystemType
|
|
avbInfo = getAvbInfo(ctx.Config(), partitionType)
|
|
if fsType == "" {
|
|
fsType = "ext4" //default
|
|
}
|
|
}
|
|
|
|
fsProps.Type = proptools.StringPtr(fsType)
|
|
if filesystem.GetFsTypeFromString(ctx, *fsProps.Type).IsUnknown() {
|
|
// Currently the android_filesystem module type only supports a handful of FS types like ext4, erofs
|
|
return nil, false
|
|
}
|
|
|
|
if *fsProps.Type == "erofs" {
|
|
if partitionVars.BoardErofsCompressor != "" {
|
|
fsProps.Erofs.Compressor = proptools.StringPtr(partitionVars.BoardErofsCompressor)
|
|
}
|
|
if partitionVars.BoardErofsCompressorHints != "" {
|
|
fsProps.Erofs.Compress_hints = proptools.StringPtr(":soong_generated_board_erofs_compress_hints_filegroup")
|
|
}
|
|
}
|
|
|
|
// Don't build this module on checkbuilds, the soong-built partitions are still in-progress
|
|
// and sometimes don't build.
|
|
fsProps.Unchecked_module = proptools.BoolPtr(true)
|
|
|
|
// BOARD_AVB_ENABLE
|
|
fsProps.Use_avb = avbInfo.avbEnable
|
|
// BOARD_AVB_KEY_PATH
|
|
fsProps.Avb_private_key = avbInfo.avbkeyFilegroup
|
|
// BOARD_AVB_ALGORITHM
|
|
fsProps.Avb_algorithm = avbInfo.avbAlgorithm
|
|
// BOARD_AVB_SYSTEM_ROLLBACK_INDEX
|
|
fsProps.Rollback_index = avbInfo.avbRollbackIndex
|
|
fsProps.Avb_hash_algorithm = avbInfo.avbHashAlgorithm
|
|
|
|
fsProps.Partition_name = proptools.StringPtr(partitionType)
|
|
|
|
switch partitionType {
|
|
// The partitions that support file_contexts came from here:
|
|
// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=2270;drc=ad7cfb56010cb22c3aa0e70cf71c804352553526
|
|
case "system", "userdata", "cache", "vendor", "product", "system_ext", "odm", "vendor_dlkm", "odm_dlkm", "system_dlkm", "oem":
|
|
fsProps.Precompiled_file_contexts = proptools.StringPtr(":file_contexts_bin_gen")
|
|
}
|
|
|
|
fsProps.Is_auto_generated = proptools.BoolPtr(true)
|
|
|
|
partitionSpecificFsProps(ctx, fsProps, partitionVars, partitionType)
|
|
|
|
return fsProps, true
|
|
}
|
|
|
|
type avbInfo struct {
|
|
avbEnable *bool
|
|
avbKeyPath *string
|
|
avbkeyFilegroup *string
|
|
avbAlgorithm *string
|
|
avbRollbackIndex *int64
|
|
avbMode *string
|
|
avbHashAlgorithm *string
|
|
}
|
|
|
|
func getAvbInfo(config android.Config, partitionType string) avbInfo {
|
|
partitionVars := config.ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
|
|
specificPartitionVars := partitionVars.PartitionQualifiedVariables[partitionType]
|
|
var result avbInfo
|
|
boardAvbEnable := partitionVars.BoardAvbEnable
|
|
if boardAvbEnable {
|
|
result.avbEnable = proptools.BoolPtr(true)
|
|
// There are "global" and "specific" copies of a lot of these variables. Sometimes they
|
|
// choose the specific and then fall back to the global one if it's not set, other times
|
|
// the global one actually only applies to the vbmeta partition.
|
|
if partitionType == "vbmeta" {
|
|
if partitionVars.BoardAvbKeyPath != "" {
|
|
result.avbKeyPath = proptools.StringPtr(partitionVars.BoardAvbKeyPath)
|
|
}
|
|
if partitionVars.BoardAvbRollbackIndex != "" {
|
|
parsed, err := strconv.ParseInt(partitionVars.BoardAvbRollbackIndex, 10, 64)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("Rollback index must be an int, got %s", partitionVars.BoardAvbRollbackIndex))
|
|
}
|
|
result.avbRollbackIndex = &parsed
|
|
}
|
|
}
|
|
if specificPartitionVars.BoardAvbKeyPath != "" {
|
|
result.avbKeyPath = proptools.StringPtr(specificPartitionVars.BoardAvbKeyPath)
|
|
}
|
|
if specificPartitionVars.BoardAvbAlgorithm != "" {
|
|
result.avbAlgorithm = proptools.StringPtr(specificPartitionVars.BoardAvbAlgorithm)
|
|
} else if partitionVars.BoardAvbAlgorithm != "" {
|
|
result.avbAlgorithm = proptools.StringPtr(partitionVars.BoardAvbAlgorithm)
|
|
}
|
|
if specificPartitionVars.BoardAvbRollbackIndex != "" {
|
|
parsed, err := strconv.ParseInt(specificPartitionVars.BoardAvbRollbackIndex, 10, 64)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("Rollback index must be an int, got %s", specificPartitionVars.BoardAvbRollbackIndex))
|
|
}
|
|
result.avbRollbackIndex = &parsed
|
|
}
|
|
if specificPartitionVars.BoardAvbRollbackIndex != "" {
|
|
parsed, err := strconv.ParseInt(specificPartitionVars.BoardAvbRollbackIndex, 10, 64)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("Rollback index must be an int, got %s", specificPartitionVars.BoardAvbRollbackIndex))
|
|
}
|
|
result.avbRollbackIndex = &parsed
|
|
}
|
|
|
|
// Make allows you to pass arbitrary arguments to avbtool via this variable, but in practice
|
|
// it's only used for --hash_algorithm. The soong module has a dedicated property for the
|
|
// hashtree algorithm, and doesn't allow custom arguments, so just extract the hashtree
|
|
// algorithm out of the arbitrary arguments.
|
|
addHashtreeFooterArgs := strings.Split(specificPartitionVars.BoardAvbAddHashtreeFooterArgs, " ")
|
|
if i := slices.Index(addHashtreeFooterArgs, "--hash_algorithm"); i >= 0 {
|
|
result.avbHashAlgorithm = &addHashtreeFooterArgs[i+1]
|
|
}
|
|
|
|
result.avbMode = proptools.StringPtr("make_legacy")
|
|
}
|
|
if result.avbKeyPath != nil {
|
|
fsGenState := config.Get(fsGenStateOnceKey).(*FsGenState)
|
|
filegroup := fsGenState.avbKeyFilegroups[*result.avbKeyPath]
|
|
result.avbkeyFilegroup = proptools.StringPtr(":" + filegroup)
|
|
}
|
|
return result
|
|
}
|
|
|
|
func (f *filesystemCreator) createFileListDiffTest(ctx android.ModuleContext, partitionType string) android.Path {
|
|
partitionModuleName := generatedModuleNameForPartition(ctx.Config(), partitionType)
|
|
systemImage := ctx.GetDirectDepWithTag(partitionModuleName, generatedFilesystemDepTag)
|
|
filesystemInfo, ok := android.OtherModuleProvider(ctx, systemImage, filesystem.FilesystemProvider)
|
|
if !ok {
|
|
ctx.ModuleErrorf("Expected module %s to provide FileysystemInfo", partitionModuleName)
|
|
}
|
|
makeFileList := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/obj/PACKAGING/%s_intermediates/file_list.txt", ctx.Config().DeviceName(), partitionType))
|
|
diffTestResultFile := android.PathForModuleOut(ctx, fmt.Sprintf("diff_test_%s.txt", partitionModuleName))
|
|
|
|
builder := android.NewRuleBuilder(pctx, ctx)
|
|
builder.Command().BuiltTool("file_list_diff").
|
|
Input(makeFileList).
|
|
Input(filesystemInfo.FileListFile).
|
|
Text(partitionModuleName)
|
|
builder.Command().Text("touch").Output(diffTestResultFile)
|
|
builder.Build(partitionModuleName+" diff test", partitionModuleName+" diff test")
|
|
return diffTestResultFile
|
|
}
|
|
|
|
func createFailingCommand(ctx android.ModuleContext, message string) android.Path {
|
|
hasher := sha256.New()
|
|
hasher.Write([]byte(message))
|
|
filename := fmt.Sprintf("failing_command_%x.txt", hasher.Sum(nil))
|
|
file := android.PathForModuleOut(ctx, filename)
|
|
builder := android.NewRuleBuilder(pctx, ctx)
|
|
builder.Command().Textf("echo %s", proptools.NinjaAndShellEscape(message))
|
|
builder.Command().Text("exit 1 #").Output(file)
|
|
builder.Build("failing command "+filename, "failing command "+filename)
|
|
return file
|
|
}
|
|
|
|
func createVbmetaDiff(ctx android.ModuleContext, vbmetaModuleName string, vbmetaPartitionName string) android.Path {
|
|
vbmetaModule := ctx.GetDirectDepWithTag(vbmetaModuleName, generatedVbmetaPartitionDepTag)
|
|
outputFilesProvider, ok := android.OtherModuleProvider(ctx, vbmetaModule, android.OutputFilesProvider)
|
|
if !ok {
|
|
ctx.ModuleErrorf("Expected module %s to provide OutputFiles", vbmetaModule)
|
|
}
|
|
if len(outputFilesProvider.DefaultOutputFiles) != 1 {
|
|
ctx.ModuleErrorf("Expected 1 output file from module %s", vbmetaModule)
|
|
}
|
|
soongVbMetaFile := outputFilesProvider.DefaultOutputFiles[0]
|
|
makeVbmetaFile := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/%s.img", ctx.Config().DeviceName(), vbmetaPartitionName))
|
|
|
|
diffTestResultFile := android.PathForModuleOut(ctx, fmt.Sprintf("diff_test_%s.txt", vbmetaModuleName))
|
|
createDiffTest(ctx, diffTestResultFile, soongVbMetaFile, makeVbmetaFile)
|
|
return diffTestResultFile
|
|
}
|
|
|
|
func createDiffTest(ctx android.ModuleContext, diffTestResultFile android.WritablePath, file1 android.Path, file2 android.Path) {
|
|
builder := android.NewRuleBuilder(pctx, ctx)
|
|
builder.Command().Text("diff").
|
|
Input(file1).
|
|
Input(file2)
|
|
builder.Command().Text("touch").Output(diffTestResultFile)
|
|
builder.Build("diff test "+diffTestResultFile.String(), "diff test")
|
|
}
|
|
|
|
type systemImageDepTagType struct {
|
|
blueprint.BaseDependencyTag
|
|
}
|
|
|
|
var generatedFilesystemDepTag systemImageDepTagType
|
|
var generatedVbmetaPartitionDepTag systemImageDepTagType
|
|
|
|
func (f *filesystemCreator) DepsMutator(ctx android.BottomUpMutatorContext) {
|
|
for _, partitionType := range f.properties.Generated_partition_types {
|
|
ctx.AddDependency(ctx.Module(), generatedFilesystemDepTag, generatedModuleNameForPartition(ctx.Config(), partitionType))
|
|
}
|
|
for _, vbmetaModule := range f.properties.Vbmeta_module_names {
|
|
ctx.AddDependency(ctx.Module(), generatedVbmetaPartitionDepTag, vbmetaModule)
|
|
}
|
|
}
|
|
|
|
func (f *filesystemCreator) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|
if ctx.ModuleDir() != "build/soong/fsgen" {
|
|
ctx.ModuleErrorf("There can only be one soong_filesystem_creator in build/soong/fsgen")
|
|
}
|
|
f.HideFromMake()
|
|
|
|
var content strings.Builder
|
|
generatedBp := android.PathForModuleOut(ctx, "soong_generated_product_config.bp")
|
|
for _, partition := range ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).soongGeneratedPartitions {
|
|
content.WriteString(generateBpContent(ctx, partition))
|
|
content.WriteString("\n")
|
|
}
|
|
android.WriteFileRule(ctx, generatedBp, content.String())
|
|
|
|
ctx.Phony("product_config_to_bp", generatedBp)
|
|
|
|
var diffTestFiles []android.Path
|
|
for _, partitionType := range f.properties.Generated_partition_types {
|
|
diffTestFile := f.createFileListDiffTest(ctx, partitionType)
|
|
diffTestFiles = append(diffTestFiles, diffTestFile)
|
|
ctx.Phony(fmt.Sprintf("soong_generated_%s_filesystem_test", partitionType), diffTestFile)
|
|
}
|
|
for _, partitionType := range f.properties.Unsupported_partition_types {
|
|
diffTestFile := createFailingCommand(ctx, fmt.Sprintf("Couldn't build %s partition", partitionType))
|
|
diffTestFiles = append(diffTestFiles, diffTestFile)
|
|
ctx.Phony(fmt.Sprintf("soong_generated_%s_filesystem_test", partitionType), diffTestFile)
|
|
}
|
|
for i, vbmetaModule := range f.properties.Vbmeta_module_names {
|
|
diffTestFile := createVbmetaDiff(ctx, vbmetaModule, f.properties.Vbmeta_partition_names[i])
|
|
diffTestFiles = append(diffTestFiles, diffTestFile)
|
|
ctx.Phony(fmt.Sprintf("soong_generated_%s_filesystem_test", f.properties.Vbmeta_partition_names[i]), diffTestFile)
|
|
}
|
|
if f.properties.Boot_image != "" {
|
|
diffTestFile := android.PathForModuleOut(ctx, "boot_diff_test.txt")
|
|
soongBootImg := android.PathForModuleSrc(ctx, f.properties.Boot_image)
|
|
makeBootImage := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/boot.img", ctx.Config().DeviceName()))
|
|
createDiffTest(ctx, diffTestFile, soongBootImg, makeBootImage)
|
|
diffTestFiles = append(diffTestFiles, diffTestFile)
|
|
ctx.Phony("soong_generated_boot_filesystem_test", diffTestFile)
|
|
}
|
|
if f.properties.Vendor_boot_image != "" {
|
|
diffTestFile := android.PathForModuleOut(ctx, "vendor_boot_diff_test.txt")
|
|
soongBootImg := android.PathForModuleSrc(ctx, f.properties.Vendor_boot_image)
|
|
makeBootImage := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/vendor_boot.img", ctx.Config().DeviceName()))
|
|
createDiffTest(ctx, diffTestFile, soongBootImg, makeBootImage)
|
|
diffTestFiles = append(diffTestFiles, diffTestFile)
|
|
ctx.Phony("soong_generated_vendor_boot_filesystem_test", diffTestFile)
|
|
}
|
|
if f.properties.Init_boot_image != "" {
|
|
diffTestFile := android.PathForModuleOut(ctx, "init_boot_diff_test.txt")
|
|
soongBootImg := android.PathForModuleSrc(ctx, f.properties.Init_boot_image)
|
|
makeBootImage := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/init_boot.img", ctx.Config().DeviceName()))
|
|
createDiffTest(ctx, diffTestFile, soongBootImg, makeBootImage)
|
|
diffTestFiles = append(diffTestFiles, diffTestFile)
|
|
ctx.Phony("soong_generated_init_boot_filesystem_test", diffTestFile)
|
|
}
|
|
if f.properties.Super_image != "" {
|
|
diffTestFile := android.PathForModuleOut(ctx, "super_diff_test.txt")
|
|
soongSuperImg := android.PathForModuleSrc(ctx, f.properties.Super_image)
|
|
makeSuperImage := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/super.img", ctx.Config().DeviceName()))
|
|
createDiffTest(ctx, diffTestFile, soongSuperImg, makeSuperImage)
|
|
diffTestFiles = append(diffTestFiles, diffTestFile)
|
|
ctx.Phony("soong_generated_super_filesystem_test", diffTestFile)
|
|
}
|
|
ctx.Phony("soong_generated_filesystem_tests", diffTestFiles...)
|
|
}
|
|
|
|
func generateBpContent(ctx android.EarlyModuleContext, partitionType string) string {
|
|
fsProps, fsTypeSupported := generateFsProps(ctx, partitionType)
|
|
if !fsTypeSupported {
|
|
return ""
|
|
}
|
|
|
|
baseProps := generateBaseProps(proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), partitionType)))
|
|
fsGenState := ctx.Config().Get(fsGenStateOnceKey).(*FsGenState)
|
|
deps := fsGenState.fsDeps[partitionType]
|
|
highPriorityDeps := fsGenState.generatedPrebuiltEtcModuleNames
|
|
depProps := generateDepStruct(*deps, highPriorityDeps)
|
|
|
|
result, err := proptools.RepackProperties([]interface{}{baseProps, fsProps, depProps})
|
|
if err != nil {
|
|
ctx.ModuleErrorf("%s", err.Error())
|
|
return ""
|
|
}
|
|
|
|
moduleType := "android_filesystem"
|
|
if partitionType == "system" {
|
|
moduleType = "android_system_image"
|
|
}
|
|
|
|
file := &parser.File{
|
|
Defs: []parser.Definition{
|
|
&parser.Module{
|
|
Type: moduleType,
|
|
Map: *result,
|
|
},
|
|
},
|
|
}
|
|
bytes, err := parser.Print(file)
|
|
if err != nil {
|
|
ctx.ModuleErrorf(err.Error())
|
|
}
|
|
return strings.TrimSpace(string(bytes))
|
|
}
|