Merge "Replace android.WriteFile rule with android.WriteFileRule"

This commit is contained in:
Colin Cross
2020-11-16 23:11:41 +00:00
committed by Gerrit Code Review
13 changed files with 90 additions and 114 deletions

View File

@@ -598,36 +598,22 @@ func (d *ApexBundleDepsInfo) BuildDepsInfoLists(ctx ModuleContext, minSdkVersion
var fullContent strings.Builder var fullContent strings.Builder
var flatContent strings.Builder var flatContent strings.Builder
fmt.Fprintf(&fullContent, "%s(minSdkVersion:%s):\\n", ctx.ModuleName(), minSdkVersion) fmt.Fprintf(&fullContent, "%s(minSdkVersion:%s):\n", ctx.ModuleName(), minSdkVersion)
for _, key := range FirstUniqueStrings(SortedStringKeys(depInfos)) { for _, key := range FirstUniqueStrings(SortedStringKeys(depInfos)) {
info := depInfos[key] info := depInfos[key]
toName := fmt.Sprintf("%s(minSdkVersion:%s)", info.To, info.MinSdkVersion) toName := fmt.Sprintf("%s(minSdkVersion:%s)", info.To, info.MinSdkVersion)
if info.IsExternal { if info.IsExternal {
toName = toName + " (external)" toName = toName + " (external)"
} }
fmt.Fprintf(&fullContent, " %s <- %s\\n", toName, strings.Join(SortedUniqueStrings(info.From), ", ")) fmt.Fprintf(&fullContent, " %s <- %s\n", toName, strings.Join(SortedUniqueStrings(info.From), ", "))
fmt.Fprintf(&flatContent, "%s\\n", toName) fmt.Fprintf(&flatContent, "%s\n", toName)
} }
d.fullListPath = PathForModuleOut(ctx, "depsinfo", "fulllist.txt").OutputPath d.fullListPath = PathForModuleOut(ctx, "depsinfo", "fulllist.txt").OutputPath
ctx.Build(pctx, BuildParams{ WriteFileRule(ctx, d.fullListPath, fullContent.String())
Rule: WriteFile,
Description: "Full Dependency Info",
Output: d.fullListPath,
Args: map[string]string{
"content": fullContent.String(),
},
})
d.flatListPath = PathForModuleOut(ctx, "depsinfo", "flatlist.txt").OutputPath d.flatListPath = PathForModuleOut(ctx, "depsinfo", "flatlist.txt").OutputPath
ctx.Build(pctx, BuildParams{ WriteFileRule(ctx, d.flatListPath, flatContent.String())
Rule: WriteFile,
Description: "Flat Dependency Info",
Output: d.flatListPath,
Args: map[string]string{
"content": flatContent.String(),
},
})
} }
// TODO(b/158059172): remove minSdkVersion allowlist // TODO(b/158059172): remove minSdkVersion allowlist

View File

