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
diff --git a/android/paths.go b/android/paths.go
index 2c50104..6c3009f 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -16,7 +16,6 @@
import (
"fmt"
- "io/ioutil"
"os"
"path/filepath"
"reflect"
@@ -2099,13 +2098,16 @@
// 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 183eb12..aac5e7d 100644
--- a/bp2build/symlink_forest.go
+++ b/bp2build/symlink_forest.go
@@ -25,6 +25,7 @@
"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 @@
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