Add support installing to root of filesystem image
If the partition of a spec is "root", that spec will be installed to
root instead. Normally that spec will be from prebuilt_root module with
install_in_root property.
Bug: 351258461
Test: USE_SOONG_DEFINED_SYSTEM_IMAGE=true m && cvd start
Change-Id: Iaaa9c2fb8a81fe0ba4710c641e1b65c5b71ad4a4
diff --git a/android/packaging.go b/android/packaging.go
index ae412e1..c247ed2 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -17,6 +17,7 @@
import (
"fmt"
"path/filepath"
+ "sort"
"strings"
"github.com/google/blueprint"
@@ -377,31 +378,59 @@
// CopySpecsToDir is a helper that will add commands to the rule builder to copy the PackagingSpec
// entries into the specified directory.
func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, specs map[string]PackagingSpec, dir WritablePath) (entries []string) {
- if len(specs) == 0 {
+ dirsToSpecs := make(map[WritablePath]map[string]PackagingSpec)
+ dirsToSpecs[dir] = specs
+ return p.CopySpecsToDirs(ctx, builder, dirsToSpecs)
+}
+
+// CopySpecsToDirs is a helper that will add commands to the rule builder to copy the PackagingSpec
+// entries into corresponding directories.
+func (p *PackagingBase) CopySpecsToDirs(ctx ModuleContext, builder *RuleBuilder, dirsToSpecs map[WritablePath]map[string]PackagingSpec) (entries []string) {
+ empty := true
+ for _, specs := range dirsToSpecs {
+ if len(specs) > 0 {
+ empty = false
+ break
+ }
+ }
+ if empty {
return entries
}
+
seenDir := make(map[string]bool)
preparerPath := PathForModuleOut(ctx, "preparer.sh")
cmd := builder.Command().Tool(preparerPath)
var sb strings.Builder
sb.WriteString("set -e\n")
- for _, k := range SortedKeys(specs) {
- ps := specs[k]
- destPath := filepath.Join(dir.String(), ps.relPathInPackage)
- destDir := filepath.Dir(destPath)
- entries = append(entries, ps.relPathInPackage)
- if _, ok := seenDir[destDir]; !ok {
- seenDir[destDir] = true
- sb.WriteString(fmt.Sprintf("mkdir -p %s\n", destDir))
- }
- if ps.symlinkTarget == "" {
- cmd.Implicit(ps.srcPath)
- sb.WriteString(fmt.Sprintf("cp %s %s\n", ps.srcPath, destPath))
- } else {
- sb.WriteString(fmt.Sprintf("ln -sf %s %s\n", ps.symlinkTarget, destPath))
- }
- if ps.executable {
- sb.WriteString(fmt.Sprintf("chmod a+x %s\n", destPath))
+
+ dirs := make([]WritablePath, 0, len(dirsToSpecs))
+ for dir, _ := range dirsToSpecs {
+ dirs = append(dirs, dir)
+ }
+ sort.Slice(dirs, func(i, j int) bool {
+ return dirs[i].String() < dirs[j].String()
+ })
+
+ for _, dir := range dirs {
+ specs := dirsToSpecs[dir]
+ for _, k := range SortedKeys(specs) {
+ ps := specs[k]
+ destPath := filepath.Join(dir.String(), ps.relPathInPackage)
+ destDir := filepath.Dir(destPath)
+ entries = append(entries, ps.relPathInPackage)
+ if _, ok := seenDir[destDir]; !ok {
+ seenDir[destDir] = true
+ sb.WriteString(fmt.Sprintf("mkdir -p %s\n", destDir))
+ }
+ if ps.symlinkTarget == "" {
+ cmd.Implicit(ps.srcPath)
+ sb.WriteString(fmt.Sprintf("cp %s %s\n", ps.srcPath, destPath))
+ } else {
+ sb.WriteString(fmt.Sprintf("ln -sf %s %s\n", ps.symlinkTarget, destPath))
+ }
+ if ps.executable {
+ sb.WriteString(fmt.Sprintf("chmod a+x %s\n", destPath))
+ }
}
}
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 5add954..5c7ef43 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -312,6 +312,25 @@
}
}
+func (f *filesystem) copyPackagingSpecs(ctx android.ModuleContext, builder *android.RuleBuilder, specs map[string]android.PackagingSpec, rootDir, rebasedDir android.WritablePath) []string {
+ rootDirSpecs := make(map[string]android.PackagingSpec)
+ rebasedDirSpecs := make(map[string]android.PackagingSpec)
+
+ for rel, spec := range specs {
+ if spec.Partition() == "root" {
+ rootDirSpecs[rel] = spec
+ } else {
+ rebasedDirSpecs[rel] = spec
+ }
+ }
+
+ dirsToSpecs := make(map[android.WritablePath]map[string]android.PackagingSpec)
+ dirsToSpecs[rootDir] = rootDirSpecs
+ dirsToSpecs[rebasedDir] = rebasedDirSpecs
+
+ return f.CopySpecsToDirs(ctx, builder, dirsToSpecs)
+}
+
func (f *filesystem) buildImageUsingBuildImage(ctx android.ModuleContext) android.OutputPath {
rootDir := android.PathForModuleOut(ctx, "root").OutputPath
rebasedDir := rootDir
@@ -322,7 +341,7 @@
// Wipe the root dir to get rid of leftover files from prior builds
builder.Command().Textf("rm -rf %s && mkdir -p %s", rootDir, rootDir)
specs := f.gatherFilteredPackagingSpecs(ctx)
- f.entries = f.CopySpecsToDir(ctx, builder, specs, rebasedDir)
+ f.entries = f.copyPackagingSpecs(ctx, builder, specs, rootDir, rebasedDir)
f.buildNonDepsFiles(ctx, builder, rootDir)
f.addMakeBuiltFiles(ctx, builder, rootDir)
@@ -465,7 +484,7 @@
// Wipe the root dir to get rid of leftover files from prior builds
builder.Command().Textf("rm -rf %s && mkdir -p %s", rootDir, rootDir)
specs := f.gatherFilteredPackagingSpecs(ctx)
- f.entries = f.CopySpecsToDir(ctx, builder, specs, rebasedDir)
+ f.entries = f.copyPackagingSpecs(ctx, builder, specs, rootDir, rebasedDir)
f.buildNonDepsFiles(ctx, builder, rootDir)
f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir)
diff --git a/filesystem/system_image.go b/filesystem/system_image.go
index 15cacfb..69d922d 100644
--- a/filesystem/system_image.go
+++ b/filesystem/system_image.go
@@ -94,9 +94,10 @@
return output
}
-// Filter the result of GatherPackagingSpecs to discard items targeting outside "system" partition.
-// Note that "apex" module installs its contents to "apex"(fake partition) as well
+// Filter the result of GatherPackagingSpecs to discard items targeting outside "system" / "root"
+// partition. Note that "apex" module installs its contents to "apex"(fake partition) as well
// for symbol lookup by imitating "activated" paths.
func (s *systemImage) filterPackagingSpec(ps android.PackagingSpec) bool {
- return s.filesystem.filterInstallablePackagingSpec(ps) && ps.Partition() == "system"
+ return s.filesystem.filterInstallablePackagingSpec(ps) &&
+ (ps.Partition() == "system" || ps.Partition() == "root")
}