Allow Bazel to write to an external DIST_DIR (outside of OUT_DIR).
Also get Bazel to write real files there (not symlinks) so that the DIST_DIR can be independent.
Test: Manually using e.g. DIST_DIR=/tmp/foo USE_BAZEL=1 m dist
Change-Id: I39d5219500864c9ecc85f356a028e9b5bf2607f4
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 4ffe944..68480d4 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -18,6 +18,7 @@
"context"
"flag"
"fmt"
+ "io/ioutil"
"os"
"path/filepath"
"strconv"
@@ -173,6 +174,10 @@
build.SetupOutDir(buildCtx, config)
+ if config.UseBazel() {
+ defer populateExternalDistDir(buildCtx, config)
+ }
+
// Set up files to be outputted in the log directory.
logsDir := config.LogsDir()
@@ -510,3 +515,72 @@
// command not found
return nil, nil, fmt.Errorf("Command not found: %q", args)
}
+
+// For Bazel support, this moves files and directories from e.g. out/dist/$f to DIST_DIR/$f if necessary.
+func populateExternalDistDir(ctx build.Context, config build.Config) {
+ // Make sure that internalDistDirPath and externalDistDirPath are both absolute paths, so we can compare them
+ var err error
+ var internalDistDirPath string
+ var externalDistDirPath string
+ if internalDistDirPath, err = filepath.Abs(config.DistDir()); err != nil {
+ ctx.Fatalf("Unable to find absolute path of %s: %s", internalDistDirPath, err)
+ }
+ if externalDistDirPath, err = filepath.Abs(config.RealDistDir()); err != nil {
+ ctx.Fatalf("Unable to find absolute path of %s: %s", externalDistDirPath, err)
+ }
+ if externalDistDirPath == internalDistDirPath {
+ return
+ }
+
+ // Make sure the external DIST_DIR actually exists before trying to write to it
+ if err = os.MkdirAll(externalDistDirPath, 0755); err != nil {
+ ctx.Fatalf("Unable to make directory %s: %s", externalDistDirPath, err)
+ }
+
+ ctx.Println("Populating external DIST_DIR...")
+
+ populateExternalDistDirHelper(ctx, config, internalDistDirPath, externalDistDirPath)
+}
+
+func populateExternalDistDirHelper(ctx build.Context, config build.Config, internalDistDirPath string, externalDistDirPath string) {
+ files, err := ioutil.ReadDir(internalDistDirPath)
+ if err != nil {
+ ctx.Fatalf("Can't read internal distdir %s: %s", internalDistDirPath, err)
+ }
+ for _, f := range files {
+ internalFilePath := filepath.Join(internalDistDirPath, f.Name())
+ externalFilePath := filepath.Join(externalDistDirPath, f.Name())
+
+ if f.IsDir() {
+ // Moving a directory - check if there is an existing directory to merge with
+ externalLstat, err := os.Lstat(externalFilePath)
+ if err != nil {
+ if !os.IsNotExist(err) {
+ ctx.Fatalf("Can't lstat external %s: %s", externalDistDirPath, err)
+ }
+ // Otherwise, if the error was os.IsNotExist, that's fine and we fall through to the rename at the bottom
+ } else {
+ if externalLstat.IsDir() {
+ // Existing dir - try to merge the directories?
+ populateExternalDistDirHelper(ctx, config, internalFilePath, externalFilePath)
+ continue
+ } else {
+ // Existing file being replaced with a directory. Delete the existing file...
+ if err := os.RemoveAll(externalFilePath); err != nil {
+ ctx.Fatalf("Unable to remove existing %s: %s", externalFilePath, err)
+ }
+ }
+ }
+ } else {
+ // Moving a file (not a dir) - delete any existing file or directory
+ if err := os.RemoveAll(externalFilePath); err != nil {
+ ctx.Fatalf("Unable to remove existing %s: %s", externalFilePath, err)
+ }
+ }
+
+ // The actual move - do a rename instead of a copy in order to save disk space.
+ if err := os.Rename(internalFilePath, externalFilePath); err != nil {
+ ctx.Fatalf("Unable to rename %s -> %s due to error %s", internalFilePath, externalFilePath, err)
+ }
+ }
+}