@@ -225,14 +225,7 @@ func createApiLevelsJson(ctx SingletonContext, file WritablePath,
ctx.Errorf(err.Error()) ctx.Errorf(err.Error())
} }
ctx.Build(pctx, BuildParams{ WriteFileRule(ctx, file, string(jsonStr))
Rule: WriteFile,
Description: "generate " + file.Base(),
Output: file,
Args: map[string]string{
"content": string(jsonStr[:]),
},
})
} }
func GetApiLevelsJson(ctx PathContext) WritablePath { func GetApiLevelsJson(ctx PathContext) WritablePath {

View File

@@ -15,8 +15,12 @@
package android package android
import ( import (
"strings"
"testing"
"github.com/google/blueprint" "github.com/google/blueprint"
_ "github.com/google/blueprint/bootstrap" _ "github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/proptools"
) )
var ( var (
@@ -91,9 +95,9 @@ var (
// ubuntu 14.04 offcially use dash for /bin/sh, and its builtin echo command // ubuntu 14.04 offcially use dash for /bin/sh, and its builtin echo command
// doesn't support -e option. Therefore we force to use /bin/bash when writing out // doesn't support -e option. Therefore we force to use /bin/bash when writing out
// content to file. // content to file.
WriteFile = pctx.AndroidStaticRule("WriteFile", writeFile = pctx.AndroidStaticRule("writeFile",
blueprint.RuleParams{ blueprint.RuleParams{
Command: "/bin/bash -c 'echo -e $$0 > $out' '$content'", Command: `/bin/bash -c 'echo -e "$$0" > $out' $content`,
Description: "writing file $out", Description: "writing file $out",
}, },
"content") "content")
@@ -111,3 +115,64 @@ var (
func init() { func init() {
pctx.Import("github.com/google/blueprint/bootstrap") pctx.Import("github.com/google/blueprint/bootstrap")
} }
var (
// echoEscaper escapes a string such that passing it to "echo -e" will produce the input value.
echoEscaper = strings.NewReplacer(
`\`, `\\`, // First escape existing backslashes so they aren't interpreted by `echo -e`.
"\n", `\n`, // Then replace newlines with \n
)
// echoEscaper reverses echoEscaper.
echoUnescaper = strings.NewReplacer(
`\n`, "\n",
`\\`, `\`,
)
// shellUnescaper reverses the replacer in proptools.ShellEscape
shellUnescaper = strings.NewReplacer(`'\''`, `'`)
)
// WriteFileRule creates a ninja rule to write contents to a file. The contents will be escaped
// so that the file contains exactly the contents passed to the function, plus a trailing newline.
func WriteFileRule(ctx BuilderContext, outputFile WritablePath, content string) {
content = echoEscaper.Replace(content)
content = proptools.ShellEscape(content)
if content == "" {
content = "''"
}
ctx.Build(pctx, BuildParams{
Rule: writeFile,
Output: outputFile,
Description: "write " + outputFile.Base(),
Args: map[string]string{
"content": content,
},
})
}
// shellUnescape reverses proptools.ShellEscape
func shellUnescape(s string) string {
// Remove leading and trailing quotes if present
if len(s) >= 2 && s[0] == '\'' {
s = s[1 : len(s)-1]
}
s = shellUnescaper.Replace(s)
return s
}
// ContentFromFileRuleForTests returns the content that was passed to a WriteFileRule for use
// in tests.
func ContentFromFileRuleForTests(t *testing.T, params TestingBuildParams) string {
t.Helper()
if g, w := params.Rule, writeFile; g != w {
t.Errorf("expected params.Rule to be %q, was %q", w, g)
return ""
}
content := params.Args["content"]
content = shellUnescape(content)
content = echoUnescaper.Replace(content)
return content
}

View File

@@ -5447,7 +5447,7 @@ func TestAppBundle(t *testing.T) {
} }
`, withManifestPackageNameOverrides([]string{"AppFoo:com.android.foo"})) `, withManifestPackageNameOverrides([]string{"AppFoo:com.android.foo"}))
bundleConfigRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Description("Bundle Config") bundleConfigRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("bundle_config.json")
content := bundleConfigRule.Args["content"] content := bundleConfigRule.Args["content"]
ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`) ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`)
@@ -5473,7 +5473,7 @@ func TestAppSetBundle(t *testing.T) {
set: "AppSet.apks", set: "AppSet.apks",
}`) }`)
mod := ctx.ModuleForTests("myapex", "android_common_myapex_image") mod := ctx.ModuleForTests("myapex", "android_common_myapex_image")
bundleConfigRule := mod.Description("Bundle Config") bundleConfigRule := mod.Output("bundle_config.json")
content := bundleConfigRule.Args["content"] content := bundleConfigRule.Args["content"]
ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`) ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`)
s := mod.Rule("apexRule").Args["copy_commands"] s := mod.Rule("apexRule").Args["copy_commands"]

View File

@@ -373,14 +373,7 @@ func (a *apexBundle) buildBundleConfig(ctx android.ModuleContext) android.Output
panic(fmt.Errorf("error while marshalling to %q: %#v", output, err)) panic(fmt.Errorf("error while marshalling to %q: %#v", output, err))
} }
ctx.Build(pctx, android.BuildParams{ android.WriteFileRule(ctx, output, string(j))
Rule: android.WriteFile,
Output: output,
Description: "Bundle Config " + output.String(),
Args: map[string]string{
"content": string(j),
},
})
return output.OutputPath return output.OutputPath
} }

View File

