Parcourir la source

Pivot towards relative paths for installs and runtimes (#6547)

When building in Bazel actions, notably building runtimes, using
absolute paths makes the results non-hermetic and generally less
cache-friendly.

This restructures the code to only form an absolute path as part of the
`bazel run` change of working directory. It also tries to make the API
for doing this a bit more clear by taking the `exe_path` and
transforming it internally.

To support this, this PR also generalizes the `RemovingDir` to support
relative paths. While these can be tricky -- the working directory needs
to not change while they exist -- that isn't a reason to fully exclude
them and they're useful for implementing relative-path runtimes, etc.
Chandler Carruth il y a 4 mois
Parent
commit
e545929386

+ 2 - 0
common/BUILD

@@ -32,6 +32,8 @@ cc_library(
     name = "bazel_working_dir",
     hdrs = ["bazel_working_dir.h"],
     deps = [
+        ":check",
+        ":filesystem",
         "@llvm-project//llvm:Support",
     ],
 )

+ 30 - 10
common/bazel_working_dir.h

@@ -5,25 +5,45 @@
 #ifndef CARBON_COMMON_BAZEL_WORKING_DIR_H_
 #define CARBON_COMMON_BAZEL_WORKING_DIR_H_
 
-#include "llvm/Support/FileSystem.h"
+#include <stdlib.h>
+
+#include <filesystem>
+#include <system_error>
+
+#include "common/check.h"
+#include "common/filesystem.h"
 
 namespace Carbon {
 
-// Behave as if the working directory is where `bazel run` was invoked.
-// This should only be used in development binaries, not release.
-inline auto SetWorkingDirForBazel() -> bool {
+// Change working directory to behave as if it is where `bazel run` was invoked.
+//
+// Accepts an optional `exe_path` argument that will be adjusted to continue to
+// be valid after this adjustment.
+//
+// There is no reasonable recovery we can do if either we can't make the path
+// absolute or we can't change directory. As a consequence, this aborts if
+// either of those fail rather than propagating any error.
+inline auto SetWorkingDirForBazelRun(std::filesystem::path exe_path = {})
+    -> std::filesystem::path {
   char* build_working_dir = getenv("BUILD_WORKING_DIRECTORY");
   if (build_working_dir == nullptr) {
-    return true;
+    return exe_path;
   }
 
-  if (std::error_code err =
-          llvm::sys::fs::set_current_path(build_working_dir)) {
-    llvm::errs() << "Failed to set working directory: " << err.message();
-    return false;
+  // Adjust `exe_path` before changing directory.
+  if (!exe_path.empty()) {
+    std::error_code err;
+    exe_path = std::filesystem::absolute(exe_path, err);
+    CARBON_CHECK(!err, "Unable to make an absolute path for `{0}`: {1}",
+                 exe_path, err.message());
   }
 
-  return true;
+  auto chdir_result = Filesystem::Cwd().Chdir(build_working_dir);
+  CARBON_CHECK(chdir_result.ok(),
+               "Unable to change working directory to `{0}`: {1}",
+               build_working_dir, chdir_result.error());
+
+  return exe_path;
 }
 
 }  // namespace Carbon

+ 0 - 3
common/filesystem.cpp

@@ -688,9 +688,6 @@ auto MakeTmpDir() -> ErrorOr<RemovingDir, Error> {
       continue;
     }
     std::filesystem::path tmpdir_env = tmpdir_env_cstr;
-    if (!tmpdir_env.is_absolute()) {
-      continue;
-    }
     tmpdir_path = std::move(tmpdir_env);
     break;
   }

+ 11 - 14
common/filesystem.h

@@ -1023,25 +1023,22 @@ class Dir : public DirRef {
 class RemovingDir : public Dir {
  public:
   // Takes ownership of the open directory `d` and wraps it in a `RemovingDir`
-  // that will remove it on destruction using `abs_path`. Requires `abs_path` to
-  // be an absolute path and the desired path to remove on destruction.
+  // that will remove it on destruction using `path`. Note that for a relative
+  // `path`, the removal will re-resolve this relative to the current working
+  // directory on removal.
   //
   // Note that there is no way for the implementation to validate what directory
-  // `abs_path` refers to, that is the responsibility of the caller.
-  explicit RemovingDir(Dir d, std::filesystem::path abs_path)
-      : Dir(std::move(d)), abs_path_(std::move(abs_path)) {
-    CARBON_CHECK(abs_path_.is_absolute(), "Relative path used for removal: {0}",
-                 abs_path_);
-  }
+  // `path` refers to, that is the responsibility of the caller.
+  explicit RemovingDir(Dir d, std::filesystem::path path)
+      : Dir(std::move(d)), path_(std::move(path)) {}
 
   RemovingDir() = default;
   RemovingDir(RemovingDir&& arg) = default;
   auto operator=(RemovingDir&& rhs) -> RemovingDir& = default;
   ~RemovingDir();
 
-  auto abs_path() const [[clang::lifetimebound]]
-  -> const std::filesystem::path& {
-    return abs_path_;
+  auto path() const [[clang::lifetimebound]] -> const std::filesystem::path& {
+    return path_;
   }
 
   // Releases the directory from being removed and returns just the underlying
@@ -1054,7 +1051,7 @@ class RemovingDir : public Dir {
  private:
   friend Dir;
 
-  std::filesystem::path abs_path_;
+  std::filesystem::path path_;
 };
 
 // A named entry in a directory.
@@ -1745,7 +1742,7 @@ inline auto Dir::TakeAndRead() && -> ErrorOr<Reader, FdError> {
 }
 
 inline Dir::Dir(RemovingDir&& arg) noexcept : Dir(static_cast<Dir&&>(arg)) {
-  arg.abs_path_.clear();
+  arg.path_.clear();
 }
 
 constexpr auto Dir::Destroy() -> void {
@@ -1794,7 +1791,7 @@ inline auto RemovingDir::Remove() && -> ErrorOr<Success, PathError> {
 
   // Close the directory base object prior to removing it.
   static_cast<Dir&>(*this) = Dir();
-  return Cwd().Rmtree(abs_path_);
+  return Cwd().Rmtree(path_);
 }
 
 inline auto Dir::Iterator::operator++() -> Iterator& {

+ 11 - 11
common/filesystem_benchmark.cpp

@@ -160,7 +160,7 @@ auto BM_Access(benchmark::State& state) -> void {
       } else if constexpr (Comp == Std) {
         std::error_code ec;
         bool exists = std::filesystem::exists(
-            context.tmpdir.abs_path() / context.file_paths[i], ec);
+            context.tmpdir.path() / context.file_paths[i], ec);
         CARBON_CHECK(!ec, "{0}", ec.message());
         CARBON_CHECK(exists);
       } else {
@@ -183,7 +183,7 @@ auto BM_AccessMissing(benchmark::State& state) -> void {
       } else if constexpr (Comp == Std) {
         std::error_code ec;
         auto exists = std::filesystem::exists(
-            context.tmpdir.abs_path() / context.missing_paths[i], ec);
+            context.tmpdir.path() / context.missing_paths[i], ec);
         CARBON_CHECK(!ec, "{0}", ec.message());
         CARBON_CHECK(!exists);
       } else {
@@ -207,7 +207,7 @@ auto BM_Stat(benchmark::State& state) -> void {
       } else if constexpr (Comp == Std) {
         std::error_code ec;
         auto status = std::filesystem::status(
-            context.tmpdir.abs_path() / context.file_paths[i], ec);
+            context.tmpdir.path() / context.file_paths[i], ec);
         CARBON_CHECK(!ec, "{0}", ec.message());
         benchmark::DoNotOptimize(status.permissions());
       } else {
@@ -230,7 +230,7 @@ auto BM_StatMissing(benchmark::State& state) -> void {
       } else if constexpr (Comp == Std) {
         std::error_code ec;
         auto status = std::filesystem::status(
-            context.tmpdir.abs_path() / context.missing_paths[i], ec);
+            context.tmpdir.path() / context.missing_paths[i], ec);
         CARBON_CHECK(ec.value() == ENOENT, "{0}", ec.message());
       } else {
         static_assert(false, "Invalid benchmark comparable");
@@ -250,7 +250,7 @@ auto BM_OpenMissing(benchmark::State& state) -> void {
         auto f = context.tmpdir.OpenReadOnly(context.missing_paths[i]);
         CARBON_CHECK(f.error().no_entity());
       } else if constexpr (Comp == Std) {
-        std::ifstream f(context.tmpdir.abs_path() / context.missing_paths[i]);
+        std::ifstream f(context.tmpdir.path() / context.missing_paths[i]);
         CARBON_CHECK(!f.is_open());
       } else {
         static_assert(false, "Invalid benchmark comparable");
@@ -272,7 +272,7 @@ auto BM_OpenClose(benchmark::State& state) -> void {
         auto close_result = std::move(*f).Close();
         CARBON_CHECK(close_result.ok(), "{0}", close_result.error());
       } else if constexpr (Comp == Std) {
-        std::ifstream f(context.tmpdir.abs_path() / context.file_paths[i]);
+        std::ifstream f(context.tmpdir.path() / context.file_paths[i]);
         CARBON_CHECK(f.is_open());
       } else {
         static_assert(false, "Invalid benchmark comparable");
@@ -300,7 +300,7 @@ auto BM_CreateRemove(benchmark::State& state) -> void {
         auto remove_result = context.tmpdir.Unlink(context.missing_paths[i]);
         CARBON_CHECK(remove_result.ok(), "{0}", remove_result.error());
       } else if constexpr (Comp == Std) {
-        auto path = context.tmpdir.abs_path() / context.missing_paths[i];
+        auto path = context.tmpdir.path() / context.missing_paths[i];
         // Create the file by opening it.
         std::ofstream f(path);
         CARBON_CHECK(f.is_open());
@@ -343,7 +343,7 @@ auto BM_Read(benchmark::State& state) -> void {
         CARBON_CHECK(read_result.ok(), "{0}", read_result.error());
         benchmark::DoNotOptimize(*read_result);
       } else if constexpr (Comp == Std) {
-        std::ifstream f(context.tmpdir.abs_path() / context.file_paths[i],
+        std::ifstream f(context.tmpdir.path() / context.file_paths[i],
                         std::ios::binary);
         CARBON_CHECK(f.is_open());
         // This may be a somewhat surprising implementation, but benchmarking
@@ -379,7 +379,7 @@ auto BM_Write(benchmark::State& state) -> void {
             context.tmpdir.WriteFileFromString(context.file_paths[i], content);
         CARBON_CHECK(write_result.ok(), "{0}", write_result.error());
       } else if constexpr (Comp == Std) {
-        std::ofstream f(context.tmpdir.abs_path() / context.file_paths[i],
+        std::ofstream f(context.tmpdir.path() / context.file_paths[i],
                         std::ios::binary | std::ios::trunc);
         CARBON_CHECK(f.is_open());
         f.write(content.data(), content.length());
@@ -417,7 +417,7 @@ auto BM_Rmtree(benchmark::State& state) -> void {
         CARBON_CHECK(rmdir_result.ok(), "{0}", rmdir_result.error());
       } else if constexpr (Comp == Std) {
         std::error_code ec;
-        std::filesystem::remove_all(context.tmpdir.abs_path() / tree, ec);
+        std::filesystem::remove_all(context.tmpdir.path() / tree, ec);
         CARBON_CHECK(!ec, "{0}", ec.message());
       } else {
         static_assert(false, "Invalid benchmark comparable");
@@ -492,7 +492,7 @@ auto BM_CreateDirectories(benchmark::State& state) -> void {
         auto close_result = std::move(*f).Close();
         CARBON_CHECK(close_result.ok(), "{0}", close_result.error());
       } else if constexpr (Comp == Std) {
-        std::filesystem::path path = context.tmpdir.abs_path() / paths[i];
+        std::filesystem::path path = context.tmpdir.path() / paths[i];
         std::error_code ec;
         std::filesystem::create_directories(path, ec);
         CARBON_CHECK(!ec, "{0}", ec.message());

+ 1 - 1
common/filesystem_test.cpp

@@ -37,7 +37,7 @@ class FilesystemTest : public ::testing::Test {
     CARBON_CHECK(result.ok(), "{0}", result.error());
   }
 
-  auto path() const -> const std::filesystem::path& { return dir_.abs_path(); }
+  auto path() const -> const std::filesystem::path& { return dir_.path(); }
 
   // The test's temp directory, deleted on destruction.
   RemovingDir dir_;

+ 1 - 1
testing/base/source_gen_main.cpp

@@ -110,7 +110,7 @@ auto main(int argc, char** argv) -> int {
   // Do LLVM's initialization first, this will also transform UTF-16 to UTF-8.
   Carbon::InitLLVM init_llvm(argc, argv);
 
-  Carbon::SetWorkingDirForBazel();
+  Carbon::SetWorkingDirForBazelRun();
 
   llvm::SmallVector<llvm::StringRef> args(argv + 1, argv + argc);
   bool success = Carbon::Testing::Run(args);

+ 1 - 7
toolchain/base/install_paths.cpp

@@ -132,8 +132,7 @@ auto InstallPaths::MakeFromFile(std::filesystem::path file_path)
   // FHS-like install prefix. We remove the filename and walk up to find the
   // expected install prefix.
   std::error_code ec;
-  InstallPaths paths(std::filesystem::absolute(
-      std::move(file_path).remove_filename() / "../..", ec));
+  InstallPaths paths(std::move(file_path).remove_filename() / "../..");
   if (ec) {
     paths.SetError(ec.message());
     return paths;
@@ -159,11 +158,6 @@ auto InstallPaths::SetError(llvm::Twine message) -> void {
 }
 
 auto InstallPaths::CheckMarkerFile() -> void {
-  if (!prefix_.is_absolute()) {
-    SetError(llvm::Twine("Not an absolute path: ") + prefix_.native());
-    return;
-  }
-
   auto access_result = prefix_dir_.Access(MarkerPath.str());
   if (!access_result.ok()) {
     SetError(access_result.error().ToString());

+ 0 - 2
toolchain/driver/clang_runtimes.cpp

@@ -390,8 +390,6 @@ auto ClangArchiveRuntimesBuilder<Component>::CollectCflags()
   }
 
   for (const auto& include_path : include_paths_) {
-    CARBON_CHECK(include_path.is_absolute(),
-                 "Unexpected relative include path: {0}", include_path);
     cflags.append({"-I", include_path.native()});
   }
   return cflags;

+ 5 - 24
toolchain/driver/runtimes_cache.cpp

@@ -28,34 +28,15 @@
 
 namespace Carbon {
 
-static auto MakeAbsolute(std::filesystem::path path)
-    -> ErrorOr<std::filesystem::path> {
-  if (!path.is_absolute()) {
-    std::error_code ec;
-    path = std::filesystem::absolute(path, ec);
-    if (ec) {
-      return Error(llvm::formatv("Unable to compute an absolute path: {0}",
-                                 ec.message()));
-    }
-  }
-  return std::move(path);
-}
-
 auto Runtimes::OpenExisting(std::filesystem::path path,
                             llvm::raw_ostream* vlog_stream)
     -> ErrorOr<Runtimes> {
-  CARBON_ASSIGN_OR_RETURN(path, MakeAbsolute(std::move(path)));
-
-  CARBON_ASSIGN_OR_RETURN(
-      Filesystem::Dir dir,
-      Filesystem::Cwd().OpenDir(path, Filesystem::OpenExisting));
+  CARBON_ASSIGN_OR_RETURN(Filesystem::Dir dir, Filesystem::Cwd().OpenDir(path));
   return Runtimes(std::move(path), std::move(dir), {}, {}, vlog_stream);
 }
 
 auto Runtimes::Make(std::filesystem::path path, llvm::raw_ostream* vlog_stream)
     -> ErrorOr<Runtimes> {
-  CARBON_ASSIGN_OR_RETURN(path, MakeAbsolute(std::move(path)));
-
   CARBON_ASSIGN_OR_RETURN(Filesystem::Dir dir,
                           Filesystem::Cwd().CreateDirectories(path));
   return Runtimes(std::move(path), std::move(dir), {}, {}, vlog_stream);
@@ -183,7 +164,7 @@ auto Runtimes::Cache::FindXdgCachePath()
 
 auto Runtimes::Cache::InitTmpSystemCache() -> ErrorOr<Success> {
   CARBON_ASSIGN_OR_RETURN(dir_owner_, Filesystem::MakeTmpDir());
-  path_ = std::get<Filesystem::RemovingDir>(dir_owner_).abs_path();
+  path_ = std::get<Filesystem::RemovingDir>(dir_owner_).path();
   dir_ = std::get<Filesystem::RemovingDir>(dir_owner_);
   CARBON_VLOG("Using temporary cache: {0}", path_);
   return Success();
@@ -467,12 +448,12 @@ auto Runtimes::Builder::Commit() && -> ErrorOr<std::filesystem::path> {
 
   // First, try to do the atomic commit of the built runtimes into the final
   // location.
-  CARBON_CHECK(dir_.abs_path().parent_path() == runtimes_->base_path(),
+  CARBON_CHECK(dir_.path().parent_path() == runtimes_->base_path(),
                "Building a temporary directory '{0}' that is not in the "
                "runtimes tree '{1}'",
-               dir_.abs_path(), runtimes_->base_path());
+               dir_.path(), runtimes_->base_path());
   auto rename_result = runtimes_->base_dir().Rename(
-      dir_.abs_path().filename(), runtimes_->base_dir(), dest_);
+      dir_.path().filename(), runtimes_->base_dir(), dest_);
   // If the rename was successful, then we don't need to remove anything so
   // release that state.
   if (rename_result.ok()) {

+ 2 - 5
toolchain/driver/runtimes_cache.h

@@ -176,10 +176,7 @@ class Runtimes {
         base_dir_(std::move(base_dir)),
         lock_file_(std::move(lock_file)),
         flock_(std::move(flock)),
-        vlog_stream_(vlog_stream) {
-    CARBON_CHECK(base_path_.is_absolute(),
-                 "The base path must be absolute: {0}", base_path_);
-  }
+        vlog_stream_(vlog_stream) {}
 
   // Implementation of building the Clang resource directory. This exposes the
   // deadline and poll interval to allow testing with artificial values.
@@ -401,7 +398,7 @@ class Runtimes::Builder : public Printable<Builder> {
   // The build's staging directory.
   auto dir() const -> Filesystem::DirRef { return dir_; }
   // The build's staging directory path.
-  auto path() const -> const std::filesystem::path& { return dir_.abs_path(); }
+  auto path() const -> const std::filesystem::path& { return dir_.path(); }
 
   // Commits the new runtime to the cache.
   //

+ 10 - 10
toolchain/driver/runtimes_cache_test.cpp

@@ -74,7 +74,7 @@ using ::testing::VariantWith;
 class RuntimesCacheTest : public ::testing::Test {
  public:
   RuntimesCacheTest()
-      : cache_(*Runtimes::Cache::MakeCustom(install_, tmp_dir_.abs_path())) {}
+      : cache_(*Runtimes::Cache::MakeCustom(install_, tmp_dir_.path())) {}
 
   auto LookupNRuntimes(int n) -> llvm::SmallVector<Runtimes> {
     llvm::SmallVector<Runtimes> runtimes;
@@ -98,13 +98,13 @@ TEST_F(RuntimesCacheTest, BuildSystemCache) {
   bad_install_dir.WriteFileFromString("carbon_install.txt", "no digest")
       .Check();
   InstallPaths bad_install =
-      InstallPaths::Make((tmp_dir_.abs_path() / "bad_install").native());
+      InstallPaths::Make((tmp_dir_.path() / "bad_install").native());
 
   // Create directories to use in various environment variables.
   auto xdg_dir = *tmp_dir_.CreateDirectories("xdg_cache_home");
-  std::filesystem::path xdg_path = tmp_dir_.abs_path() / "xdg_cache_home";
+  std::filesystem::path xdg_path = tmp_dir_.path() / "xdg_cache_home";
   auto test_home = *tmp_dir_.CreateDirectories("test_home");
-  std::filesystem::path home_path = tmp_dir_.abs_path() / "test_home";
+  std::filesystem::path home_path = tmp_dir_.path() / "test_home";
   auto home_cache_dir = *test_home.CreateDirectories(".cache");
   std::filesystem::path home_cache_path = home_path / ".cache";
 
@@ -276,8 +276,8 @@ TEST_F(RuntimesCacheTest, DifferentKeys) {
       .Check();
   custom_install_dir.WriteFileFromString("install_digest.txt", "abcd").Check();
   InstallPaths install2 =
-      InstallPaths::Make((tmp_dir_.abs_path() / "custom_install").native());
-  auto cache2 = *Runtimes::Cache::MakeCustom(install2, tmp_dir_.abs_path());
+      InstallPaths::Make((tmp_dir_.path() / "custom_install").native());
+  auto cache2 = *Runtimes::Cache::MakeCustom(install2, tmp_dir_.path());
   auto runtimes2 = *cache2.Lookup({.target = target});
 
   // The parent paths of these runtimes should be the same.
@@ -295,7 +295,7 @@ TEST_F(RuntimesCacheTest, ConcurrentBuilds) {
 
   // Build a second cache and runtimes pointing at the same directory and target
   // to simulate concurrent processes.
-  auto cache2 = *Runtimes::Cache::MakeCustom(install_, tmp_dir_.abs_path());
+  auto cache2 = *Runtimes::Cache::MakeCustom(install_, tmp_dir_.path());
   auto runtimes2 = *cache2.Lookup({.target = target});
 
   // Start the first build, this will lock the directory.
@@ -378,7 +378,7 @@ TEST_F(RuntimesCacheTest, ConcurrentBuildsWithFailedLocking) {
 
   // Build a second cache and runtimes pointing at the same directory and target
   // to simulate concurrent processes.
-  auto cache2 = *Runtimes::Cache::MakeCustom(install_, tmp_dir_.abs_path());
+  auto cache2 = *Runtimes::Cache::MakeCustom(install_, tmp_dir_.path());
   auto runtimes2 = *cache2.Lookup({.target = target});
 
   // Start the first build, this will lock the directory.
@@ -476,7 +476,7 @@ TEST_F(RuntimesCacheTest, ConcurrentBuildsLockTimeout) {
 
   // Build a second cache and runtimes pointing at the same directory and target
   // to simulate concurrent processes.
-  auto cache2 = *Runtimes::Cache::MakeCustom(install_, tmp_dir_.abs_path());
+  auto cache2 = *Runtimes::Cache::MakeCustom(install_, tmp_dir_.path());
   auto runtimes2 = *cache2.Lookup({.target = target});
 
   // Start the first build, this will lock the directory.
@@ -549,7 +549,7 @@ TEST_F(RuntimesCacheTest, Lookup) {
 
 TEST_F(RuntimesCacheTest, LookupFailsIfCannotCreateDir) {
   // Create a read-only directory with the cache in it to cause failures.
-  std::filesystem::path ro_cache_path = tmp_dir_.abs_path() / "ro_cache";
+  std::filesystem::path ro_cache_path = tmp_dir_.path() / "ro_cache";
   tmp_dir_.CreateDirectories("ro_cache", /*creation_mode=*/0500).Check();
   auto ro_cache = *Runtimes::Cache::MakeCustom(install_, ro_cache_path);
 

+ 1 - 1
toolchain/install/busybox_info_test.cpp

@@ -26,7 +26,7 @@ using ::testing::Eq;
 class BusyboxInfoTest : public ::testing::Test {
  public:
   explicit BusyboxInfoTest()
-      : dir_(std::move(*Filesystem::MakeTmpDir())), path_(dir_.abs_path()) {
+      : dir_(std::move(*Filesystem::MakeTmpDir())), path_(dir_.path()) {
     // Most tests need the running binary for `MakeBusyboxFile`.
     static int static_for_main_addr;
     running_binary_ = llvm::sys::fs::getMainExecutable("busybox_info_test",

+ 4 - 5
toolchain/install/busybox_main.cpp

@@ -27,11 +27,10 @@ static auto Main(int argc, char** argv) -> ErrorOr<int> {
   // Start by resolving any symlinks.
   CARBON_ASSIGN_OR_RETURN(auto busybox_info, GetBusyboxInfo(argv[0]));
 
-  auto fs = llvm::vfs::getRealFileSystem();
+  std::filesystem::path exe_path = busybox_info.bin_path.string();
+  exe_path = SetWorkingDirForBazelRun(exe_path);
 
-  // Resolve paths before calling SetWorkingDirForBazel.
-  std::string exe_path = busybox_info.bin_path.string();
-  const auto install_paths = InstallPaths::MakeExeRelative(exe_path);
+  const auto install_paths = InstallPaths::MakeExeRelative(exe_path.native());
   if (install_paths.error()) {
     return Error(*install_paths.error());
   }
@@ -44,7 +43,7 @@ static auto Main(int argc, char** argv) -> ErrorOr<int> {
       (install_paths.llvm_install_bin().native() + "llvm-symbolizer").c_str(),
       /*overwrite=*/0);
 
-  SetWorkingDirForBazel();
+  auto fs = llvm::vfs::getRealFileSystem();
 
   llvm::SmallVector<llvm::StringRef> args;
   args.reserve(argc + 1);

+ 1 - 1
toolchain/install/make_installation_digest.cpp

@@ -53,7 +53,7 @@ class DigestProgram {
 
 auto DigestProgram::Run(int argc, char** argv) -> ErrorOr<int> {
   InitLLVM init_llvm(argc, argv);
-  SetWorkingDirForBazel();
+  SetWorkingDirForBazelRun();
   llvm::SHA256 sha256;
 
   // If the first argument is `--verbose`, enable verbose logging.