From 1a12d032301b67d0b20bb93c80a819cb0f616833 Mon Sep 17 00:00:00 2001 From: Chris Parsons Date: Mon, 6 Feb 2023 22:37:41 -0500 Subject: [PATCH] Avoid rewriting soong_build outputs if unchanged This changes bp2build codegen, symlink forest generation, and soong_build so that they do not rewrite output files if the contents are unchanged. Bug: 266983462 Test: m droid Test: canonical_perf.sh benchmarking Test: Manually verified that rerunning analysis did not regenerate out/soong/workspace/prebuilts/sdk/BUILD.bazel unless contents changed Change-Id: I5ec227df7a32b53c7fa0d741fb1403a51931024b --- android/paths.go | 6 ++++-- bp2build/symlink_forest.go | 23 ++++++----------------- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/android/paths.go b/android/paths.go index 2c5010473..6c3009f4c 100644 --- a/android/paths.go +++ b/android/paths.go @@ -16,7 +16,6 @@ package android import ( "fmt" - "io/ioutil" "os" "path/filepath" "reflect" @@ -2099,13 +2098,16 @@ func maybeRelErr(basePath string, targetPath string) (string, bool, error) { // Writes a file to the output directory. Attempting to write directly to the output directory // will fail due to the sandbox of the soong_build process. +// Only writes the file if the file doesn't exist or if it has different contents, to prevent +// updating the timestamp if no changes would be made. (This is better for incremental +// performance.) func WriteFileToOutputDir(path WritablePath, data []byte, perm os.FileMode) error { absPath := absolutePath(path.String()) err := os.MkdirAll(filepath.Dir(absPath), 0777) if err != nil { return err } - return ioutil.WriteFile(absPath, data, perm) + return pathtools.WriteFileIfChanged(absPath, data, perm) } func RemoveAllOutputDir(path WritablePath) error { diff --git a/bp2build/symlink_forest.go b/bp2build/symlink_forest.go index 183eb1205..aac5e7d2c 100644 --- a/bp2build/symlink_forest.go +++ b/bp2build/symlink_forest.go @@ -25,6 +25,7 @@ import ( "sync/atomic" "android/soong/shared" + "github.com/google/blueprint/pathtools" ) // A tree structure that describes what to do at each directory in the created @@ -116,25 +117,13 @@ func mergeBuildFiles(output string, srcBuildFile string, generatedBuildFile stri generatedBuildFileContent = packageDefaultVisibilityRegex.ReplaceAll(generatedBuildFileContent, []byte{}) } - outFile, err := os.Create(output) - if err != nil { - return err + newContents := generatedBuildFileContent + if newContents[len(newContents)-1] != '\n' { + newContents = append(newContents, '\n') } + newContents = append(newContents, srcBuildFileContent...) - _, err = outFile.Write(generatedBuildFileContent) - if err != nil { - return err - } - - if generatedBuildFileContent[len(generatedBuildFileContent)-1] != '\n' { - _, err = outFile.WriteString("\n") - if err != nil { - return err - } - } - - _, err = outFile.Write(srcBuildFileContent) - return err + return pathtools.WriteFileIfChanged(output, newContents, 0666) } // Calls readdir() and returns it as a map from the basename of the files in dir