diff options
| -rw-r--r-- | android/config.go | 28 | ||||
| -rw-r--r-- | android/neverallow.go | 2 | ||||
| -rw-r--r-- | android/variable.go | 4 | ||||
| -rw-r--r-- | etc/prebuilt_etc.go | 44 | ||||
| -rw-r--r-- | fsgen/Android.bp | 2 | ||||
| -rw-r--r-- | fsgen/filesystem_creator.go | 324 | ||||
| -rw-r--r-- | fsgen/fsgen_mutators.go | 343 | ||||
| -rw-r--r-- | fsgen/prebuilt_etc_modules_gen.go | 298 |
8 files changed, 723 insertions, 322 deletions
diff --git a/android/config.go b/android/config.go index 16d77db6b..275c07fc4 100644 --- a/android/config.go +++ b/android/config.go @@ -1522,6 +1522,13 @@ func (c *deviceConfig) VendorPath() string { return "vendor" } +func (c *deviceConfig) VendorDlkmPath() string { + if c.config.productVariables.VendorDlkmPath != nil { + return *c.config.productVariables.VendorDlkmPath + } + return "vendor_dlkm" +} + func (c *deviceConfig) BuildingVendorImage() bool { return proptools.Bool(c.config.productVariables.BuildingVendorImage) } @@ -1553,6 +1560,13 @@ func (c *deviceConfig) BuildingOdmImage() bool { return proptools.Bool(c.config.productVariables.BuildingOdmImage) } +func (c *deviceConfig) OdmDlkmPath() string { + if c.config.productVariables.OdmDlkmPath != nil { + return *c.config.productVariables.OdmDlkmPath + } + return "odm_dlkm" +} + func (c *deviceConfig) ProductPath() string { if c.config.productVariables.ProductPath != nil { return *c.config.productVariables.ProductPath @@ -1571,6 +1585,20 @@ func (c *deviceConfig) SystemExtPath() string { return "system_ext" } +func (c *deviceConfig) SystemDlkmPath() string { + if c.config.productVariables.SystemDlkmPath != nil { + return *c.config.productVariables.SystemDlkmPath + } + return "system_dlkm" +} + +func (c *deviceConfig) OemPath() string { + if c.config.productVariables.OemPath != nil { + return *c.config.productVariables.OemPath + } + return "oem" +} + func (c *deviceConfig) BtConfigIncludeDir() string { return String(c.config.productVariables.BtConfigIncludeDir) } diff --git a/android/neverallow.go b/android/neverallow.go index 7fb22bf13..6251e2b0d 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -334,6 +334,8 @@ func createPrebuiltEtcBpDefineRule() Rule { "prebuilt_res", "prebuilt_wlc_upt", "prebuilt_odm", + "prebuilt_vendor_dlkm", + "prebuilt_bt_firmware", ). DefinedInBpFile(). Because("module type not allowed to be defined in bp file") diff --git a/android/variable.go b/android/variable.go index df9db7c22..2ca771481 100644 --- a/android/variable.go +++ b/android/variable.go @@ -339,12 +339,16 @@ type ProductVariables struct { HWASanExcludePaths []string `json:",omitempty"` VendorPath *string `json:",omitempty"` + VendorDlkmPath *string `json:",omitempty"` BuildingVendorImage *bool `json:",omitempty"` OdmPath *string `json:",omitempty"` BuildingOdmImage *bool `json:",omitempty"` + OdmDlkmPath *string `json:",omitempty"` ProductPath *string `json:",omitempty"` BuildingProductImage *bool `json:",omitempty"` SystemExtPath *string `json:",omitempty"` + SystemDlkmPath *string `json:",omitempty"` + OemPath *string `json:",omitempty"` ClangTidy *bool `json:",omitempty"` TidyChecks *string `json:",omitempty"` diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go index a46da77e8..938f3bde3 100644 --- a/etc/prebuilt_etc.go +++ b/etc/prebuilt_etc.go @@ -76,6 +76,8 @@ func RegisterPrebuiltEtcBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("prebuilt_res", PrebuiltResFactory) ctx.RegisterModuleType("prebuilt_wlc_upt", PrebuiltWlcUptFactory) ctx.RegisterModuleType("prebuilt_odm", PrebuiltOdmFactory) + ctx.RegisterModuleType("prebuilt_vendor_dlkm", PrebuiltVendorDlkmFactory) + ctx.RegisterModuleType("prebuilt_bt_firmware", PrebuiltBtFirmwareFactory) ctx.RegisterModuleType("prebuilt_defaults", defaultsFactory) @@ -132,6 +134,18 @@ type prebuiltEtcProperties struct { // Install symlinks to the installed file. Symlinks []string `android:"arch_variant"` + + // Install to partition system_dlkm when set to true. + System_dlkm_specific *bool `android:"arch_variant"` + + // Install to partition vendor_dlkm when set to true. + Vendor_dlkm_specific *bool `android:"arch_variant"` + + // Install to partition odm_dlkm when set to true. + Odm_dlkm_specific *bool `android:"arch_variant"` + + // Install to partition oem when set to true. + Oem_specific *bool `android:"arch_variant"` } type prebuiltSubdirProperties struct { @@ -369,6 +383,16 @@ func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.PropertyErrorf("sub_dir", "relative_install_path is set. Cannot set sub_dir") } baseInstallDirPath := android.PathForModuleInstall(ctx, p.installBaseDir(ctx), p.SubDir()) + // TODO(b/377304441) + if android.Bool(p.properties.System_dlkm_specific) { + baseInstallDirPath = android.PathForModuleInPartitionInstall(ctx, ctx.DeviceConfig().SystemDlkmPath(), p.installBaseDir(ctx), p.SubDir()) + } else if android.Bool(p.properties.Vendor_dlkm_specific) { + baseInstallDirPath = android.PathForModuleInPartitionInstall(ctx, ctx.DeviceConfig().VendorDlkmPath(), p.installBaseDir(ctx), p.SubDir()) + } else if android.Bool(p.properties.Odm_dlkm_specific) { + baseInstallDirPath = android.PathForModuleInPartitionInstall(ctx, ctx.DeviceConfig().OdmDlkmPath(), p.installBaseDir(ctx), p.SubDir()) + } else if android.Bool(p.properties.Oem_specific) { + baseInstallDirPath = android.PathForModuleInPartitionInstall(ctx, ctx.DeviceConfig().OemPath(), p.installBaseDir(ctx), p.SubDir()) + } filename := proptools.String(p.properties.Filename) filenameFromSrc := proptools.Bool(p.properties.Filename_from_src) @@ -910,3 +934,23 @@ func PrebuiltOdmFactory() android.Module { android.InitDefaultableModule(module) return module } + +// prebuilt_vendor_dlkm installs files in <partition>/vendor_dlkm directory. +func PrebuiltVendorDlkmFactory() android.Module { + module := &PrebuiltEtc{} + InitPrebuiltEtcModule(module, "vendor_dlkm") + // This module is device-only + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) + android.InitDefaultableModule(module) + return module +} + +// prebuilt_bt_firmware installs files in <partition>/bt_firmware directory. +func PrebuiltBtFirmwareFactory() android.Module { + module := &PrebuiltEtc{} + InitPrebuiltEtcModule(module, "bt_firmware") + // This module is device-only + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) + android.InitDefaultableModule(module) + return module +} diff --git a/fsgen/Android.bp b/fsgen/Android.bp index e3cbdb375..690ad2821 100644 --- a/fsgen/Android.bp +++ b/fsgen/Android.bp @@ -14,6 +14,8 @@ bootstrap_go_package { ], srcs: [ "filesystem_creator.go", + "fsgen_mutators.go", + "prebuilt_etc_modules_gen.go", ], testSrcs: [ "filesystem_creator_test.go", diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go index c3f63493b..5d887677c 100644 --- a/fsgen/filesystem_creator.go +++ b/fsgen/filesystem_creator.go @@ -18,10 +18,8 @@ import ( "crypto/sha256" "fmt" "path/filepath" - "slices" "strconv" "strings" - "sync" "android/soong/android" "android/soong/filesystem" @@ -43,325 +41,6 @@ func registerBuildComponents(ctx android.RegistrationContext) { ctx.PreDepsMutators(RegisterCollectFileSystemDepsMutators) } -func RegisterCollectFileSystemDepsMutators(ctx android.RegisterMutatorsContext) { - ctx.BottomUp("fs_collect_deps", collectDepsMutator).MutatesGlobalState() - ctx.BottomUp("fs_set_deps", setDepsMutator) -} - -var fsGenStateOnceKey = android.NewOnceKey("FsGenState") -var fsGenRemoveOverridesOnceKey = android.NewOnceKey("FsGenRemoveOverrides") - -// Map of partition module name to its partition that may be generated by Soong. -// Note that it is not guaranteed that all modules returned by this function are successfully -// created. -func getAllSoongGeneratedPartitionNames(config android.Config, partitions []string) map[string]string { - ret := map[string]string{} - for _, partition := range partitions { - ret[generatedModuleNameForPartition(config, partition)] = partition - } - return ret -} - -type depCandidateProps struct { - Namespace string - Multilib string - Arch []android.ArchType -} - -// Map of module name to depCandidateProps -type multilibDeps map[string]*depCandidateProps - -// Information necessary to generate the filesystem modules, including details about their -// dependencies -type FsGenState struct { - // List of modules in `PRODUCT_PACKAGES` and `PRODUCT_PACKAGES_DEBUG` - depCandidates []string - // Map of names of partition to the information of modules to be added as deps - fsDeps map[string]*multilibDeps - // List of name of partitions to be generated by the filesystem_creator module - soongGeneratedPartitions []string - // Mutex to protect the fsDeps - fsDepsMutex sync.Mutex - // Map of _all_ soong module names to their corresponding installation properties - moduleToInstallationProps map[string]installationProperties -} - -type installationProperties struct { - Required []string - Overrides []string -} - -func defaultDepCandidateProps(config android.Config) *depCandidateProps { - return &depCandidateProps{ - Namespace: ".", - Arch: []android.ArchType{config.BuildArch}, - } -} - -func createFsGenState(ctx android.LoadHookContext) *FsGenState { - return ctx.Config().Once(fsGenStateOnceKey, func() interface{} { - partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse - candidates := android.FirstUniqueStrings(android.Concat(partitionVars.ProductPackages, partitionVars.ProductPackagesDebug)) - - 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 partitionVars.BuildingSystemDlkmImage { - generatedPartitions = append(generatedPartitions, "system_dlkm") - } - - return &FsGenState{ - depCandidates: candidates, - fsDeps: map[string]*multilibDeps{ - // These additional deps are added according to the cuttlefish system image bp. - "system": { - "com.android.apex.cts.shim.v1_prebuilt": defaultDepCandidateProps(ctx.Config()), - "dex_bootjars": defaultDepCandidateProps(ctx.Config()), - "framework_compatibility_matrix.device.xml": defaultDepCandidateProps(ctx.Config()), - "idc_data": defaultDepCandidateProps(ctx.Config()), - "init.environ.rc-soong": defaultDepCandidateProps(ctx.Config()), - "keychars_data": defaultDepCandidateProps(ctx.Config()), - "keylayout_data": defaultDepCandidateProps(ctx.Config()), - "libclang_rt.asan": defaultDepCandidateProps(ctx.Config()), - "libcompiler_rt": defaultDepCandidateProps(ctx.Config()), - "libdmabufheap": defaultDepCandidateProps(ctx.Config()), - "libgsi": defaultDepCandidateProps(ctx.Config()), - "llndk.libraries.txt": defaultDepCandidateProps(ctx.Config()), - "logpersist.start": defaultDepCandidateProps(ctx.Config()), - "preloaded-classes": defaultDepCandidateProps(ctx.Config()), - "public.libraries.android.txt": defaultDepCandidateProps(ctx.Config()), - "update_engine_sideload": defaultDepCandidateProps(ctx.Config()), - }, - "vendor": { - "fs_config_files_vendor": defaultDepCandidateProps(ctx.Config()), - "fs_config_dirs_vendor": defaultDepCandidateProps(ctx.Config()), - generatedModuleName(ctx.Config(), "vendor-build.prop"): defaultDepCandidateProps(ctx.Config()), - }, - "odm": { - // fs_config_* files are automatically installed for all products with odm partitions. - // https://cs.android.com/android/_/android/platform/build/+/e4849e87ab660b59a6501b3928693db065ee873b:tools/fs_config/Android.mk;l=34;drc=8d6481b92c4b4e9b9f31a61545b6862090fcc14b;bpv=1;bpt=0 - "fs_config_files_odm": defaultDepCandidateProps(ctx.Config()), - "fs_config_dirs_odm": defaultDepCandidateProps(ctx.Config()), - }, - "product": {}, - "system_ext": { - // VNDK apexes are automatically included. - // This hardcoded list will need to be updated if `PRODUCT_EXTRA_VNDK_VERSIONS` is updated. - // https://cs.android.com/android/_/android/platform/build/+/adba533072b00c53ac0f198c550a3cbd7a00e4cd:core/main.mk;l=984;bpv=1;bpt=0;drc=174db7b179592cf07cbfd2adb0119486fda911e7 - "com.android.vndk.v30": defaultDepCandidateProps(ctx.Config()), - "com.android.vndk.v31": defaultDepCandidateProps(ctx.Config()), - "com.android.vndk.v32": defaultDepCandidateProps(ctx.Config()), - "com.android.vndk.v33": defaultDepCandidateProps(ctx.Config()), - "com.android.vndk.v34": defaultDepCandidateProps(ctx.Config()), - }, - "system_dlkm": {}, - }, - soongGeneratedPartitions: generatedPartitions, - fsDepsMutex: sync.Mutex{}, - moduleToInstallationProps: map[string]installationProperties{}, - } - }).(*FsGenState) -} - -func checkDepModuleInMultipleNamespaces(mctx android.BottomUpMutatorContext, foundDeps multilibDeps, module string, partitionName string) { - otherNamespace := mctx.Namespace().Path - if val, found := foundDeps[module]; found && otherNamespace != "." && !android.InList(val.Namespace, []string{".", otherNamespace}) { - mctx.ModuleErrorf("found in multiple namespaces(%s and %s) when including in %s partition", val.Namespace, otherNamespace, partitionName) - } -} - -func appendDepIfAppropriate(mctx android.BottomUpMutatorContext, deps *multilibDeps, installPartition string) { - checkDepModuleInMultipleNamespaces(mctx, *deps, mctx.Module().Name(), installPartition) - if _, ok := (*deps)[mctx.Module().Name()]; ok { - // Prefer the namespace-specific module over the platform module - if mctx.Namespace().Path != "." { - (*deps)[mctx.Module().Name()].Namespace = mctx.Namespace().Path - } - (*deps)[mctx.Module().Name()].Arch = append((*deps)[mctx.Module().Name()].Arch, mctx.Module().Target().Arch.ArchType) - } else { - multilib, _ := mctx.Module().DecodeMultilib(mctx) - (*deps)[mctx.Module().Name()] = &depCandidateProps{ - Namespace: mctx.Namespace().Path, - Multilib: multilib, - Arch: []android.ArchType{mctx.Module().Target().Arch.ArchType}, - } - } -} - -func collectDepsMutator(mctx android.BottomUpMutatorContext) { - fsGenState := mctx.Config().Get(fsGenStateOnceKey).(*FsGenState) - - m := mctx.Module() - if m.Target().Os.Class == android.Device && slices.Contains(fsGenState.depCandidates, m.Name()) { - installPartition := m.PartitionTag(mctx.DeviceConfig()) - fsGenState.fsDepsMutex.Lock() - // Only add the module as dependency when: - // - its enabled - // - its namespace is included in PRODUCT_SOONG_NAMESPACES - if m.Enabled(mctx) && m.ExportedToMake() { - appendDepIfAppropriate(mctx, fsGenState.fsDeps[installPartition], installPartition) - } - fsGenState.fsDepsMutex.Unlock() - } - // store the map of module to (required,overrides) even if the module is not in PRODUCT_PACKAGES. - // the module might be installed transitively. - if m.Target().Os.Class == android.Device && m.Enabled(mctx) && m.ExportedToMake() { - fsGenState.fsDepsMutex.Lock() - fsGenState.moduleToInstallationProps[m.Name()] = installationProperties{ - Required: m.RequiredModuleNames(mctx), - Overrides: m.Overrides(), - } - fsGenState.fsDepsMutex.Unlock() - } -} - -type depsStruct struct { - Deps []string -} - -type multilibDepsStruct struct { - Common depsStruct - Lib32 depsStruct - Lib64 depsStruct - Both depsStruct - Prefer32 depsStruct -} - -type packagingPropsStruct struct { - High_priority_deps []string - Deps []string - Multilib multilibDepsStruct -} - -func fullyQualifiedModuleName(moduleName, namespace string) string { - if namespace == "." { - return moduleName - } - return fmt.Sprintf("//%s:%s", namespace, moduleName) -} - -func getBitness(archTypes []android.ArchType) (ret []string) { - for _, archType := range archTypes { - if archType.Multilib == "" { - ret = append(ret, android.COMMON_VARIANT) - } else { - ret = append(ret, archType.Bitness()) - } - } - return ret -} - -func setDepsMutator(mctx android.BottomUpMutatorContext) { - removeOverriddenDeps(mctx) - fsGenState := mctx.Config().Get(fsGenStateOnceKey).(*FsGenState) - fsDeps := fsGenState.fsDeps - soongGeneratedPartitionMap := getAllSoongGeneratedPartitionNames(mctx.Config(), fsGenState.soongGeneratedPartitions) - m := mctx.Module() - if partition, ok := soongGeneratedPartitionMap[m.Name()]; ok { - depsStruct := generateDepStruct(*fsDeps[partition]) - if err := proptools.AppendMatchingProperties(m.GetProperties(), depsStruct, nil); err != nil { - mctx.ModuleErrorf(err.Error()) - } - } -} - -// removeOverriddenDeps collects PRODUCT_PACKAGES and (transitive) required deps. -// it then removes any modules which appear in `overrides` of the above list. -func removeOverriddenDeps(mctx android.BottomUpMutatorContext) { - mctx.Config().Once(fsGenRemoveOverridesOnceKey, func() interface{} { - fsGenState := mctx.Config().Get(fsGenStateOnceKey).(*FsGenState) - fsDeps := fsGenState.fsDeps - overridden := map[string]bool{} - allDeps := []string{} - - // Step 1: Initialization: Append PRODUCT_PACKAGES to the queue - for _, fsDep := range fsDeps { - for depName, _ := range *fsDep { - allDeps = append(allDeps, depName) - } - } - - // Step 2: Process the queue, and add required modules to the queue. - i := 0 - for { - if i == len(allDeps) { - break - } - depName := allDeps[i] - for _, overrides := range fsGenState.moduleToInstallationProps[depName].Overrides { - overridden[overrides] = true - } - // add required dep to the queue. - allDeps = append(allDeps, fsGenState.moduleToInstallationProps[depName].Required...) - i += 1 - } - - // Step 3: Delete all the overridden modules. - for overridden, _ := range overridden { - for partition, _ := range fsDeps { - delete(*fsDeps[partition], overridden) - } - } - return nil - }) -} - -var HighPriorityDeps = []string{} - -func generateDepStruct(deps map[string]*depCandidateProps) *packagingPropsStruct { - depsStruct := packagingPropsStruct{} - for depName, depProps := range deps { - bitness := getBitness(depProps.Arch) - fullyQualifiedDepName := fullyQualifiedModuleName(depName, depProps.Namespace) - if android.InList(depName, HighPriorityDeps) { - depsStruct.High_priority_deps = append(depsStruct.High_priority_deps, fullyQualifiedDepName) - } else if android.InList("32", bitness) && android.InList("64", bitness) { - // If both 32 and 64 bit variants are enabled for this module - switch depProps.Multilib { - case string(android.MultilibBoth): - depsStruct.Multilib.Both.Deps = append(depsStruct.Multilib.Both.Deps, fullyQualifiedDepName) - case string(android.MultilibCommon), string(android.MultilibFirst): - depsStruct.Deps = append(depsStruct.Deps, fullyQualifiedDepName) - case "32": - depsStruct.Multilib.Lib32.Deps = append(depsStruct.Multilib.Lib32.Deps, fullyQualifiedDepName) - case "64", "darwin_universal": - depsStruct.Multilib.Lib64.Deps = append(depsStruct.Multilib.Lib64.Deps, fullyQualifiedDepName) - case "prefer32", "first_prefer32": - depsStruct.Multilib.Prefer32.Deps = append(depsStruct.Multilib.Prefer32.Deps, fullyQualifiedDepName) - default: - depsStruct.Multilib.Both.Deps = append(depsStruct.Multilib.Both.Deps, fullyQualifiedDepName) - } - } else if android.InList("64", bitness) { - // If only 64 bit variant is enabled - depsStruct.Multilib.Lib64.Deps = append(depsStruct.Multilib.Lib64.Deps, fullyQualifiedDepName) - } else if android.InList("32", bitness) { - // If only 32 bit variant is enabled - depsStruct.Multilib.Lib32.Deps = append(depsStruct.Multilib.Lib32.Deps, fullyQualifiedDepName) - } else { - // If only common variant is enabled - depsStruct.Multilib.Common.Deps = append(depsStruct.Multilib.Common.Deps, fullyQualifiedDepName) - } - } - depsStruct.Deps = android.SortedUniqueStrings(depsStruct.Deps) - depsStruct.Multilib.Lib32.Deps = android.SortedUniqueStrings(depsStruct.Multilib.Lib32.Deps) - depsStruct.Multilib.Lib64.Deps = android.SortedUniqueStrings(depsStruct.Multilib.Lib64.Deps) - depsStruct.Multilib.Prefer32.Deps = android.SortedUniqueStrings(depsStruct.Multilib.Prefer32.Deps) - depsStruct.Multilib.Both.Deps = android.SortedUniqueStrings(depsStruct.Multilib.Both.Deps) - depsStruct.Multilib.Common.Deps = android.SortedUniqueStrings(depsStruct.Multilib.Common.Deps) - - return &depsStruct -} - type filesystemCreatorProps struct { Generated_partition_types []string `blueprint:"mutated"` Unsupported_partition_types []string `blueprint:"mutated"` @@ -379,7 +58,8 @@ func filesystemCreatorFactory() android.Module { android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) module.AddProperties(&module.properties) android.AddLoadHook(module, func(ctx android.LoadHookContext) { - createFsGenState(ctx) + generatedPrebuiltEtcModuleNames := createPrebuiltEtcModules(ctx) + createFsGenState(ctx, generatedPrebuiltEtcModuleNames) module.createInternalModules(ctx) }) diff --git a/fsgen/fsgen_mutators.go b/fsgen/fsgen_mutators.go new file mode 100644 index 000000000..bf07ab3a8 --- /dev/null +++ b/fsgen/fsgen_mutators.go @@ -0,0 +1,343 @@ +// 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 ( + "android/soong/android" + "fmt" + "slices" + "sync" + + "github.com/google/blueprint/proptools" +) + +func RegisterCollectFileSystemDepsMutators(ctx android.RegisterMutatorsContext) { + ctx.BottomUp("fs_collect_deps", collectDepsMutator).MutatesGlobalState() + ctx.BottomUp("fs_set_deps", setDepsMutator) +} + +var fsGenStateOnceKey = android.NewOnceKey("FsGenState") +var fsGenRemoveOverridesOnceKey = android.NewOnceKey("FsGenRemoveOverrides") + +// Map of partition module name to its partition that may be generated by Soong. +// Note that it is not guaranteed that all modules returned by this function are successfully +// created. +func getAllSoongGeneratedPartitionNames(config android.Config, partitions []string) map[string]string { + ret := map[string]string{} + for _, partition := range partitions { + ret[generatedModuleNameForPartition(config, partition)] = partition + } + return ret +} + +type depCandidateProps struct { + Namespace string + Multilib string + Arch []android.ArchType +} + +// Map of module name to depCandidateProps +type multilibDeps map[string]*depCandidateProps + +// Information necessary to generate the filesystem modules, including details about their +// dependencies +type FsGenState struct { + // List of modules in `PRODUCT_PACKAGES` and `PRODUCT_PACKAGES_DEBUG` + depCandidates []string + // Map of names of partition to the information of modules to be added as deps + fsDeps map[string]*multilibDeps + // List of name of partitions to be generated by the filesystem_creator module + soongGeneratedPartitions []string + // Mutex to protect the fsDeps + fsDepsMutex sync.Mutex + // Map of _all_ soong module names to their corresponding installation properties + moduleToInstallationProps map[string]installationProperties +} + +type installationProperties struct { + Required []string + Overrides []string +} + +func defaultDepCandidateProps(config android.Config) *depCandidateProps { + return &depCandidateProps{ + Namespace: ".", + Arch: []android.ArchType{config.BuildArch}, + } +} + +func generatedPartitions(ctx android.LoadHookContext) []string { + 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.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BuildingSystemDlkmImage { + generatedPartitions = append(generatedPartitions, "system_dlkm") + } + return generatedPartitions +} + +func createFsGenState(ctx android.LoadHookContext, generatedPrebuiltEtcModuleNames []string) *FsGenState { + return ctx.Config().Once(fsGenStateOnceKey, func() interface{} { + partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse + candidates := android.FirstUniqueStrings(android.Concat(partitionVars.ProductPackages, partitionVars.ProductPackagesDebug)) + candidates = android.Concat(candidates, generatedPrebuiltEtcModuleNames) + + return &FsGenState{ + depCandidates: candidates, + fsDeps: map[string]*multilibDeps{ + // These additional deps are added according to the cuttlefish system image bp. + "system": { + "com.android.apex.cts.shim.v1_prebuilt": defaultDepCandidateProps(ctx.Config()), + "dex_bootjars": defaultDepCandidateProps(ctx.Config()), + "framework_compatibility_matrix.device.xml": defaultDepCandidateProps(ctx.Config()), + "init.environ.rc-soong": defaultDepCandidateProps(ctx.Config()), + "libclang_rt.asan": defaultDepCandidateProps(ctx.Config()), + "libcompiler_rt": defaultDepCandidateProps(ctx.Config()), + "libdmabufheap": defaultDepCandidateProps(ctx.Config()), + "libgsi": defaultDepCandidateProps(ctx.Config()), + "llndk.libraries.txt": defaultDepCandidateProps(ctx.Config()), + "logpersist.start": defaultDepCandidateProps(ctx.Config()), + "update_engine_sideload": defaultDepCandidateProps(ctx.Config()), + }, + "vendor": { + "fs_config_files_vendor": defaultDepCandidateProps(ctx.Config()), + "fs_config_dirs_vendor": defaultDepCandidateProps(ctx.Config()), + generatedModuleName(ctx.Config(), "vendor-build.prop"): defaultDepCandidateProps(ctx.Config()), + }, + "odm": { + // fs_config_* files are automatically installed for all products with odm partitions. + // https://cs.android.com/android/_/android/platform/build/+/e4849e87ab660b59a6501b3928693db065ee873b:tools/fs_config/Android.mk;l=34;drc=8d6481b92c4b4e9b9f31a61545b6862090fcc14b;bpv=1;bpt=0 + "fs_config_files_odm": defaultDepCandidateProps(ctx.Config()), + "fs_config_dirs_odm": defaultDepCandidateProps(ctx.Config()), + }, + "product": {}, + "system_ext": { + // VNDK apexes are automatically included. + // This hardcoded list will need to be updated if `PRODUCT_EXTRA_VNDK_VERSIONS` is updated. + // https://cs.android.com/android/_/android/platform/build/+/adba533072b00c53ac0f198c550a3cbd7a00e4cd:core/main.mk;l=984;bpv=1;bpt=0;drc=174db7b179592cf07cbfd2adb0119486fda911e7 + "com.android.vndk.v30": defaultDepCandidateProps(ctx.Config()), + "com.android.vndk.v31": defaultDepCandidateProps(ctx.Config()), + "com.android.vndk.v32": defaultDepCandidateProps(ctx.Config()), + "com.android.vndk.v33": defaultDepCandidateProps(ctx.Config()), + "com.android.vndk.v34": defaultDepCandidateProps(ctx.Config()), + }, + "system_dlkm": {}, + }, + soongGeneratedPartitions: generatedPartitions(ctx), + fsDepsMutex: sync.Mutex{}, + moduleToInstallationProps: map[string]installationProperties{}, + } + }).(*FsGenState) +} + +func checkDepModuleInMultipleNamespaces(mctx android.BottomUpMutatorContext, foundDeps multilibDeps, module string, partitionName string) { + otherNamespace := mctx.Namespace().Path + if val, found := foundDeps[module]; found && otherNamespace != "." && !android.InList(val.Namespace, []string{".", otherNamespace}) { + mctx.ModuleErrorf("found in multiple namespaces(%s and %s) when including in %s partition", val.Namespace, otherNamespace, partitionName) + } +} + +func appendDepIfAppropriate(mctx android.BottomUpMutatorContext, deps *multilibDeps, installPartition string) { + moduleName := mctx.ModuleName() + checkDepModuleInMultipleNamespaces(mctx, *deps, moduleName, installPartition) + if _, ok := (*deps)[moduleName]; ok { + // Prefer the namespace-specific module over the platform module + if mctx.Namespace().Path != "." { + (*deps)[moduleName].Namespace = mctx.Namespace().Path + } + (*deps)[moduleName].Arch = append((*deps)[moduleName].Arch, mctx.Module().Target().Arch.ArchType) + } else { + multilib, _ := mctx.Module().DecodeMultilib(mctx) + (*deps)[moduleName] = &depCandidateProps{ + Namespace: mctx.Namespace().Path, + Multilib: multilib, + Arch: []android.ArchType{mctx.Module().Target().Arch.ArchType}, + } + } +} + +func collectDepsMutator(mctx android.BottomUpMutatorContext) { + fsGenState := mctx.Config().Get(fsGenStateOnceKey).(*FsGenState) + + m := mctx.Module() + if m.Target().Os.Class == android.Device && slices.Contains(fsGenState.depCandidates, mctx.ModuleName()) { + installPartition := m.PartitionTag(mctx.DeviceConfig()) + fsGenState.fsDepsMutex.Lock() + // Only add the module as dependency when: + // - its enabled + // - its namespace is included in PRODUCT_SOONG_NAMESPACES + if m.Enabled(mctx) && m.ExportedToMake() { + appendDepIfAppropriate(mctx, fsGenState.fsDeps[installPartition], installPartition) + } + fsGenState.fsDepsMutex.Unlock() + } + // store the map of module to (required,overrides) even if the module is not in PRODUCT_PACKAGES. + // the module might be installed transitively. + if m.Target().Os.Class == android.Device && m.Enabled(mctx) && m.ExportedToMake() { + fsGenState.fsDepsMutex.Lock() + fsGenState.moduleToInstallationProps[m.Name()] = installationProperties{ + Required: m.RequiredModuleNames(mctx), + Overrides: m.Overrides(), + } + fsGenState.fsDepsMutex.Unlock() + } +} + +type depsStruct struct { + Deps []string +} + +type multilibDepsStruct struct { + Common depsStruct + Lib32 depsStruct + Lib64 depsStruct + Both depsStruct + Prefer32 depsStruct +} + +type packagingPropsStruct struct { + High_priority_deps []string + Deps []string + Multilib multilibDepsStruct +} + +func fullyQualifiedModuleName(moduleName, namespace string) string { + if namespace == "." { + return moduleName + } + return fmt.Sprintf("//%s:%s", namespace, moduleName) +} + +func getBitness(archTypes []android.ArchType) (ret []string) { + for _, archType := range archTypes { + if archType.Multilib == "" { + ret = append(ret, android.COMMON_VARIANT) + } else { + ret = append(ret, archType.Bitness()) + } + } + return ret +} + +func setDepsMutator(mctx android.BottomUpMutatorContext) { + removeOverriddenDeps(mctx) + fsGenState := mctx.Config().Get(fsGenStateOnceKey).(*FsGenState) + fsDeps := fsGenState.fsDeps + soongGeneratedPartitionMap := getAllSoongGeneratedPartitionNames(mctx.Config(), fsGenState.soongGeneratedPartitions) + m := mctx.Module() + if partition, ok := soongGeneratedPartitionMap[m.Name()]; ok { + depsStruct := generateDepStruct(*fsDeps[partition]) + if err := proptools.AppendMatchingProperties(m.GetProperties(), depsStruct, nil); err != nil { + mctx.ModuleErrorf(err.Error()) + } + } +} + +// removeOverriddenDeps collects PRODUCT_PACKAGES and (transitive) required deps. +// it then removes any modules which appear in `overrides` of the above list. +func removeOverriddenDeps(mctx android.BottomUpMutatorContext) { + mctx.Config().Once(fsGenRemoveOverridesOnceKey, func() interface{} { + fsGenState := mctx.Config().Get(fsGenStateOnceKey).(*FsGenState) + fsDeps := fsGenState.fsDeps + overridden := map[string]bool{} + allDeps := []string{} + + // Step 1: Initialization: Append PRODUCT_PACKAGES to the queue + for _, fsDep := range fsDeps { + for depName, _ := range *fsDep { + allDeps = append(allDeps, depName) + } + } + + // Step 2: Process the queue, and add required modules to the queue. + i := 0 + for { + if i == len(allDeps) { + break + } + depName := allDeps[i] + for _, overrides := range fsGenState.moduleToInstallationProps[depName].Overrides { + overridden[overrides] = true + } + // add required dep to the queue. + allDeps = append(allDeps, fsGenState.moduleToInstallationProps[depName].Required...) + i += 1 + } + + // Step 3: Delete all the overridden modules. + for overridden, _ := range overridden { + for partition, _ := range fsDeps { + delete(*fsDeps[partition], overridden) + } + } + return nil + }) +} + +var HighPriorityDeps = []string{} + +func generateDepStruct(deps map[string]*depCandidateProps) *packagingPropsStruct { + depsStruct := packagingPropsStruct{} + for depName, depProps := range deps { + bitness := getBitness(depProps.Arch) + fullyQualifiedDepName := fullyQualifiedModuleName(depName, depProps.Namespace) + if android.InList(depName, HighPriorityDeps) { + depsStruct.High_priority_deps = append(depsStruct.High_priority_deps, fullyQualifiedDepName) + } else if android.InList("32", bitness) && android.InList("64", bitness) { + // If both 32 and 64 bit variants are enabled for this module + switch depProps.Multilib { + case string(android.MultilibBoth): + depsStruct.Multilib.Both.Deps = append(depsStruct.Multilib.Both.Deps, fullyQualifiedDepName) + case string(android.MultilibCommon), string(android.MultilibFirst): + depsStruct.Deps = append(depsStruct.Deps, fullyQualifiedDepName) + case "32": + depsStruct.Multilib.Lib32.Deps = append(depsStruct.Multilib.Lib32.Deps, fullyQualifiedDepName) + case "64", "darwin_universal": + depsStruct.Multilib.Lib64.Deps = append(depsStruct.Multilib.Lib64.Deps, fullyQualifiedDepName) + case "prefer32", "first_prefer32": + depsStruct.Multilib.Prefer32.Deps = append(depsStruct.Multilib.Prefer32.Deps, fullyQualifiedDepName) + default: + depsStruct.Multilib.Both.Deps = append(depsStruct.Multilib.Both.Deps, fullyQualifiedDepName) + } + } else if android.InList("64", bitness) { + // If only 64 bit variant is enabled + depsStruct.Multilib.Lib64.Deps = append(depsStruct.Multilib.Lib64.Deps, fullyQualifiedDepName) + } else if android.InList("32", bitness) { + // If only 32 bit variant is enabled + depsStruct.Multilib.Lib32.Deps = append(depsStruct.Multilib.Lib32.Deps, fullyQualifiedDepName) + } else { + // If only common variant is enabled + depsStruct.Multilib.Common.Deps = append(depsStruct.Multilib.Common.Deps, fullyQualifiedDepName) + } + } + depsStruct.Deps = android.SortedUniqueStrings(depsStruct.Deps) + depsStruct.Multilib.Lib32.Deps = android.SortedUniqueStrings(depsStruct.Multilib.Lib32.Deps) + depsStruct.Multilib.Lib64.Deps = android.SortedUniqueStrings(depsStruct.Multilib.Lib64.Deps) + depsStruct.Multilib.Prefer32.Deps = android.SortedUniqueStrings(depsStruct.Multilib.Prefer32.Deps) + depsStruct.Multilib.Both.Deps = android.SortedUniqueStrings(depsStruct.Multilib.Both.Deps) + depsStruct.Multilib.Common.Deps = android.SortedUniqueStrings(depsStruct.Multilib.Common.Deps) + + return &depsStruct +} diff --git a/fsgen/prebuilt_etc_modules_gen.go b/fsgen/prebuilt_etc_modules_gen.go new file mode 100644 index 000000000..1df7ec86d --- /dev/null +++ b/fsgen/prebuilt_etc_modules_gen.go @@ -0,0 +1,298 @@ +// 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 ( + "android/soong/android" + "android/soong/etc" + "fmt" + "path/filepath" + "strings" + + "github.com/google/blueprint/proptools" +) + +type srcBaseFileInstallBaseFileTuple struct { + srcBaseFile string + installBaseFile string +} + +// prebuilt src files grouped by the install partitions. +// Each groups are a mapping of the relative install path to the name of the files +type prebuiltSrcGroupByInstallPartition struct { + system map[string][]srcBaseFileInstallBaseFileTuple + system_ext map[string][]srcBaseFileInstallBaseFileTuple + product map[string][]srcBaseFileInstallBaseFileTuple + vendor map[string][]srcBaseFileInstallBaseFileTuple +} + +func newPrebuiltSrcGroupByInstallPartition() *prebuiltSrcGroupByInstallPartition { + return &prebuiltSrcGroupByInstallPartition{ + system: map[string][]srcBaseFileInstallBaseFileTuple{}, + system_ext: map[string][]srcBaseFileInstallBaseFileTuple{}, + product: map[string][]srcBaseFileInstallBaseFileTuple{}, + vendor: map[string][]srcBaseFileInstallBaseFileTuple{}, + } +} + +func isSubdirectory(parent, child string) bool { + rel, err := filepath.Rel(parent, child) + if err != nil { + return false + } + return !strings.HasPrefix(rel, "..") +} + +func appendIfCorrectInstallPartition(partitionToInstallPathList []partitionToInstallPath, destPath, srcPath string, srcGroup *prebuiltSrcGroupByInstallPartition) { + for _, part := range partitionToInstallPathList { + partition := part.name + installPath := part.installPath + + if isSubdirectory(installPath, destPath) { + relativeInstallPath, _ := filepath.Rel(installPath, destPath) + relativeInstallDir := filepath.Dir(relativeInstallPath) + var srcMap map[string][]srcBaseFileInstallBaseFileTuple + switch partition { + case "system": + srcMap = srcGroup.system + case "system_ext": + srcMap = srcGroup.system_ext + case "product": + srcMap = srcGroup.product + case "vendor": + srcMap = srcGroup.vendor + } + if srcMap != nil { + srcMap[relativeInstallDir] = append(srcMap[relativeInstallDir], srcBaseFileInstallBaseFileTuple{ + srcBaseFile: filepath.Base(srcPath), + installBaseFile: filepath.Base(destPath), + }) + } + return + } + } +} + +func uniqueExistingProductCopyFileMap(ctx android.LoadHookContext) map[string]string { + seen := make(map[string]bool) + filtered := make(map[string]string) + + for src, dest := range ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.ProductCopyFiles { + if _, ok := seen[dest]; !ok { + if optionalPath := android.ExistentPathForSource(ctx, src); optionalPath.Valid() { + seen[dest] = true + filtered[src] = dest + } + } + } + + return filtered +} + +type partitionToInstallPath struct { + name string + installPath string +} + +func processProductCopyFiles(ctx android.LoadHookContext) map[string]*prebuiltSrcGroupByInstallPartition { + // Filter out duplicate dest entries and non existing src entries + productCopyFileMap := uniqueExistingProductCopyFileMap(ctx) + + // System is intentionally added at the last to consider the scenarios where + // non-system partitions are installed as part of the system partition + partitionToInstallPathList := []partitionToInstallPath{ + {name: "vendor", installPath: ctx.DeviceConfig().VendorPath()}, + {name: "product", installPath: ctx.DeviceConfig().ProductPath()}, + {name: "system_ext", installPath: ctx.DeviceConfig().SystemExtPath()}, + {name: "system", installPath: "system"}, + } + + groupedSources := map[string]*prebuiltSrcGroupByInstallPartition{} + for _, src := range android.SortedKeys(productCopyFileMap) { + dest := productCopyFileMap[src] + srcFileDir := filepath.Dir(src) + if _, ok := groupedSources[srcFileDir]; !ok { + groupedSources[srcFileDir] = newPrebuiltSrcGroupByInstallPartition() + } + appendIfCorrectInstallPartition(partitionToInstallPathList, dest, filepath.Base(src), groupedSources[srcFileDir]) + } + + return groupedSources +} + +type prebuiltModuleProperties struct { + Name *string + + Soc_specific *bool + Product_specific *bool + System_ext_specific *bool + + Srcs []string + Dsts []string + + No_full_install *bool + + NamespaceExportedToMake bool + + Visibility []string +} + +// Split relative_install_path to a separate struct, because it is not supported for every +// modules listed in [etcInstallPathToFactoryMap] +type prebuiltSubdirProperties struct { + // If the base file name of the src and dst all match, dsts property does not need to be + // set, and only relative_install_path can be set. + Relative_install_path *string +} + +var ( + etcInstallPathToFactoryList = map[string]android.ModuleFactory{ + "": etc.PrebuiltRootFactory, + "avb": etc.PrebuiltAvbFactory, + "bin": etc.PrebuiltBinaryFactory, + "bt_firmware": etc.PrebuiltBtFirmwareFactory, + "cacerts": etc.PrebuiltEtcCaCertsFactory, + "dsp": etc.PrebuiltDSPFactory, + "etc": etc.PrebuiltEtcFactory, + "etc/dsp": etc.PrebuiltDSPFactory, + "etc/firmware": etc.PrebuiltFirmwareFactory, + "firmware": etc.PrebuiltFirmwareFactory, + "fonts": etc.PrebuiltFontFactory, + "framework": etc.PrebuiltFrameworkFactory, + "lib": etc.PrebuiltRenderScriptBitcodeFactory, + "lib64": etc.PrebuiltRenderScriptBitcodeFactory, + "lib/rfsa": etc.PrebuiltRFSAFactory, + "media": etc.PrebuiltMediaFactory, + "odm": etc.PrebuiltOdmFactory, + "overlay": etc.PrebuiltOverlayFactory, + "priv-app": etc.PrebuiltPrivAppFactory, + "res": etc.PrebuiltResFactory, + "rfs": etc.PrebuiltRfsFactory, + "tts": etc.PrebuiltVoicepackFactory, + "usr/share": etc.PrebuiltUserShareFactory, + "usr/hyphen-data": etc.PrebuiltUserHyphenDataFactory, + "usr/keylayout": etc.PrebuiltUserKeyLayoutFactory, + "usr/keychars": etc.PrebuiltUserKeyCharsFactory, + "usr/srec": etc.PrebuiltUserSrecFactory, + "usr/idc": etc.PrebuiltUserIdcFactory, + "vendor_dlkm": etc.PrebuiltVendorDlkmFactory, + "wallpaper": etc.PrebuiltWallpaperFactory, + "wlc_upt": etc.PrebuiltWlcUptFactory, + } +) + +func createPrebuiltEtcModule(ctx android.LoadHookContext, partition, srcDir, destDir string, destFiles []srcBaseFileInstallBaseFileTuple) string { + moduleProps := &prebuiltModuleProperties{} + propsList := []interface{}{moduleProps} + + // generated module name follows the pattern: + // <install partition>-<src file path>-<relative install path from partition root>-<install file extension> + // Note that all path separators are replaced with "_" in the name + moduleName := partition + if !android.InList(srcDir, []string{"", "."}) { + moduleName += fmt.Sprintf("-%s", strings.ReplaceAll(srcDir, string(filepath.Separator), "_")) + } + if !android.InList(destDir, []string{"", "."}) { + moduleName += fmt.Sprintf("-%s", strings.ReplaceAll(destDir, string(filepath.Separator), "_")) + } + if len(destFiles) > 0 { + if ext := filepath.Ext(destFiles[0].srcBaseFile); ext != "" { + moduleName += fmt.Sprintf("-%s", strings.TrimPrefix(ext, ".")) + } + } + moduleProps.Name = proptools.StringPtr(moduleName) + + allCopyFileNamesUnchanged := true + var srcBaseFiles, installBaseFiles []string + for _, tuple := range destFiles { + if tuple.srcBaseFile != tuple.installBaseFile { + allCopyFileNamesUnchanged = false + } + srcBaseFiles = append(srcBaseFiles, tuple.srcBaseFile) + installBaseFiles = append(installBaseFiles, tuple.installBaseFile) + } + + // Find out the most appropriate module type to generate + var etcInstallPathKey string + for _, etcInstallPath := range android.SortedKeys(etcInstallPathToFactoryList) { + // Do not break when found but iterate until the end to find a module with more + // specific install path + if strings.HasPrefix(destDir, etcInstallPath) { + etcInstallPathKey = etcInstallPath + } + } + destDir, _ = filepath.Rel(etcInstallPathKey, destDir) + + // Set partition specific properties + switch partition { + case "system_ext": + moduleProps.System_ext_specific = proptools.BoolPtr(true) + case "product": + moduleProps.Product_specific = proptools.BoolPtr(true) + case "vendor": + moduleProps.Soc_specific = proptools.BoolPtr(true) + } + + // Set appropriate srcs, dsts, and releative_install_path based on + // the source and install file names + if allCopyFileNamesUnchanged { + moduleProps.Srcs = srcBaseFiles + + // Specify relative_install_path if it is not installed in the root directory of the + // partition + if !android.InList(destDir, []string{"", "."}) { + propsList = append(propsList, &prebuiltSubdirProperties{ + Relative_install_path: proptools.StringPtr(destDir), + }) + } + } else { + moduleProps.Srcs = srcBaseFiles + dsts := []string{} + for _, installBaseFile := range installBaseFiles { + dsts = append(dsts, filepath.Join(destDir, installBaseFile)) + } + moduleProps.Dsts = dsts + } + + moduleProps.No_full_install = proptools.BoolPtr(true) + moduleProps.NamespaceExportedToMake = true + moduleProps.Visibility = []string{"//visibility:public"} + + ctx.CreateModuleInDirectory(etcInstallPathToFactoryList[etcInstallPathKey], srcDir, propsList...) + + return moduleName +} + +func createPrebuiltEtcModulesForPartition(ctx android.LoadHookContext, partition, srcDir string, destDirFilesMap map[string][]srcBaseFileInstallBaseFileTuple) (ret []string) { + for _, destDir := range android.SortedKeys(destDirFilesMap) { + ret = append(ret, createPrebuiltEtcModule(ctx, partition, srcDir, destDir, destDirFilesMap[destDir])) + } + return ret +} + +// Creates prebuilt_* modules based on the install paths and returns the list of generated +// module names +func createPrebuiltEtcModules(ctx android.LoadHookContext) (ret []string) { + groupedSources := processProductCopyFiles(ctx) + for _, srcDir := range android.SortedKeys(groupedSources) { + groupedSource := groupedSources[srcDir] + ret = append(ret, createPrebuiltEtcModulesForPartition(ctx, "system", srcDir, groupedSource.system)...) + ret = append(ret, createPrebuiltEtcModulesForPartition(ctx, "system_ext", srcDir, groupedSource.system_ext)...) + ret = append(ret, createPrebuiltEtcModulesForPartition(ctx, "product", srcDir, groupedSource.product)...) + ret = append(ret, createPrebuiltEtcModulesForPartition(ctx, "vendor", srcDir, groupedSource.vendor)...) + } + + return ret +} |