diff options
Diffstat (limited to 'filesystem/filesystem.go')
| -rw-r--r-- | filesystem/filesystem.go | 174 | 
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 +} |