@@ -116,7 +116,7 @@ func (s *apexKeysText) GenerateBuildActions(ctx android.SingletonContext) {
partition string partition string
} }
toString := func(e apexKeyEntry) string { toString := func(e apexKeyEntry) string {
format := "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q partition=%q\\n" format := "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q partition=%q\n"
if e.presigned { if e.presigned {
return fmt.Sprintf(format, e.name, "PRESIGNED", "PRESIGNED", "PRESIGNED", "PRESIGNED", e.partition) return fmt.Sprintf(format, e.name, "PRESIGNED", "PRESIGNED", "PRESIGNED", "PRESIGNED", e.partition)
} else { } else {
@@ -173,17 +173,9 @@ func (s *apexKeysText) GenerateBuildActions(ctx android.SingletonContext) {
var filecontent strings.Builder var filecontent strings.Builder
for _, name := range moduleNames { for _, name := range moduleNames {
fmt.Fprintf(&filecontent, "%s", toString(apexKeyMap[name])) filecontent.WriteString(toString(apexKeyMap[name]))
} }
android.WriteFileRule(ctx, s.output, filecontent.String())
ctx.Build(pctx, android.BuildParams{
Rule: android.WriteFile,
Description: "apexkeys.txt",
Output: s.output,
Args: map[string]string{
"content": filecontent.String(),
},
})
} }
func apexKeysTextFactory() android.Singleton { func apexKeysTextFactory() android.Singleton {

View File

@@ -296,8 +296,8 @@ func checkSnapshotExclude(t *testing.T, ctx *android.TestContext, singleton andr
func checkWriteFileOutput(t *testing.T, params android.TestingBuildParams, expected []string) { func checkWriteFileOutput(t *testing.T, params android.TestingBuildParams, expected []string) {
t.Helper() t.Helper()
assertString(t, params.Rule.String(), android.WriteFile.String()) content := android.ContentFromFileRuleForTests(t, params)
actual := strings.FieldsFunc(strings.ReplaceAll(params.Args["content"], "\\n", "\n"), func(r rune) bool { return r == '\n' }) actual := strings.FieldsFunc(content, func(r rune) bool { return r == '\n' })
assertArrayString(t, actual, expected) assertArrayString(t, actual, expected)
} }

View File

@@ -278,14 +278,7 @@ func (fuzz *fuzzBinary) install(ctx ModuleContext, file android.Path) {
if fuzz.Properties.Fuzz_config != nil { if fuzz.Properties.Fuzz_config != nil {
configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json") configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
ctx.Build(pctx, android.BuildParams{ android.WriteFileRule(ctx, configPath, fuzz.Properties.Fuzz_config.String())
Rule: android.WriteFile,
Description: "fuzzer infrastructure configuration",
Output: configPath,
Args: map[string]string{
"content": fuzz.Properties.Fuzz_config.String(),
},
})
fuzz.config = configPath fuzz.config = configPath
} }

View File

@@ -93,13 +93,6 @@ func combineNotices(ctx android.SingletonContext, paths android.Paths, out strin
func writeStringToFile(ctx android.SingletonContext, content, out string) android.OutputPath { func writeStringToFile(ctx android.SingletonContext, content, out string) android.OutputPath {
outPath := android.PathForOutput(ctx, out) outPath := android.PathForOutput(ctx, out)
ctx.Build(pctx, android.BuildParams{ android.WriteFileRule(ctx, outPath, content)
Rule: android.WriteFile,
Output: outPath,
Description: "WriteFile " + out,
Args: map[string]string{
"content": content,
},
})
return outPath return outPath
} }

View File

@@ -487,14 +487,7 @@ func (txt *vndkLibrariesTxt) GenerateAndroidBuildActions(ctx android.ModuleConte
} }
txt.outputFile = android.PathForModuleOut(ctx, filename).OutputPath txt.outputFile = android.PathForModuleOut(ctx, filename).OutputPath
ctx.Build(pctx, android.BuildParams{ android.WriteFileRule(ctx, txt.outputFile, strings.Join(list, "\n"))
Rule: android.WriteFile,
Output: txt.outputFile,
Description: "Writing " + txt.outputFile.String(),
Args: map[string]string{
"content": strings.Join(list, "\\n"),
},
})
installPath := android.PathForModuleInstall(ctx, "etc") installPath := android.PathForModuleInstall(ctx, "etc")
ctx.InstallFile(installPath, filename, txt.outputFile) ctx.InstallFile(installPath, filename, txt.outputFile)
@@ -825,14 +818,7 @@ func (c *vndkSnapshotSingleton) buildVndkLibrariesTxtFiles(ctx android.Singleton
merged = append(merged, addPrefix(filterOutLibClangRt(vndkcore), "VNDK-core: ")...) merged = append(merged, addPrefix(filterOutLibClangRt(vndkcore), "VNDK-core: ")...)
merged = append(merged, addPrefix(vndkprivate, "VNDK-private: ")...) merged = append(merged, addPrefix(vndkprivate, "VNDK-private: ")...)
c.vndkLibrariesFile = android.PathForOutput(ctx, "vndk", "vndk.libraries.txt") c.vndkLibrariesFile = android.PathForOutput(ctx, "vndk", "vndk.libraries.txt")
ctx.Build(pctx, android.BuildParams{ android.WriteFileRule(ctx, c.vndkLibrariesFile, strings.Join(merged, "\n"))
Rule: android.WriteFile,
Output: c.vndkLibrariesFile,
Description: "Writing " + c.vndkLibrariesFile.String(),
Args: map[string]string{
"content": strings.Join(merged, "\\n"),
},
})
} }
func (c *vndkSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) { func (c *vndkSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) {

View File

@@ -486,13 +486,7 @@ func (s *globalSoongConfigSingleton) GenerateBuildActions(ctx android.SingletonC
return return
} }
ctx.Build(pctx, android.BuildParams{ android.WriteFileRule(ctx, android.PathForOutput(ctx, "dexpreopt_soong.config"), string(data))
Rule: android.WriteFile,
Output: android.PathForOutput(ctx, "dexpreopt_soong.config"),
Args: map[string]string{
"content": string(data),
},
})
} }
func (s *globalSoongConfigSingleton) MakeVars(ctx android.MakeVarsContext) { func (s *globalSoongConfigSingleton) MakeVars(ctx android.MakeVarsContext) {

View File

@@ -572,14 +572,7 @@ func TransformJetifier(ctx android.ModuleContext, outputFile android.WritablePat
} }
func GenerateMainClassManifest(ctx android.ModuleContext, outputFile android.WritablePath, mainClass string) { func GenerateMainClassManifest(ctx android.ModuleContext, outputFile android.WritablePath, mainClass string) {
ctx.Build(pctx, android.BuildParams{ android.WriteFileRule(ctx, outputFile, "Main-Class: "+mainClass+"\n")
Rule: android.WriteFile,
Description: "manifest",
Output: outputFile,
Args: map[string]string{
"content": "Main-Class: " + mainClass + "\n",
},
})
} }
func TransformZipAlign(ctx android.ModuleContext, outputFile android.WritablePath, inputFile android.Path) { func TransformZipAlign(ctx android.ModuleContext, outputFile android.WritablePath, inputFile android.Path) {

View File

@@ -651,14 +651,8 @@ func updatableBcpPackagesRule(ctx android.SingletonContext, image *bootImageConf
updatableBcpPackagesName := "updatable-bcp-packages.txt" updatableBcpPackagesName := "updatable-bcp-packages.txt"
updatableBcpPackages := image.dir.Join(ctx, updatableBcpPackagesName) updatableBcpPackages := image.dir.Join(ctx, updatableBcpPackagesName)
ctx.Build(pctx, android.BuildParams{ // WriteFileRule automatically adds the last end-of-line.
Rule: android.WriteFile, android.WriteFileRule(ctx, updatableBcpPackages, strings.Join(updatablePackages, "\n"))
Output: updatableBcpPackages,
Args: map[string]string{
// WriteFile automatically adds the last end-of-line.
"content": strings.Join(updatablePackages, "\\n"),
},
})
rule := android.NewRuleBuilder() rule := android.NewRuleBuilder()
rule.MissingDeps(missingDeps) rule.MissingDeps(missingDeps)
@@ -720,13 +714,7 @@ func dumpOatRules(ctx android.SingletonContext, image *bootImageConfig) {
func writeGlobalConfigForMake(ctx android.SingletonContext, path android.WritablePath) { func writeGlobalConfigForMake(ctx android.SingletonContext, path android.WritablePath) {
data := dexpreopt.GetGlobalConfigRawData(ctx) data := dexpreopt.GetGlobalConfigRawData(ctx)
ctx.Build(pctx, android.BuildParams{ android.WriteFileRule(ctx, path, string(data))
Rule: android.WriteFile,
Output: path,
Args: map[string]string{
"content": string(data),
},
})
} }
// Export paths for default boot image to Make // Export paths for default boot image to Make