Replace android.WriteFile rule with android.WriteFileRule
The android.WriteFile rule takes careful escaping to produce the right contents. Wrap it in an android.WriteFileRule that handles the escaping. Test: compare all android.WriteFile outputs Change-Id: If71a5843af47a37ca61714e1a1ebb32d08536c31
This commit is contained in:
parent
1d26d3033a
commit
cf371cc1f7
13 changed files with 90 additions and 114 deletions
|
@ -598,36 +598,22 @@ func (d *ApexBundleDepsInfo) BuildDepsInfoLists(ctx ModuleContext, minSdkVersion
|
|||
var fullContent 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)) {
|
||||
info := depInfos[key]
|
||||
toName := fmt.Sprintf("%s(minSdkVersion:%s)", info.To, info.MinSdkVersion)
|
||||
if info.IsExternal {
|
||||
toName = toName + " (external)"
|
||||
}
|
||||
fmt.Fprintf(&fullContent, " %s <- %s\\n", toName, strings.Join(SortedUniqueStrings(info.From), ", "))
|
||||
fmt.Fprintf(&flatContent, "%s\\n", toName)
|
||||
fmt.Fprintf(&fullContent, " %s <- %s\n", toName, strings.Join(SortedUniqueStrings(info.From), ", "))
|
||||
fmt.Fprintf(&flatContent, "%s\n", toName)
|
||||
}
|
||||
|
||||
d.fullListPath = PathForModuleOut(ctx, "depsinfo", "fulllist.txt").OutputPath
|
||||
ctx.Build(pctx, BuildParams{
|
||||
Rule: WriteFile,
|
||||
Description: "Full Dependency Info",
|
||||
Output: d.fullListPath,
|
||||
Args: map[string]string{
|
||||
"content": fullContent.String(),
|
||||
},
|
||||
})
|
||||
WriteFileRule(ctx, d.fullListPath, fullContent.String())
|
||||
|
||||
d.flatListPath = PathForModuleOut(ctx, "depsinfo", "flatlist.txt").OutputPath
|
||||
ctx.Build(pctx, BuildParams{
|
||||
Rule: WriteFile,
|
||||
Description: "Flat Dependency Info",
|
||||
Output: d.flatListPath,
|
||||
Args: map[string]string{
|
||||
"content": flatContent.String(),
|
||||
},
|
||||
})
|
||||
WriteFileRule(ctx, d.flatListPath, flatContent.String())
|
||||
}
|
||||
|
||||
// TODO(b/158059172): remove minSdkVersion allowlist
|
||||
|
|
|
@ -225,14 +225,7 @@ func createApiLevelsJson(ctx SingletonContext, file WritablePath,
|
|||
ctx.Errorf(err.Error())
|
||||
}
|
||||
|
||||
ctx.Build(pctx, BuildParams{
|
||||
Rule: WriteFile,
|
||||
Description: "generate " + file.Base(),
|
||||
Output: file,
|
||||
Args: map[string]string{
|
||||
"content": string(jsonStr[:]),
|
||||
},
|
||||
})
|
||||
WriteFileRule(ctx, file, string(jsonStr))
|
||||
}
|
||||
|
||||
func GetApiLevelsJson(ctx PathContext) WritablePath {
|
||||
|
|
|
@ -15,8 +15,12 @@
|
|||
package android
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
_ "github.com/google/blueprint/bootstrap"
|
||||
"github.com/google/blueprint/proptools"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -91,9 +95,9 @@ var (
|
|||
// 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
|
||||
// content to file.
|
||||
WriteFile = pctx.AndroidStaticRule("WriteFile",
|
||||
writeFile = pctx.AndroidStaticRule("writeFile",
|
||||
blueprint.RuleParams{
|
||||
Command: "/bin/bash -c 'echo -e $$0 > $out' '$content'",
|
||||
Command: `/bin/bash -c 'echo -e "$$0" > $out' $content`,
|
||||
Description: "writing file $out",
|
||||
},
|
||||
"content")
|
||||
|
@ -111,3 +115,64 @@ var (
|
|||
func init() {
|
||||
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
|
||||
}
|
||||
|
|
|
@ -5574,7 +5574,7 @@ func TestAppBundle(t *testing.T) {
|
|||
}
|
||||
`, 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"]
|
||||
|
||||
ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`)
|
||||
|
@ -5600,7 +5600,7 @@ func TestAppSetBundle(t *testing.T) {
|
|||
set: "AppSet.apks",
|
||||
}`)
|
||||
mod := ctx.ModuleForTests("myapex", "android_common_myapex_image")
|
||||
bundleConfigRule := mod.Description("Bundle Config")
|
||||
bundleConfigRule := mod.Output("bundle_config.json")
|
||||
content := bundleConfigRule.Args["content"]
|
||||
ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`)
|
||||
s := mod.Rule("apexRule").Args["copy_commands"]
|
||||
|
|
|
@ -373,14 +373,7 @@ func (a *apexBundle) buildBundleConfig(ctx android.ModuleContext) android.Output
|
|||
panic(fmt.Errorf("error while marshalling to %q: %#v", output, err))
|
||||
}
|
||||
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: android.WriteFile,
|
||||
Output: output,
|
||||
Description: "Bundle Config " + output.String(),
|
||||
Args: map[string]string{
|
||||
"content": string(j),
|
||||
},
|
||||
})
|
||||
android.WriteFileRule(ctx, output, string(j))
|
||||
|
||||
return output.OutputPath
|
||||
}
|
||||
|
|
14
apex/key.go
14
apex/key.go
|
@ -116,7 +116,7 @@ func (s *apexKeysText) GenerateBuildActions(ctx android.SingletonContext) {
|
|||
partition 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 {
|
||||
return fmt.Sprintf(format, e.name, "PRESIGNED", "PRESIGNED", "PRESIGNED", "PRESIGNED", e.partition)
|
||||
} else {
|
||||
|
@ -173,17 +173,9 @@ func (s *apexKeysText) GenerateBuildActions(ctx android.SingletonContext) {
|
|||
|
||||
var filecontent strings.Builder
|
||||
for _, name := range moduleNames {
|
||||
fmt.Fprintf(&filecontent, "%s", toString(apexKeyMap[name]))
|
||||
filecontent.WriteString(toString(apexKeyMap[name]))
|
||||
}
|
||||
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: android.WriteFile,
|
||||
Description: "apexkeys.txt",
|
||||
Output: s.output,
|
||||
Args: map[string]string{
|
||||
"content": filecontent.String(),
|
||||
},
|
||||
})
|
||||
android.WriteFileRule(ctx, s.output, filecontent.String())
|
||||
}
|
||||
|
||||
func apexKeysTextFactory() android.Singleton {
|
||||
|
|
|
@ -296,8 +296,8 @@ func checkSnapshotExclude(t *testing.T, ctx *android.TestContext, singleton andr
|
|||
|
||||
func checkWriteFileOutput(t *testing.T, params android.TestingBuildParams, expected []string) {
|
||||
t.Helper()
|
||||
assertString(t, params.Rule.String(), android.WriteFile.String())
|
||||
actual := strings.FieldsFunc(strings.ReplaceAll(params.Args["content"], "\\n", "\n"), func(r rune) bool { return r == '\n' })
|
||||
content := android.ContentFromFileRuleForTests(t, params)
|
||||
actual := strings.FieldsFunc(content, func(r rune) bool { return r == '\n' })
|
||||
assertArrayString(t, actual, expected)
|
||||
}
|
||||
|
||||
|
|
|
@ -278,14 +278,7 @@ func (fuzz *fuzzBinary) install(ctx ModuleContext, file android.Path) {
|
|||
|
||||
if fuzz.Properties.Fuzz_config != nil {
|
||||
configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: android.WriteFile,
|
||||
Description: "fuzzer infrastructure configuration",
|
||||
Output: configPath,
|
||||
Args: map[string]string{
|
||||
"content": fuzz.Properties.Fuzz_config.String(),
|
||||
},
|
||||
})
|
||||
android.WriteFileRule(ctx, configPath, fuzz.Properties.Fuzz_config.String())
|
||||
fuzz.config = configPath
|
||||
}
|
||||
|
||||
|
|
|
@ -93,13 +93,6 @@ func combineNotices(ctx android.SingletonContext, paths android.Paths, out strin
|
|||
|
||||
func writeStringToFile(ctx android.SingletonContext, content, out string) android.OutputPath {
|
||||
outPath := android.PathForOutput(ctx, out)
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: android.WriteFile,
|
||||
Output: outPath,
|
||||
Description: "WriteFile " + out,
|
||||
Args: map[string]string{
|
||||
"content": content,
|
||||
},
|
||||
})
|
||||
android.WriteFileRule(ctx, outPath, content)
|
||||
return outPath
|
||||
}
|
||||
|
|
18
cc/vndk.go
18
cc/vndk.go
|
@ -487,14 +487,7 @@ func (txt *vndkLibrariesTxt) GenerateAndroidBuildActions(ctx android.ModuleConte
|
|||
}
|
||||
|
||||
txt.outputFile = android.PathForModuleOut(ctx, filename).OutputPath
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: android.WriteFile,
|
||||
Output: txt.outputFile,
|
||||
Description: "Writing " + txt.outputFile.String(),
|
||||
Args: map[string]string{
|
||||
"content": strings.Join(list, "\\n"),
|
||||
},
|
||||
})
|
||||
android.WriteFileRule(ctx, txt.outputFile, strings.Join(list, "\n"))
|
||||
|
||||
installPath := android.PathForModuleInstall(ctx, "etc")
|
||||
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(vndkprivate, "VNDK-private: ")...)
|
||||
c.vndkLibrariesFile = android.PathForOutput(ctx, "vndk", "vndk.libraries.txt")
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: android.WriteFile,
|
||||
Output: c.vndkLibrariesFile,
|
||||
Description: "Writing " + c.vndkLibrariesFile.String(),
|
||||
Args: map[string]string{
|
||||
"content": strings.Join(merged, "\\n"),
|
||||
},
|
||||
})
|
||||
android.WriteFileRule(ctx, c.vndkLibrariesFile, strings.Join(merged, "\n"))
|
||||
}
|
||||
|
||||
func (c *vndkSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) {
|
||||
|
|
|
@ -488,13 +488,7 @@ func (s *globalSoongConfigSingleton) GenerateBuildActions(ctx android.SingletonC
|
|||
return
|
||||
}
|
||||
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: android.WriteFile,
|
||||
Output: android.PathForOutput(ctx, "dexpreopt_soong.config"),
|
||||
Args: map[string]string{
|
||||
"content": string(data),
|
||||
},
|
||||
})
|
||||
android.WriteFileRule(ctx, android.PathForOutput(ctx, "dexpreopt_soong.config"), string(data))
|
||||
}
|
||||
|
||||
func (s *globalSoongConfigSingleton) MakeVars(ctx android.MakeVarsContext) {
|
||||
|
|
|
@ -572,14 +572,7 @@ func TransformJetifier(ctx android.ModuleContext, outputFile android.WritablePat
|
|||
}
|
||||
|
||||
func GenerateMainClassManifest(ctx android.ModuleContext, outputFile android.WritablePath, mainClass string) {
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: android.WriteFile,
|
||||
Description: "manifest",
|
||||
Output: outputFile,
|
||||
Args: map[string]string{
|
||||
"content": "Main-Class: " + mainClass + "\n",
|
||||
},
|
||||
})
|
||||
android.WriteFileRule(ctx, outputFile, "Main-Class: "+mainClass+"\n")
|
||||
}
|
||||
|
||||
func TransformZipAlign(ctx android.ModuleContext, outputFile android.WritablePath, inputFile android.Path) {
|
||||
|
|
|
@ -651,14 +651,8 @@ func updatableBcpPackagesRule(ctx android.SingletonContext, image *bootImageConf
|
|||
updatableBcpPackagesName := "updatable-bcp-packages.txt"
|
||||
updatableBcpPackages := image.dir.Join(ctx, updatableBcpPackagesName)
|
||||
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: android.WriteFile,
|
||||
Output: updatableBcpPackages,
|
||||
Args: map[string]string{
|
||||
// WriteFile automatically adds the last end-of-line.
|
||||
"content": strings.Join(updatablePackages, "\\n"),
|
||||
},
|
||||
})
|
||||
// WriteFileRule automatically adds the last end-of-line.
|
||||
android.WriteFileRule(ctx, updatableBcpPackages, strings.Join(updatablePackages, "\n"))
|
||||
|
||||
rule := android.NewRuleBuilder()
|
||||
rule.MissingDeps(missingDeps)
|
||||
|
@ -720,13 +714,7 @@ func dumpOatRules(ctx android.SingletonContext, image *bootImageConfig) {
|
|||
func writeGlobalConfigForMake(ctx android.SingletonContext, path android.WritablePath) {
|
||||
data := dexpreopt.GetGlobalConfigRawData(ctx)
|
||||
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: android.WriteFile,
|
||||
Output: path,
|
||||
Args: map[string]string{
|
||||
"content": string(data),
|
||||
},
|
||||
})
|
||||
android.WriteFileRule(ctx, path, string(data))
|
||||
}
|
||||
|
||||
// Export paths for default boot image to Make
|
||||
|
|
Loading…
Reference in a new issue