Skip to content

Commit

Permalink
Respect $XDG_CACHE_HOME if available for Bazel's output root on Linux…
Browse files Browse the repository at this point in the history
… and BSD

It may well be that $HOME is on a read-only mount. In this case, it is the
convention in the Linux and BSD world that $XDG_CACHE_HOME points to an
appropriate writable location.

Fixes #16937

RELNOTES: Bazel on Linux and BSD now respects the XDG_CACHE_HOME environment
variable instead of assuming that ~/.cache/bazel is writable.
PiperOrigin-RevId: 614772057
Change-Id: I6377d7a90fb929843d18e82f5ed3d0adc55ac5c6
  • Loading branch information
tetromino authored and copybara-github committed Mar 11, 2024
1 parent 63be83f commit 05ae91f
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 29 deletions.
7 changes: 4 additions & 3 deletions site/en/remote/output-directories.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ The solution that's currently implemented:
subdirectory thereof. In other words, Bazel must be invoked from inside a
[repository](../external/overview#repository). Otherwise, an error is
reported.
* The _outputRoot_ directory defaults to `~/.cache/bazel` on Linux,
`/private/var/tmp` on macOS, and on Windows it defaults to `%HOME%` if set,
else `%USERPROFILE%` if set, else the result of calling
* The _outputRoot_ directory defaults to `${XDG_CACHE_HOME}/bazel` (or
`~/.cache/bazel`, if the `XDG_CACHE_HOME` environment variable is not set) on
Linux, `/private/var/tmp` on macOS, and on Windows it defaults to `%HOME%` if
set, else `%USERPROFILE%` if set, else the result of calling
`SHGetKnownFolderPath()` with the `FOLDERID_Profile` flag set. If the
environment variable `$TEST_TMPDIR` is set, as in a test of Bazel itself,
then that value overrides the default.
Expand Down
25 changes: 16 additions & 9 deletions src/main/cpp/blaze_util_bsd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,24 @@ namespace blaze {
using blaze_util::GetLastErrorString;
using std::string;

// ${XDG_CACHE_HOME}/bazel, a.k.a. ~/.cache/bazel by default (which is the
// fallback when XDG_CACHE_HOME is not set)
string GetOutputRoot() {
char buf[2048];
struct passwd pwbuf;
struct passwd *pw = nullptr;
int uid = getuid();
int r = getpwuid_r(uid, &pwbuf, buf, 2048, &pw);
if (r == 0 && pw != nullptr) {
return blaze_util::JoinPath(pw->pw_dir, ".cache/bazel");
} else {
return "/tmp";
string xdg_cache_home = GetPathEnv("XDG_CACHE_HOME");
if (xdg_cache_home.empty()) {
char buf[2048];
struct passwd pwbuf;
struct passwd *pw = nullptr;
int uid = getuid();
int r = getpwuid_r(uid, &pwbuf, buf, 2048, &pw);
if (r == 0 && pw != nullptr) {
xdg_cache_home = blaze_util::JoinPath(pw->pw_dir, ".cache");
} else {
return "/tmp";
}
}

return blaze_util::JoinPath(xdg_cache_home, "bazel");
}

void WarnFilesystemType(const blaze_util::Path &output_base) {
Expand Down
36 changes: 19 additions & 17 deletions src/main/cpp/blaze_util_linux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,27 +43,29 @@ using blaze_util::GetLastErrorString;
using std::string;
using std::vector;

// ${XDG_CACHE_HOME}/bazel, a.k.a. ~/.cache/bazel by default (which is the
// fallback when XDG_CACHE_HOME is not set)
string GetOutputRoot() {
string base;
string home = GetHomeDir();
if (!home.empty()) {
base = home;
} else {
char buf[2048];
struct passwd pwbuf;
struct passwd *pw = nullptr;
int uid = getuid();
int r = getpwuid_r(uid, &pwbuf, buf, 2048, &pw);
if (r == 0 && pw != nullptr) {
base = pw->pw_dir;
string xdg_cache_home = GetPathEnv("XDG_CACHE_HOME");
if (xdg_cache_home.empty()) {
string home = GetHomeDir(); // via $HOME env variable
if (home.empty()) {
// Fall back to home dir from password database
char buf[2048];
struct passwd pwbuf;
struct passwd *pw = nullptr;
int uid = getuid();
int r = getpwuid_r(uid, &pwbuf, buf, 2048, &pw);
if (r == 0 && pw != nullptr) {
home = pw->pw_dir;
} else {
return "/tmp";
}
}
xdg_cache_home = blaze_util::JoinPath(home, ".cache");
}

if (!base.empty()) {
return blaze_util::JoinPath(base, ".cache/bazel");
}

return "/tmp";
return blaze_util::JoinPath(xdg_cache_home, "bazel");
}

void WarnFilesystemType(const blaze_util::Path &output_base) {
Expand Down
12 changes: 12 additions & 0 deletions src/test/cpp/startup_options_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,27 @@ TEST_F(StartupOptionsTest, JavaLoggingOptions) {
#ifdef __linux
TEST_F(StartupOptionsTest, OutputRootPreferTestTmpdirIfSet) {
SetEnv("HOME", "/nonexistent/home");
SetEnv("XDG_CACHE_HOME", "/nonexistent/cache");
SetEnv("TEST_TMPDIR", "/nonexistent/tmpdir");
ReinitStartupOptions();

ASSERT_EQ("/nonexistent/tmpdir", startup_options_->output_root);
}

TEST_F(StartupOptionsTest,
OutputRootPreferXdgCacheHomeIfSetAndTestTmpdirUnset) {
SetEnv("HOME", "/nonexistent/home");
SetEnv("XDG_CACHE_HOME", "/nonexistent/cache");
UnsetEnv("TEST_TMPDIR");
ReinitStartupOptions();

ASSERT_EQ("/nonexistent/cache/bazel", startup_options_->output_root);
}

TEST_F(StartupOptionsTest, OutputRootUseHomeDirectory) {
SetEnv("HOME", "/nonexistent/home");
UnsetEnv("TEST_TMPDIR");
UnsetEnv("XDG_CACHE_HOME");
ReinitStartupOptions();

ASSERT_EQ("/nonexistent/home/.cache/bazel", startup_options_->output_root);
Expand Down

0 comments on commit 05ae91f

Please sign in to comment.