diff options
Diffstat (limited to 'filesystem/filesystem.go')
-rw-r--r-- | filesystem/filesystem.go | 222 |
1 files changed, 174 insertions, 48 deletions
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index 0ce31b293..f84993de7 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -36,6 +36,8 @@ import ( func init() { registerBuildComponents(android.InitRegistrationContext) registerMutators(android.InitRegistrationContext) + pctx.HostBinToolVariable("fileslist", "fileslist") + pctx.HostBinToolVariable("fs_config", "fs_config") } func registerBuildComponents(ctx android.RegistrationContext) { @@ -54,11 +56,28 @@ func registerMutators(ctx android.RegistrationContext) { }) } -// Remember to add referenced files to implicits! -var textFileProcessorRule = pctx.AndroidStaticRule("text_file_processing", blueprint.RuleParams{ - Command: "build/soong/scripts/text_file_processor.py $in $out", - CommandDeps: []string{"build/soong/scripts/text_file_processor.py"}, -}) +var ( + // Remember to add referenced files to implicits! + textFileProcessorRule = pctx.AndroidStaticRule("text_file_processing", blueprint.RuleParams{ + Command: "build/soong/scripts/text_file_processor.py $in $out", + CommandDeps: []string{"build/soong/scripts/text_file_processor.py"}, + }) + + // Remember to add the output image file as an implicit dependency! + installedFilesJsonRule = pctx.AndroidStaticRule("installed_files_json", blueprint.RuleParams{ + Command: `${fileslist} ${rootDir} > ${out}`, + CommandDeps: []string{"${fileslist}"}, + }, "rootDir") + + installedFilesTxtRule = pctx.AndroidStaticRule("installed_files_txt", blueprint.RuleParams{ + Command: `build/make/tools/fileslist_util.py -c ${in} > ${out}`, + CommandDeps: []string{"build/make/tools/fileslist_util.py"}, + }) + fsConfigRule = pctx.AndroidStaticRule("fs_config_rule", blueprint.RuleParams{ + Command: `(cd ${rootDir}; find . -type d | sed 's,$$,/,'; find . \! -type d) | cut -c 3- | sort | sed 's,^,${prefix},' | ${fs_config} -C -D ${rootDir} -R "${prefix}" > ${out}`, + CommandDeps: []string{"${fs_config}"}, + }, "rootDir", "prefix") +) type filesystem struct { android.ModuleBase @@ -76,6 +95,8 @@ type filesystem struct { entries []string filesystemBuilder filesystemBuilder + + selinuxFc android.Path } type filesystemBuilder interface { @@ -131,7 +152,7 @@ type FilesystemProperties struct { // The index used to prevent rollback of the image. Only used if use_avb is true. Rollback_index *int64 - // Rollback index location of this image. Must be 0, 1, 2, etc. + // Rollback index location of this image. Must be 1, 2, 3, etc. Rollback_index_location *int64 // Name of the partition stored in vbmeta desc. Defaults to the name of this module. @@ -358,6 +379,11 @@ func (fs fsType) IsUnknown() bool { return fs == unknown } +type InstalledFilesStruct struct { + Txt android.Path + Json android.Path +} + type FilesystemInfo struct { // The built filesystem image Output android.Path @@ -391,6 +417,17 @@ type FilesystemInfo struct { SpecsForSystemOther map[string]android.PackagingSpec FullInstallPaths []FullInstallPathInfo + + // Installed files list + InstalledFiles InstalledFilesStruct + + // Path to compress hints file for erofs filesystems + // This will be nil for other fileystems like ext4 + ErofsCompressHints android.Path + + SelinuxFc android.Path + + FilesystemConfig android.Path } // FullInstallPathInfo contains information about the "full install" paths of all the files @@ -498,6 +535,34 @@ func (f *filesystem) ModifyPackagingSpec(ps *android.PackagingSpec) { } } +func buildInstalledFiles(ctx android.ModuleContext, partition string, rootDir android.Path, image android.Path) (txt android.ModuleOutPath, json android.ModuleOutPath) { + fileName := "installed-files" + if len(partition) > 0 { + fileName += fmt.Sprintf("-%s", partition) + } + txt = android.PathForModuleOut(ctx, fmt.Sprintf("%s.txt", fileName)) + json = android.PathForModuleOut(ctx, fmt.Sprintf("%s.json", fileName)) + + ctx.Build(pctx, android.BuildParams{ + Rule: installedFilesJsonRule, + Implicit: image, + Output: json, + Description: "Installed file list json", + Args: map[string]string{ + "rootDir": rootDir.String(), + }, + }) + + ctx.Build(pctx, android.BuildParams{ + Rule: installedFilesTxtRule, + Input: json, + Output: txt, + Description: "Installed file list txt", + }) + + return txt, json +} + var pctx = android.NewPackageContext("android/soong/filesystem") func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -537,14 +602,27 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { f.buildEventLogtagsFile(ctx, builder, rebasedDir, &fullInstallPaths) f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir, &fullInstallPaths) f.filesystemBuilder.BuildLinkerConfigFile(ctx, builder, rebasedDir, &fullInstallPaths) + // Assemeble the staging dir and output a timestamp + builder.Command().Text("touch").Output(f.fileystemStagingDirTimestamp(ctx)) + builder.Build("assemble_filesystem_staging_dir", fmt.Sprintf("Assemble filesystem staging dir %s", f.BaseModuleName())) + // Create a new rule builder for build_image + builder = android.NewRuleBuilder(pctx, ctx) var mapFile android.Path - var outputHermetic android.Path + var outputHermetic android.WritablePath var buildImagePropFile android.Path var buildImagePropFileDeps android.Paths switch f.fsType(ctx) { case ext4Type, erofsType, f2fsType: - f.output, outputHermetic, buildImagePropFile, buildImagePropFileDeps = f.buildImageUsingBuildImage(ctx, builder, rootDir, rebasedDir) + buildImagePropFile, buildImagePropFileDeps = f.buildPropFile(ctx) + output := android.PathForModuleOut(ctx, f.installFileName()) + f.buildImageUsingBuildImage(ctx, builder, buildImageParams{rootDir, buildImagePropFile, buildImagePropFileDeps, output}) + f.output = output + // Create the hermetic img file using a separate rule builder so that it can be built independently + hermeticBuilder := android.NewRuleBuilder(pctx, ctx) + outputHermetic = android.PathForModuleOut(ctx, "for_target_files", f.installFileName()) + propFileHermetic := f.propFileForHermeticImg(ctx, hermeticBuilder, buildImagePropFile) + f.buildImageUsingBuildImage(ctx, hermeticBuilder, buildImageParams{rootDir, propFileHermetic, buildImagePropFileDeps, outputHermetic}) mapFile = f.getMapFile(ctx) case compressedCpioType: f.output = f.buildCpioImage(ctx, builder, rootDir, true) @@ -565,6 +643,17 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { fileListFile := android.PathForModuleOut(ctx, "fileList") android.WriteFileRule(ctx, fileListFile, f.installedFilesList()) + partitionName := f.partitionName() + if partitionName == "system" { + partitionName = "" + } + installedFileTxt, installedFileJson := buildInstalledFiles(ctx, partitionName, rootDir, f.output) + + var erofsCompressHints android.Path + if f.properties.Erofs.Compress_hints != nil { + erofsCompressHints = android.PathForModuleSrc(ctx, *f.properties.Erofs.Compress_hints) + } + fsInfo := FilesystemInfo{ Output: f.output, OutputHermetic: outputHermetic, @@ -577,6 +666,13 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { BuildImagePropFileDeps: buildImagePropFileDeps, SpecsForSystemOther: f.systemOtherFiles(ctx), FullInstallPaths: fullInstallPaths, + InstalledFiles: InstalledFilesStruct{ + Txt: installedFileTxt, + Json: installedFileJson, + }, + ErofsCompressHints: erofsCompressHints, + SelinuxFc: f.selinuxFc, + FilesystemConfig: f.generateFilesystemConfig(ctx, rootDir, rebasedDir), } android.SetProvider(ctx, FilesystemProvider, fsInfo) @@ -590,6 +686,34 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { f.setVbmetaPartitionProvider(ctx) } +func (f *filesystem) fileystemStagingDirTimestamp(ctx android.ModuleContext) android.WritablePath { + return android.PathForModuleOut(ctx, "staging_dir.timestamp") +} + +func (f *filesystem) generateFilesystemConfig(ctx android.ModuleContext, rootDir android.Path, rebasedDir android.Path) android.Path { + rootDirString := rootDir.String() + prefix := f.partitionName() + "/" + if f.partitionName() == "system" { + rootDirString = rebasedDir.String() + } + if f.partitionName() == "ramdisk" || f.partitionName() == "recovery" { + // Hardcoded to match make behavior. + // https://cs.android.com/android/_/android/platform/build/+/2a0ef42a432d4da00201e8eb7697dcaa68fd2389:core/Makefile;l=6957-6962;drc=9ea8ad9232cef4d0a24d70133b1b9d2ce2defe5f;bpv=1;bpt=0 + prefix = "" + } + out := android.PathForModuleOut(ctx, "filesystem_config.txt") + ctx.Build(pctx, android.BuildParams{ + Rule: fsConfigRule, + Input: f.fileystemStagingDirTimestamp(ctx), // assemble the staging directory + Output: out, + Args: map[string]string{ + "rootDir": rootDirString, + "prefix": prefix, + }, + }) + return out +} + func (f *filesystem) setVbmetaPartitionProvider(ctx android.ModuleContext) { var extractedPublicKey android.ModuleOutPath if f.properties.Avb_private_key != nil { @@ -776,28 +900,35 @@ func (f *filesystem) copyPackagingSpecs(ctx android.ModuleContext, builder *andr dirsToSpecs[rootDir] = rootDirSpecs dirsToSpecs[rebasedDir] = rebasedDirSpecs - return f.CopySpecsToDirs(ctx, builder, dirsToSpecs) + // Preserve timestamps for adb sync, so that this staging dir file matches the timestamp in the + // out/target/product staging directory. + return f.CopySpecsToDirs(ctx, builder, dirsToSpecs, true) } func (f *filesystem) rootDirString() string { return f.partitionName() } +type buildImageParams struct { + // inputs + rootDir android.OutputPath + propFile android.Path + toolDeps android.Paths + // outputs + output android.WritablePath +} + func (f *filesystem) buildImageUsingBuildImage( ctx android.ModuleContext, builder *android.RuleBuilder, - rootDir android.OutputPath, - rebasedDir android.OutputPath, -) (android.Path, android.Path, android.Path, android.Paths) { + params buildImageParams) { // run host_init_verifier // Ideally we should have a concept of pluggable linters that verify the generated image. // While such concept is not implement this will do. // TODO(b/263574231): substitute with pluggable linter. builder.Command(). BuiltTool("host_init_verifier"). - FlagWithArg("--out_system=", rootDir.String()+"/system") - - propFile, toolDeps := f.buildPropFile(ctx) + FlagWithArg("--out_system=", params.rootDir.String()+"/system") // Most of the time, if build_image were to call a host tool, it accepts the path to the // host tool in a field in the prop file. However, it doesn't have that option for fec, which @@ -805,44 +936,32 @@ func (f *filesystem) buildImageUsingBuildImage( fec := ctx.Config().HostToolPath(ctx, "fec") pathToolDirs := []string{filepath.Dir(fec.String())} - output := android.PathForModuleOut(ctx, f.installFileName()) - builder.Command().Text("touch").Output(f.getMapFile(ctx)) builder.Command(). Textf("PATH=%s:$PATH", strings.Join(pathToolDirs, ":")). BuiltTool("build_image"). - Text(rootDir.String()). // input directory - Input(propFile). - Implicits(toolDeps). + Text(params.rootDir.String()). // input directory + Input(params.propFile). + Implicits(params.toolDeps). Implicit(fec). - Output(output). - Text(rootDir.String()) // directory where to find fs_config_files|dirs - - // TODO (b/393203512): Re-enable hermetic img file creation for target_files.zip - // Add an additional cmd to create a hermetic img file. This will contain pinned timestamps e.g. - //propFilePinnedTimestamp := android.PathForModuleOut(ctx, "for_target_files", "prop") - //builder.Command().Textf("cat").Input(propFile).Flag(">").Output(propFilePinnedTimestamp). - // Textf(" && echo use_fixed_timestamp=true >> %s", propFilePinnedTimestamp). - // Textf(" && echo block_list=%s >> %s", f.getMapFile(ctx).String(), propFilePinnedTimestamp) // mapfile will be an implicit output - - //outputHermetic := android.PathForModuleOut(ctx, "for_target_files", f.installFileName()) - //builder.Command(). - // Textf("PATH=%s:$PATH", strings.Join(pathToolDirs, ":")). - // BuiltTool("build_image"). - // Text(rootDir.String()). // input directory - // Flag(propFilePinnedTimestamp.String()). - // Implicits(toolDeps). - // Implicit(fec). - // Output(outputHermetic). - // Text(rootDir.String()) // directory where to find fs_config_files|dirs + Implicit(f.fileystemStagingDirTimestamp(ctx)). // assemble the staging directory + Output(params.output). + Text(params.rootDir.String()) // directory where to find fs_config_files|dirs if f.properties.Partition_size != nil { - assertMaxImageSize(builder, output, *f.properties.Partition_size, false) + assertMaxImageSize(builder, params.output, *f.properties.Partition_size, false) } // rootDir is not deleted. Might be useful for quick inspection. - builder.Build("build_filesystem_image", fmt.Sprintf("Creating filesystem %s", f.BaseModuleName())) + builder.Build("build_"+params.output.String(), fmt.Sprintf("Creating filesystem %s", f.BaseModuleName())) +} - return output, nil, propFile, toolDeps +func (f *filesystem) propFileForHermeticImg(ctx android.ModuleContext, builder *android.RuleBuilder, inputPropFile android.Path) android.Path { + propFilePinnedTimestamp := android.PathForModuleOut(ctx, "for_target_files", "prop") + builder.Command().Textf("cat").Input(inputPropFile).Flag(">").Output(propFilePinnedTimestamp). + Textf(" && echo use_fixed_timestamp=true >> %s", propFilePinnedTimestamp). + Textf(" && echo block_list=%s >> %s", f.getMapFile(ctx).String(), propFilePinnedTimestamp) // mapfile will be an implicit output + builder.Command().Text("touch").Output(f.getMapFile(ctx)) + return propFilePinnedTimestamp } func (f *filesystem) buildFileContexts(ctx android.ModuleContext) android.Path { @@ -926,12 +1045,12 @@ func (f *filesystem) buildPropFile(ctx android.ModuleContext) (android.Path, and if f.properties.File_contexts != nil && f.properties.Precompiled_file_contexts != nil { ctx.ModuleErrorf("file_contexts and precompiled_file_contexts cannot both be set") } else if f.properties.File_contexts != nil { - addPath("selinux_fc", f.buildFileContexts(ctx)) + f.selinuxFc = f.buildFileContexts(ctx) } else if f.properties.Precompiled_file_contexts != nil { - src := android.PathForModuleSrc(ctx, *f.properties.Precompiled_file_contexts) - if src != nil { - addPath("selinux_fc", src) - } + f.selinuxFc = android.PathForModuleSrc(ctx, *f.properties.Precompiled_file_contexts) + } + if f.selinuxFc != nil { + addPath("selinux_fc", f.selinuxFc) } if timestamp := proptools.String(f.properties.Fake_timestamp); timestamp != "" { addStr("timestamp", timestamp) @@ -1053,6 +1172,7 @@ func (f *filesystem) buildCpioImage( output := android.PathForModuleOut(ctx, f.installFileName()) cmd := builder.Command(). BuiltTool("mkbootfs"). + Implicit(f.fileystemStagingDirTimestamp(ctx)). Text(rootDir.String()) // input directory for i := range len(rootDirs) { @@ -1373,3 +1493,9 @@ func addAutogeneratedRroDeps(ctx android.BottomUpMutatorContext) { return true }) } + +func (f *filesystem) MakeVars(ctx android.MakeVarsModuleContext) { + if f.Name() == ctx.Config().SoongDefinedSystemImage() { + ctx.StrictRaw("SOONG_DEFINED_SYSTEM_IMAGE_PATH", f.output.String()) + } +} |