summaryrefslogtreecommitdiff
path: root/filesystem/filesystem.go
diff options
context:
space:
mode:
Diffstat (limited to 'filesystem/filesystem.go')
-rw-r--r--filesystem/filesystem.go174
1 files changed, 137 insertions, 37 deletions
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 97421c8a3..78e24e296 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -25,6 +25,7 @@ import (
"android/soong/android"
"android/soong/cc"
+ "android/soong/linkerconfig"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -51,12 +52,6 @@ type filesystem struct {
properties FilesystemProperties
- // Function that builds extra files under the root directory and returns the files
- buildExtraFiles func(ctx android.ModuleContext, root android.OutputPath) android.OutputPaths
-
- // Function that filters PackagingSpec in PackagingBase.GatherPackagingSpecs()
- filterPackagingSpec func(spec android.PackagingSpec) bool
-
output android.OutputPath
installDir android.InstallPath
@@ -64,8 +59,18 @@ type filesystem struct {
// Keeps the entries installed from this filesystem
entries []string
+
+ filesystemBuilder filesystemBuilder
+}
+
+type filesystemBuilder interface {
+ BuildLinkerConfigFile(ctx android.ModuleContext, builder *android.RuleBuilder, rebasedDir android.OutputPath)
+ // Function that filters PackagingSpec in PackagingBase.GatherPackagingSpecs()
+ FilterPackagingSpec(spec android.PackagingSpec) bool
}
+var _ filesystemBuilder = (*filesystem)(nil)
+
type SymlinkDefinition struct {
Target *string
Name *string
@@ -146,6 +151,10 @@ type FilesystemProperties struct {
Erofs ErofsProperties
+ F2fs F2fsProperties
+
+ Linker_config LinkerConfigProperties
+
// Determines if the module is auto-generated from Soong or not. If the module is
// auto-generated, its deps are exempted from visibility enforcement.
Is_auto_generated *bool
@@ -163,6 +172,21 @@ type ErofsProperties struct {
Sparse *bool
}
+// Additional properties required to generate f2fs FS partitions.
+type F2fsProperties struct {
+ Sparse *bool
+}
+
+type LinkerConfigProperties struct {
+
+ // Build a linker.config.pb file
+ Gen_linker_config *bool
+
+ // List of files (in .json format) that will be converted to a linker config file (in .pb format).
+ // The linker config file be installed in the filesystem at /etc/linker.config.pb
+ Linker_config_srcs []string `android:"path"`
+}
+
// android_filesystem packages a set of modules and their transitive dependencies into a filesystem
// image. The filesystem images are expected to be mounted in the target device, which means the
// modules in the filesystem image are built for the target device (i.e. Android, not Linux host).
@@ -170,7 +194,7 @@ type ErofsProperties struct {
// partitions like system.img. For example, cc_library modules are placed under ./lib[64] directory.
func FilesystemFactory() android.Module {
module := &filesystem{}
- module.filterPackagingSpec = module.filterInstallablePackagingSpec
+ module.filesystemBuilder = module
initFilesystemModule(module, module)
return module
}
@@ -179,6 +203,7 @@ func initFilesystemModule(module android.DefaultableModule, filesystemModule *fi
module.AddProperties(&filesystemModule.properties)
android.InitPackageModule(filesystemModule)
filesystemModule.PackagingBase.DepsCollectFirstTargetOnly = true
+ filesystemModule.PackagingBase.AllowHighPriorityDeps = true
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
}
@@ -213,6 +238,7 @@ type fsType int
const (
ext4Type fsType = iota
erofsType
+ f2fsType
compressedCpioType
cpioType // uncompressed
unknown
@@ -235,6 +261,8 @@ func GetFsTypeFromString(ctx android.EarlyModuleContext, typeStr string) fsType
return ext4Type
case "erofs":
return erofsType
+ case "f2fs":
+ return f2fsType
case "compressed_cpio":
return compressedCpioType
case "cpio":
@@ -261,13 +289,17 @@ func (f *filesystem) partitionName() string {
return proptools.StringDefault(f.properties.Partition_name, f.Name())
}
-func (f *filesystem) filterInstallablePackagingSpec(ps android.PackagingSpec) bool {
+func (f *filesystem) FilterPackagingSpec(ps android.PackagingSpec) bool {
// Filesystem module respects the installation semantic. A PackagingSpec from a module with
// IsSkipInstall() is skipped.
+ if ps.SkipInstall() {
+ return false
+ }
if proptools.Bool(f.properties.Is_auto_generated) { // TODO (spandandas): Remove this.
- return !ps.SkipInstall() && (ps.Partition() == f.PartitionType())
+ pt := f.PartitionType()
+ return pt == "ramdisk" || ps.Partition() == pt
}
- return !ps.SkipInstall()
+ return true
}
var pctx = android.NewPackageContext("android/soong/filesystem")
@@ -275,7 +307,7 @@ var pctx = android.NewPackageContext("android/soong/filesystem")
func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) {
validatePartitionType(ctx, f)
switch f.fsType(ctx) {
- case ext4Type, erofsType:
+ case ext4Type, erofsType, f2fsType:
f.output = f.buildImageUsingBuildImage(ctx)
case compressedCpioType:
f.output = f.buildCpioImage(ctx, true)
@@ -363,25 +395,6 @@ func (f *filesystem) buildNonDepsFiles(ctx android.ModuleContext, builder *andro
builder.Command().Text("ln -sf").Text(proptools.ShellEscape(target)).Text(dst.String())
f.appendToEntry(ctx, dst)
}
-
- // create extra files if there's any
- if f.buildExtraFiles != nil {
- rootForExtraFiles := android.PathForModuleGen(ctx, "root-extra").OutputPath
- extraFiles := f.buildExtraFiles(ctx, rootForExtraFiles)
- for _, extraFile := range extraFiles {
- rel, err := filepath.Rel(rootForExtraFiles.String(), extraFile.String())
- if err != nil || strings.HasPrefix(rel, "..") {
- ctx.ModuleErrorf("can't make %q relative to %q", extraFile, rootForExtraFiles)
- }
- f.appendToEntry(ctx, rootDir.Join(ctx, rel))
- }
- if len(extraFiles) > 0 {
- builder.Command().BuiltTool("merge_directories").
- Implicits(extraFiles.Paths()).
- Text(rootDir.String()).
- Text(rootForExtraFiles.String())
- }
- }
}
func (f *filesystem) copyPackagingSpecs(ctx android.ModuleContext, builder *android.RuleBuilder, specs map[string]android.PackagingSpec, rootDir, rebasedDir android.WritablePath) []string {
@@ -428,6 +441,7 @@ func (f *filesystem) buildImageUsingBuildImage(ctx android.ModuleContext) androi
f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir)
f.buildEventLogtagsFile(ctx, builder, rebasedDir)
f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir)
+ f.filesystemBuilder.BuildLinkerConfigFile(ctx, builder, rebasedDir)
f.copyFilesToProductOut(ctx, builder, rebasedDir)
// run host_init_verifier
@@ -490,6 +504,8 @@ func (f *filesystem) buildPropFile(ctx android.ModuleContext) (propFile android.
return "ext4"
case erofsType:
return "erofs"
+ case f2fsType:
+ return "f2fs"
}
panic(fmt.Errorf("unsupported fs type %v", t))
}
@@ -539,8 +555,11 @@ func (f *filesystem) buildPropFile(ctx android.ModuleContext) (propFile android.
addStr("uuid", uuid)
addStr("hash_seed", uuid)
}
- // Add erofs properties
- if f.fsType(ctx) == erofsType {
+
+ fst := f.fsType(ctx)
+ switch fst {
+ case erofsType:
+ // Add erofs properties
if compressor := f.properties.Erofs.Compressor; compressor != nil {
addStr("erofs_default_compressor", proptools.String(compressor))
}
@@ -551,17 +570,39 @@ func (f *filesystem) buildPropFile(ctx android.ModuleContext) (propFile android.
// https://source.corp.google.com/h/googleplex-android/platform/build/+/88b1c67239ca545b11580237242774b411f2fed9:core/Makefile;l=2292;bpv=1;bpt=0;drc=ea8f34bc1d6e63656b4ec32f2391e9d54b3ebb6b
addStr("erofs_sparse_flag", "-s")
}
- } else if f.properties.Erofs.Compressor != nil || f.properties.Erofs.Compress_hints != nil || f.properties.Erofs.Sparse != nil {
- // Raise an exception if the propfile contains erofs properties, but the fstype is not erofs
- fs := fsTypeStr(f.fsType(ctx))
- ctx.PropertyErrorf("erofs", "erofs is non-empty, but FS type is %s\n. Please delete erofs properties if this partition should use %s\n", fs, fs)
+ case f2fsType:
+ if proptools.BoolDefault(f.properties.F2fs.Sparse, true) {
+ // https://source.corp.google.com/h/googleplex-android/platform/build/+/88b1c67239ca545b11580237242774b411f2fed9:core/Makefile;l=2294;drc=ea8f34bc1d6e63656b4ec32f2391e9d54b3ebb6b;bpv=1;bpt=0
+ addStr("f2fs_sparse_flag", "-S")
+ }
}
+ f.checkFsTypePropertyError(ctx, fst, fsTypeStr(fst))
propFile = android.PathForModuleOut(ctx, "prop").OutputPath
android.WriteFileRuleVerbatim(ctx, propFile, propFileString.String())
return propFile, deps
}
+// This method checks if there is any property set for the fstype(s) other than
+// the current fstype.
+func (f *filesystem) checkFsTypePropertyError(ctx android.ModuleContext, t fsType, fs string) {
+ raiseError := func(otherFsType, currentFsType string) {
+ errMsg := fmt.Sprintf("%s is non-empty, but FS type is %s\n. Please delete %s properties if this partition should use %s\n", otherFsType, currentFsType, otherFsType, currentFsType)
+ ctx.PropertyErrorf(otherFsType, errMsg)
+ }
+
+ if t != erofsType {
+ if f.properties.Erofs.Compressor != nil || f.properties.Erofs.Compress_hints != nil || f.properties.Erofs.Sparse != nil {
+ raiseError("erofs", fs)
+ }
+ }
+ if t != f2fsType {
+ if f.properties.F2fs.Sparse != nil {
+ raiseError("f2fs", fs)
+ }
+ }
+}
+
func (f *filesystem) buildCpioImage(ctx android.ModuleContext, compressed bool) android.OutputPath {
if proptools.Bool(f.properties.Use_avb) {
ctx.PropertyErrorf("use_avb", "signing compresed cpio image using avbtool is not supported."+
@@ -591,6 +632,7 @@ func (f *filesystem) buildCpioImage(ctx android.ModuleContext, compressed bool)
f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir)
f.buildEventLogtagsFile(ctx, builder, rebasedDir)
f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir)
+ f.filesystemBuilder.BuildLinkerConfigFile(ctx, builder, rebasedDir)
f.copyFilesToProductOut(ctx, builder, rebasedDir)
output := android.PathForModuleOut(ctx, f.installFileName()).OutputPath
@@ -626,6 +668,7 @@ var validPartitions = []string{
"vendor_dlkm",
"odm_dlkm",
"system_dlkm",
+ "ramdisk",
}
func (f *filesystem) addMakeBuiltFiles(ctx android.ModuleContext, builder *android.RuleBuilder, rootDir android.Path) {
@@ -682,6 +725,18 @@ func (f *filesystem) buildEventLogtagsFile(ctx android.ModuleContext, builder *a
f.appendToEntry(ctx, eventLogtagsPath)
}
+func (f *filesystem) BuildLinkerConfigFile(ctx android.ModuleContext, builder *android.RuleBuilder, rebasedDir android.OutputPath) {
+ if !proptools.Bool(f.properties.Linker_config.Gen_linker_config) {
+ return
+ }
+
+ provideModules, _ := f.getLibsForLinkerConfig(ctx)
+ output := rebasedDir.Join(ctx, "etc", "linker.config.pb")
+ linkerconfig.BuildLinkerConfig(ctx, builder, android.PathsForModuleSrc(ctx, f.properties.Linker_config.Linker_config_srcs), provideModules, nil, output)
+
+ f.appendToEntry(ctx, output)
+}
+
type partition interface {
PartitionType() string
}
@@ -737,7 +792,7 @@ func (f *filesystem) SignedOutputPath() android.Path {
// Note that "apex" module installs its contents to "apex"(fake partition) as well
// for symbol lookup by imitating "activated" paths.
func (f *filesystem) gatherFilteredPackagingSpecs(ctx android.ModuleContext) map[string]android.PackagingSpec {
- specs := f.PackagingBase.GatherPackagingSpecsWithFilter(ctx, f.filterPackagingSpec)
+ specs := f.PackagingBase.GatherPackagingSpecsWithFilter(ctx, f.filesystemBuilder.FilterPackagingSpec)
return specs
}
@@ -790,3 +845,48 @@ var _ partition = (*filesystemDefaults)(nil)
func (f *filesystemDefaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
validatePartitionType(ctx, f)
}
+
+// getLibsForLinkerConfig returns
+// 1. A list of libraries installed in this filesystem
+// 2. A list of dep libraries _not_ installed in this filesystem
+//
+// `linkerconfig.BuildLinkerConfig` will convert these two to a linker.config.pb for the filesystem
+// (1) will be added to --provideLibs if they are C libraries with a stable interface (has stubs)
+// (2) will be added to --requireLibs if they are C libraries with a stable interface (has stubs)
+func (f *filesystem) getLibsForLinkerConfig(ctx android.ModuleContext) ([]android.Module, []android.Module) {
+ // we need "Module"s for packaging items
+ modulesInPackageByModule := make(map[android.Module]bool)
+ modulesInPackageByName := make(map[string]bool)
+
+ deps := f.gatherFilteredPackagingSpecs(ctx)
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ for _, ps := range android.OtherModuleProviderOrDefault(
+ ctx, child, android.InstallFilesProvider).PackagingSpecs {
+ if _, ok := deps[ps.RelPathInPackage()]; ok {
+ modulesInPackageByModule[child] = true
+ modulesInPackageByName[child.Name()] = true
+ return true
+ }
+ }
+ return true
+ })
+
+ provideModules := make([]android.Module, 0, len(modulesInPackageByModule))
+ for mod := range modulesInPackageByModule {
+ provideModules = append(provideModules, mod)
+ }
+
+ var requireModules []android.Module
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ _, parentInPackage := modulesInPackageByModule[parent]
+ _, childInPackageName := modulesInPackageByName[child.Name()]
+
+ // When parent is in the package, and child (or its variant) is not, this can be from an interface.
+ if parentInPackage && !childInPackageName {
+ requireModules = append(requireModules, child)
+ }
+ return true
+ })
+
+ return provideModules, requireModules
+}