Merge "Support generating prebuilt_* modules from 1:n mapping of PRODUCT_COPY_FILES" into main
diff --git a/android/variable.go b/android/variable.go
index 89d90c2..2d43c6d 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -635,7 +635,7 @@
BoardInfoFiles []string `json:",omitempty"`
BootLoaderBoardName string `json:",omitempty"`
- ProductCopyFiles map[string]string `json:",omitempty"`
+ ProductCopyFiles []string `json:",omitempty"`
BuildingSystemDlkmImage bool `json:",omitempty"`
SystemKernelModules []string `json:",omitempty"`
diff --git a/fsgen/fsgen_mutators.go b/fsgen/fsgen_mutators.go
index b6ba6c4..e9fd513 100644
--- a/fsgen/fsgen_mutators.go
+++ b/fsgen/fsgen_mutators.go
@@ -17,6 +17,7 @@
import (
"fmt"
"slices"
+ "strings"
"sync"
"android/soong/android"
@@ -327,12 +328,21 @@
var HighPriorityDeps = []string{}
+func isHighPriorityDep(depName string) bool {
+ for _, highPriorityDeps := range HighPriorityDeps {
+ if strings.HasPrefix(depName, highPriorityDeps) {
+ return true
+ }
+ }
+ return false
+}
+
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) {
+ if isHighPriorityDep(depName) {
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
diff --git a/fsgen/prebuilt_etc_modules_gen.go b/fsgen/prebuilt_etc_modules_gen.go
index 362ac31..cbcd4a1 100644
--- a/fsgen/prebuilt_etc_modules_gen.go
+++ b/fsgen/prebuilt_etc_modules_gen.go
@@ -85,15 +85,25 @@
}
}
-func uniqueExistingProductCopyFileMap(ctx android.LoadHookContext) map[string]string {
+// Create a map of source files to the list of destination files from PRODUCT_COPY_FILES entries.
+// Note that the value of the map is a list of string, given that a single source file can be
+// copied to multiple files.
+// This function also checks the existence of the source files, and validates that there is no
+// multiple source files copying to the same dest file.
+func uniqueExistingProductCopyFileMap(ctx android.LoadHookContext) map[string][]string {
seen := make(map[string]bool)
- filtered := make(map[string]string)
+ filtered := make(map[string][]string)
- for src, dest := range ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.ProductCopyFiles {
+ for _, copyFilePair := range ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.ProductCopyFiles {
+ srcDestList := strings.Split(copyFilePair, ":")
+ if len(srcDestList) < 2 {
+ ctx.ModuleErrorf("PRODUCT_COPY_FILES must follow the format \"src:dest\", got: %s", copyFilePair)
+ }
+ src, dest := srcDestList[0], srcDestList[1]
if _, ok := seen[dest]; !ok {
if optionalPath := android.ExistentPathForSource(ctx, src); optionalPath.Valid() {
seen[dest] = true
- filtered[src] = dest
+ filtered[src] = append(filtered[src], dest)
}
}
}
@@ -121,12 +131,14 @@
groupedSources := map[string]*prebuiltSrcGroupByInstallPartition{}
for _, src := range android.SortedKeys(productCopyFileMap) {
- dest := productCopyFileMap[src]
+ destFiles := productCopyFileMap[src]
srcFileDir := filepath.Dir(src)
if _, ok := groupedSources[srcFileDir]; !ok {
groupedSources[srcFileDir] = newPrebuiltSrcGroupByInstallPartition()
}
- appendIfCorrectInstallPartition(partitionToInstallPathList, dest, filepath.Base(src), groupedSources[srcFileDir])
+ for _, dest := range destFiles {
+ appendIfCorrectInstallPartition(partitionToInstallPathList, dest, filepath.Base(src), groupedSources[srcFileDir])
+ }
}
return groupedSources
@@ -195,12 +207,9 @@
}
)
-func createPrebuiltEtcModule(ctx android.LoadHookContext, partition, srcDir, destDir string, destFiles []srcBaseFileInstallBaseFileTuple) string {
- moduleProps := &prebuiltModuleProperties{}
- propsList := []interface{}{moduleProps}
-
+func generatedPrebuiltEtcModuleName(partition, srcDir, destDir string, count int) string {
// generated module name follows the pattern:
- // <install partition>-<src file path>-<relative install path from partition root>-<install file extension>
+ // <install partition>-<src file path>-<relative install path from partition root>-<number>
// Note that all path separators are replaced with "_" in the name
moduleName := partition
if !android.InList(srcDir, []string{"", "."}) {
@@ -209,33 +218,27 @@
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)
+ moduleName += fmt.Sprintf("-%d", count)
- allCopyFileNamesUnchanged := true
- var srcBaseFiles, installBaseFiles []string
+ return moduleName
+}
+
+func groupDestFilesBySrc(destFiles []srcBaseFileInstallBaseFileTuple) (ret map[string][]srcBaseFileInstallBaseFileTuple, maxLen int) {
+ ret = map[string][]srcBaseFileInstallBaseFileTuple{}
+ maxLen = 0
for _, tuple := range destFiles {
- if tuple.srcBaseFile != tuple.installBaseFile {
- allCopyFileNamesUnchanged = false
+ if _, ok := ret[tuple.srcBaseFile]; !ok {
+ ret[tuple.srcBaseFile] = []srcBaseFileInstallBaseFileTuple{}
}
- srcBaseFiles = append(srcBaseFiles, tuple.srcBaseFile)
- installBaseFiles = append(installBaseFiles, tuple.installBaseFile)
+ ret[tuple.srcBaseFile] = append(ret[tuple.srcBaseFile], tuple)
+ maxLen = max(maxLen, len(ret[tuple.srcBaseFile]))
}
+ return ret, maxLen
+}
- // 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)
+func prebuiltEtcModuleProps(moduleName, partition string) prebuiltModuleProperties {
+ moduleProps := prebuiltModuleProperties{}
+ moduleProps.Name = proptools.StringPtr(moduleName)
// Set partition specific properties
switch partition {
@@ -247,39 +250,81 @@
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 moduleProps
+}
- return moduleName
+func createPrebuiltEtcModulesInDirectory(ctx android.LoadHookContext, partition, srcDir, destDir string, destFiles []srcBaseFileInstallBaseFileTuple) (moduleNames []string) {
+ groupedDestFiles, maxLen := groupDestFilesBySrc(destFiles)
+
+ // 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
+ }
+ }
+ relDestDirFromInstallDirBase, _ := filepath.Rel(etcInstallPathKey, destDir)
+
+ for fileIndex := range maxLen {
+ srcTuple := []srcBaseFileInstallBaseFileTuple{}
+ for _, groupedDestFile := range groupedDestFiles {
+ if len(groupedDestFile) > fileIndex {
+ srcTuple = append(srcTuple, groupedDestFile[fileIndex])
+ }
+ }
+
+ moduleName := generatedPrebuiltEtcModuleName(partition, srcDir, destDir, fileIndex)
+ moduleProps := prebuiltEtcModuleProps(moduleName, partition)
+ modulePropsPtr := &moduleProps
+ propsList := []interface{}{modulePropsPtr}
+
+ allCopyFileNamesUnchanged := true
+ var srcBaseFiles, installBaseFiles []string
+ for _, tuple := range srcTuple {
+ if tuple.srcBaseFile != tuple.installBaseFile {
+ allCopyFileNamesUnchanged = false
+ }
+ srcBaseFiles = append(srcBaseFiles, tuple.srcBaseFile)
+ installBaseFiles = append(installBaseFiles, tuple.installBaseFile)
+ }
+
+ // Set appropriate srcs, dsts, and releative_install_path based on
+ // the source and install file names
+ if allCopyFileNamesUnchanged {
+ modulePropsPtr.Srcs = srcBaseFiles
+
+ // Specify relative_install_path if it is not installed in the root directory of the
+ // partition
+ if !android.InList(relDestDirFromInstallDirBase, []string{"", "."}) {
+ propsList = append(propsList, &prebuiltSubdirProperties{
+ Relative_install_path: proptools.StringPtr(relDestDirFromInstallDirBase),
+ })
+ }
+ } else {
+ modulePropsPtr.Srcs = srcBaseFiles
+ dsts := []string{}
+ for _, installBaseFile := range installBaseFiles {
+ dsts = append(dsts, filepath.Join(relDestDirFromInstallDirBase, installBaseFile))
+ }
+ modulePropsPtr.Dsts = dsts
+ }
+
+ ctx.CreateModuleInDirectory(etcInstallPathToFactoryList[etcInstallPathKey], srcDir, propsList...)
+ moduleNames = append(moduleNames, moduleName)
+ }
+
+ return moduleNames
}
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]))
+ ret = append(ret, createPrebuiltEtcModulesInDirectory(ctx, partition, srcDir, destDir, destDirFilesMap[destDir])...)
}
return ret
}