diff --git a/apex/apex.go b/apex/apex.go index ff2e2d684..ad1d3b11c 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -2294,26 +2294,6 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, return false } -func collectAconfigFiles(ctx android.ModuleContext, apexFiles []apexFile) android.Paths { - var aconfigFiles android.Paths - for _, file := range apexFiles { - if file.module == nil { - continue - } - if dep, ok := android.OtherModuleProvider(ctx, file.module, android.AconfigPropagatingProviderKey); ok { - if len(dep.AconfigFiles) > 0 && dep.AconfigFiles[ctx.ModuleName()] != nil { - aconfigFiles = append(aconfigFiles, dep.AconfigFiles[ctx.ModuleName()]...) - } - } - - validationFlag := ctx.DeviceConfig().AconfigContainerValidation() - if validationFlag == "error" || validationFlag == "warning" { - android.VerifyAconfigBuildMode(ctx, ctx.ModuleName(), file.module, validationFlag == "error") - } - } - return android.FirstUniquePaths(aconfigFiles) -} - func (a *apexBundle) shouldCheckDuplicate(ctx android.ModuleContext) bool { // TODO(b/263308293) remove this if a.properties.IsCoverageVariant { @@ -2395,12 +2375,15 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { // 3) some fields in apexBundle struct are configured a.installDir = android.PathForModuleInstall(ctx, "apex") a.filesInfo = vctx.filesInfo - a.aconfigFiles = collectAconfigFiles(ctx, a.filesInfo) a.setPayloadFsType(ctx) a.setSystemLibLink(ctx) a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx) + //////////////////////////////////////////////////////////////////////////////////////////// + // 3.a) some artifacts are generated from the collected files + a.filesInfo = append(a.filesInfo, a.buildAconfigFiles(ctx)...) + //////////////////////////////////////////////////////////////////////////////////////////// // 4) generate the build rules to create the APEX. This is done in builder.go. a.buildManifest(ctx, vctx.provideNativeLibs, vctx.requireNativeLibs) diff --git a/apex/apex_test.go b/apex/apex_test.go index 83053332a..685cb3743 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -267,6 +267,7 @@ func ensureNotContains(t *testing.T, result string, notExpected string) { } func ensureMatches(t *testing.T, result string, expectedRex string) { + t.Helper() ok, err := regexp.MatchString(expectedRex, result) if err != nil { t.Fatalf("regexp failure trying to match %s against `%s` expression: %s", result, expectedRex, err) @@ -277,6 +278,14 @@ func ensureMatches(t *testing.T, result string, expectedRex string) { } } +func ensureListContainsMatch(t *testing.T, result []string, expectedRex string) { + t.Helper() + p := regexp.MustCompile(expectedRex) + if android.IndexListPred(func(s string) bool { return p.MatchString(s) }, result) == -1 { + t.Errorf("%q is not found in %v", expectedRex, result) + } +} + func ensureListContains(t *testing.T, result []string, expected string) { t.Helper() if !android.InList(expected, result) { @@ -10791,14 +10800,14 @@ func TestAconfigFilesJavaDeps(t *testing.T) { mod := ctx.ModuleForTests("myapex", "android_common_myapex") s := mod.Rule("apexRule").Args["copy_commands"] copyCmds := regexp.MustCompile(" *&& *").Split(s, -1) - if len(copyCmds) != 8 { - t.Fatalf("Expected 5 commands, got %d in:\n%s", len(copyCmds), s) + if len(copyCmds) != 12 { + t.Fatalf("Expected 12 commands, got %d in:\n%s", len(copyCmds), s) } - ensureMatches(t, copyCmds[4], "^cp -f .*/aconfig_flags.pb .*/image.apex/etc$") - ensureMatches(t, copyCmds[5], "^cp -f .*/package.map .*/image.apex/etc$") - ensureMatches(t, copyCmds[6], "^cp -f .*/flag.map .*/image.apex/etc$") - ensureMatches(t, copyCmds[7], "^cp -f .*/flag.val .*/image.apex/etc$") + ensureListContainsMatch(t, copyCmds, "^cp -f .*/aconfig_flags.pb .*/image.apex/etc/aconfig_flags.pb") + ensureListContainsMatch(t, copyCmds, "^cp -f .*/package.map .*/image.apex/etc/package.map") + ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.map .*/image.apex/etc/flag.map") + ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.val .*/image.apex/etc/flag.val") inputs := []string{ "my_aconfig_declarations_foo/intermediate.pb", @@ -10926,14 +10935,14 @@ func TestAconfigFilesJavaAndCcDeps(t *testing.T) { mod := ctx.ModuleForTests("myapex", "android_common_myapex") s := mod.Rule("apexRule").Args["copy_commands"] copyCmds := regexp.MustCompile(" *&& *").Split(s, -1) - if len(copyCmds) != 12 { - t.Fatalf("Expected 12 commands, got %d in:\n%s", len(copyCmds), s) + if len(copyCmds) != 16 { + t.Fatalf("Expected 16 commands, got %d in:\n%s", len(copyCmds), s) } - ensureMatches(t, copyCmds[8], "^cp -f .*/aconfig_flags.pb .*/image.apex/etc$") - ensureMatches(t, copyCmds[9], "^cp -f .*/package.map .*/image.apex/etc$") - ensureMatches(t, copyCmds[10], "^cp -f .*/flag.map .*/image.apex/etc$") - ensureMatches(t, copyCmds[11], "^cp -f .*/flag.val .*/image.apex/etc$") + ensureListContainsMatch(t, copyCmds, "^cp -f .*/aconfig_flags.pb .*/image.apex/etc/aconfig_flags.pb") + ensureListContainsMatch(t, copyCmds, "^cp -f .*/package.map .*/image.apex/etc/package.map") + ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.map .*/image.apex/etc/flag.map") + ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.val .*/image.apex/etc/flag.val") inputs := []string{ "my_aconfig_declarations_foo/intermediate.pb", @@ -11094,14 +11103,14 @@ func TestAconfigFilesRustDeps(t *testing.T) { mod := ctx.ModuleForTests("myapex", "android_common_myapex") s := mod.Rule("apexRule").Args["copy_commands"] copyCmds := regexp.MustCompile(" *&& *").Split(s, -1) - if len(copyCmds) != 32 { - t.Fatalf("Expected 28 commands, got %d in:\n%s", len(copyCmds), s) + if len(copyCmds) != 36 { + t.Fatalf("Expected 36 commands, got %d in:\n%s", len(copyCmds), s) } - ensureMatches(t, copyCmds[28], "^cp -f .*/aconfig_flags.pb .*/image.apex/etc$") - ensureMatches(t, copyCmds[29], "^cp -f .*/package.map .*/image.apex/etc$") - ensureMatches(t, copyCmds[30], "^cp -f .*/flag.map .*/image.apex/etc$") - ensureMatches(t, copyCmds[31], "^cp -f .*/flag.val .*/image.apex/etc$") + ensureListContainsMatch(t, copyCmds, "^cp -f .*/aconfig_flags.pb .*/image.apex/etc/aconfig_flags.pb") + ensureListContainsMatch(t, copyCmds, "^cp -f .*/package.map .*/image.apex/etc/package.map") + ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.map .*/image.apex/etc/flag.map") + ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.val .*/image.apex/etc/flag.val") inputs := []string{ "my_aconfig_declarations_foo/intermediate.pb", diff --git a/apex/builder.go b/apex/builder.go index 0d084834d..505ef8b59 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -262,6 +262,58 @@ var ( }, "tool_path", "unwanted") ) +func (a *apexBundle) buildAconfigFiles(ctx android.ModuleContext) []apexFile { + var aconfigFiles android.Paths + for _, file := range a.filesInfo { + if file.module == nil { + continue + } + if dep, ok := android.OtherModuleProvider(ctx, file.module, android.AconfigPropagatingProviderKey); ok { + if len(dep.AconfigFiles) > 0 && dep.AconfigFiles[ctx.ModuleName()] != nil { + aconfigFiles = append(aconfigFiles, dep.AconfigFiles[ctx.ModuleName()]...) + } + } + + validationFlag := ctx.DeviceConfig().AconfigContainerValidation() + if validationFlag == "error" || validationFlag == "warning" { + android.VerifyAconfigBuildMode(ctx, ctx.ModuleName(), file.module, validationFlag == "error") + } + } + aconfigFiles = android.FirstUniquePaths(aconfigFiles) + + var files []apexFile + if len(aconfigFiles) > 0 { + apexAconfigFile := android.PathForModuleOut(ctx, "aconfig_flags.pb") + ctx.Build(pctx, android.BuildParams{ + Rule: aconfig.AllDeclarationsRule, + Inputs: aconfigFiles, + Output: apexAconfigFile, + Description: "combine_aconfig_declarations", + Args: map[string]string{ + "cache_files": android.JoinPathsWithPrefix(aconfigFiles, "--cache "), + }, + }) + files = append(files, newApexFile(ctx, apexAconfigFile, "aconfig_flags", "etc", etc, nil)) + + for _, info := range createStorageInfo { + outputFile := android.PathForModuleOut(ctx, info.Output_file) + ctx.Build(pctx, android.BuildParams{ + Rule: aconfig.CreateStorageRule, + Inputs: aconfigFiles, + Output: outputFile, + Description: info.Desc, + Args: map[string]string{ + "container": ctx.ModuleName(), + "file_type": info.File_type, + "cache_files": android.JoinPathsWithPrefix(aconfigFiles, "--cache "), + }, + }) + files = append(files, newApexFile(ctx, outputFile, info.File_type, "etc", etc, nil)) + } + } + return files +} + // buildManifest creates buile rules to modify the input apex_manifest.json to add information // gathered by the build system such as provided/required native libraries. Two output files having // different formats are generated. a.manifestJsonOut is JSON format for Q devices, and @@ -644,48 +696,10 @@ func (a *apexBundle) buildApex(ctx android.ModuleContext) { outHostBinDir := ctx.Config().HostToolPath(ctx, "").String() prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin") - defaultReadOnlyFiles := []string{"apex_manifest.json", "apex_manifest.pb"} - aconfigDest := imageDir.Join(ctx, "etc").String() - if len(a.aconfigFiles) > 0 { - apexAconfigFile := android.PathForModuleOut(ctx, "aconfig_flags.pb") - ctx.Build(pctx, android.BuildParams{ - Rule: aconfig.AllDeclarationsRule, - Inputs: a.aconfigFiles, - Output: apexAconfigFile, - Description: "combine_aconfig_declarations", - Args: map[string]string{ - "cache_files": android.JoinPathsWithPrefix(a.aconfigFiles, "--cache "), - }, - }) - - copyCommands = append(copyCommands, "cp -f "+apexAconfigFile.String()+" "+aconfigDest) - implicitInputs = append(implicitInputs, apexAconfigFile) - defaultReadOnlyFiles = append(defaultReadOnlyFiles, "etc/"+apexAconfigFile.Base()) - - for _, info := range createStorageInfo { - outputFile := android.PathForModuleOut(ctx, info.Output_file) - ctx.Build(pctx, android.BuildParams{ - Rule: aconfig.CreateStorageRule, - Inputs: a.aconfigFiles, - Output: outputFile, - Description: info.Desc, - Args: map[string]string{ - "container": ctx.ModuleName(), - "file_type": info.File_type, - "cache_files": android.JoinPathsWithPrefix(a.aconfigFiles, "--cache "), - }, - }) - - copyCommands = append(copyCommands, "cp -f "+outputFile.String()+" "+aconfigDest) - implicitInputs = append(implicitInputs, outputFile) - defaultReadOnlyFiles = append(defaultReadOnlyFiles, "etc/"+outputFile.Base()) - } - } - //////////////////////////////////////////////////////////////////////////////////// // Step 2: create canned_fs_config which encodes filemode,uid,gid of each files // in this APEX. The file will be used by apexer in later steps. - cannedFsConfig := a.buildCannedFsConfig(ctx, defaultReadOnlyFiles) + cannedFsConfig := a.buildCannedFsConfig(ctx) implicitInputs = append(implicitInputs, cannedFsConfig) //////////////////////////////////////////////////////////////////////////////////// @@ -1139,8 +1153,8 @@ func (a *apexBundle) buildLintReports(ctx android.ModuleContext) { a.lintReports = java.BuildModuleLintReportZips(ctx, depSetsBuilder.Build()) } -func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext, defaultReadOnlyFiles []string) android.OutputPath { - var readOnlyPaths = defaultReadOnlyFiles +func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext) android.OutputPath { + var readOnlyPaths = []string{"apex_manifest.json", "apex_manifest.pb"} var executablePaths []string // this also includes dirs var appSetDirs []string appSetFiles := make(map[string]android.Path)