Write raw files to disk instead of the ninja file
Writing raw files as rules in the ninja file unnecessarily bloats
the ninja file. Write files immediately to disk instead to files
based on the hash of the contents, and then emit ninja rules to
copy the files into place during the build. Delete obsolete files
in a singleton at the end of analysis.
Bug: 306029038
Test: Run: m libc_musl_version.h
touch build/soong/Android.bp
m libc_musl_version.h
libc_musl_version.h/genrule.sbox.textproto is not recopied.
Test: Run: lunch aosp_cf_x86_64_phone-userdebug
m libc_musl_version.h
lunch aosp_x86_64-userdebug
m libc_musl_version.h
lunch aosp_cf_x86_64_phone-userdebug
m libc_musl_version.h
libc_musl_version.h/genrule.sbox.textproto is recopied but restat prevents rerunning the genrule.
Test: Run: touch out/soong/raw-aosp_cf_x86_64_phone/00/foo
touch build/soong/Android.bp
m nothing
out/soong/raw-aosp_cf_x86_64_phone/00/foo is removed.
Change-Id: I172869c4d49565504794c051e2e8c1f7cf46486e
diff --git a/android/defs.go b/android/defs.go
index 03968c1..a988964 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -15,13 +15,8 @@
package android
import (
- "fmt"
- "strings"
- "testing"
-
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
- "github.com/google/blueprint/proptools"
)
var (
@@ -72,8 +67,7 @@
Command: "if ! cmp -s $in $out; then cp $in $out; fi",
Description: "cp if changed $out",
Restat: true,
- },
- "cpFlags")
+ })
CpExecutable = pctx.AndroidStaticRule("CpExecutable",
blueprint.RuleParams{
@@ -146,106 +140,6 @@
return BazelToolchainVars(config, exportedVars)
}
-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(`'\''`, `'`)
-)
-
-func buildWriteFileRule(ctx BuilderContext, outputFile WritablePath, content string) {
- content = echoEscaper.Replace(content)
- content = proptools.NinjaEscape(proptools.ShellEscapeIncludingSpaces(content))
- if content == "" {
- content = "''"
- }
- ctx.Build(pctx, BuildParams{
- Rule: writeFile,
- Output: outputFile,
- Description: "write " + outputFile.Base(),
- Args: map[string]string{
- "content": content,
- },
- })
-}
-
-// 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) {
- WriteFileRuleVerbatim(ctx, outputFile, content+"\n")
-}
-
-// WriteFileRuleVerbatim 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.
-func WriteFileRuleVerbatim(ctx BuilderContext, outputFile WritablePath, content string) {
- // This is MAX_ARG_STRLEN subtracted with some safety to account for shell escapes
- const SHARD_SIZE = 131072 - 10000
-
- if len(content) > SHARD_SIZE {
- var chunks WritablePaths
- for i, c := range ShardString(content, SHARD_SIZE) {
- tempPath := outputFile.ReplaceExtension(ctx, fmt.Sprintf("%s.%d", outputFile.Ext(), i))
- buildWriteFileRule(ctx, tempPath, c)
- chunks = append(chunks, tempPath)
- }
- ctx.Build(pctx, BuildParams{
- Rule: Cat,
- Inputs: chunks.Paths(),
- Output: outputFile,
- Description: "Merging to " + outputFile.Base(),
- })
- return
- }
- buildWriteFileRule(ctx, outputFile, content)
-}
-
-// WriteExecutableFileRuleVerbatim is the same as WriteFileRuleVerbatim, but runs chmod +x on the result
-func WriteExecutableFileRuleVerbatim(ctx BuilderContext, outputFile WritablePath, content string) {
- intermediate := PathForIntermediates(ctx, "write_executable_file_intermediates").Join(ctx, outputFile.String())
- WriteFileRuleVerbatim(ctx, intermediate, content)
- ctx.Build(pctx, BuildParams{
- Rule: CpExecutable,
- Output: outputFile,
- Input: intermediate,
- })
-}
-
-// 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, ctx *TestContext, 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
-}
-
// GlobToListFileRule creates a rule that writes a list of files matching a pattern to a file.
func GlobToListFileRule(ctx ModuleContext, pattern string, excludes []string, file WritablePath) {
bootstrap.GlobFile(ctx.blueprintModuleContext(), pattern, excludes, file.String())