diff --git a/ui/build/bazel.go b/ui/build/bazel.go index 910131a7d..1cab8f8a7 100644 --- a/ui/build/bazel.go +++ b/ui/build/bazel.go @@ -189,6 +189,7 @@ func runBazel(ctx Context, config Config) { // currently hardcoded as ninja_build.output_root. bazelNinjaBuildOutputRoot := filepath.Join(outputBasePath, "..", "out") + ctx.Println("Creating output symlinks..") symlinkOutdir(ctx, config, bazelNinjaBuildOutputRoot, ".") } @@ -201,27 +202,39 @@ func symlinkOutdir(ctx Context, config Config, rootPath string, relativePath str if err != nil { ctx.Fatal(err) } + for _, f := range files { + // The original Bazel file path destPath := filepath.Join(destDir, f.Name()) + + // The desired Soong file path srcPath := filepath.Join(config.OutDir(), relativePath, f.Name()) - if statResult, err := os.Stat(srcPath); err == nil { - if statResult.Mode().IsDir() && f.IsDir() { - // Directory under OutDir already exists, so recurse on its contents. + + destLstatResult, destLstatErr := os.Lstat(destPath) + if destLstatErr != nil { + ctx.Fatalf("Unable to Lstat dest %s: %s", destPath, destLstatErr) + } + + srcLstatResult, srcLstatErr := os.Lstat(srcPath) + + if srcLstatErr == nil { + if srcLstatResult.IsDir() && destLstatResult.IsDir() { + // src and dest are both existing dirs - recurse on the dest dir contents... symlinkOutdir(ctx, config, rootPath, filepath.Join(relativePath, f.Name())) - } else if !statResult.Mode().IsDir() && !f.IsDir() { - // File exists both in source and destination, and it's not a directory - // in either location. Do nothing. - // This can arise for files which are generated under OutDir outside of - // soong_build, such as .bootstrap files. } else { - // File is a directory in one location but not the other. Raise an error. - ctx.Fatalf("Could not link %s to %s due to conflict", srcPath, destPath) + // Ignore other pre-existing src files (could be pre-existing files, directories, symlinks, ...) + // This can arise for files which are generated under OutDir outside of soong_build, such as .bootstrap files. + // FIXME: This might cause a problem later e.g. if a symlink in the build graph changes... } - } else if os.IsNotExist(err) { - // Create symlink srcPath -> fullDestPath. - os.Symlink(destPath, srcPath) } else { - ctx.Fatalf("Unable to stat %s: %s", srcPath, err) + if !os.IsNotExist(srcLstatErr) { + ctx.Fatalf("Unable to Lstat src %s: %s", srcPath, srcLstatErr) + } + + // src does not exist, so try to create a src -> dest symlink (i.e. a Soong path -> Bazel path symlink) + if symlinkErr := os.Symlink(destPath, srcPath); symlinkErr != nil { + ctx.Fatalf("Unable to create symlink %s -> %s due to error %s", srcPath, destPath, symlinkErr) + } } } }