Skip to content

Commit 13da9a1

Browse files
aaronskycopybara-github
authored andcommitted
Move default output root on macOS to $HOME/Library/Caches
Fixes #25260 Implements the request made [here](#25205 (comment)) and moves the default output root on macOS from `/private/var/tmp` to `$HOME/Library/Caches`. May constitute an incompatible change, though on a cursory glance I didn't see any precedent for incompatible startup options in source. Closes #25262. PiperOrigin-RevId: 840604399 Change-Id: I391b805b2c8e99d3ffe44a76e916d1c9839225e5
1 parent 4cfe9b8 commit 13da9a1

File tree

4 files changed

+76
-60
lines changed

4 files changed

+76
-60
lines changed

docs/remote/output-directories.mdx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,16 @@ The solution that's currently implemented:
2929
subdirectory thereof. In other words, Bazel must be invoked from inside a
3030
[repository](../external/overview#repository). Otherwise, an error is
3131
reported.
32-
* The _outputRoot_ directory defaults to `~/.cache/bazel` on Linux,
33-
`/private/var/tmp` on macOS, and on Windows it defaults to `%HOME%` if
34-
set, else `%USERPROFILE%` if set, else the result of calling
35-
`SHGetKnownFolderPath()` with the `FOLDERID_Profile` flag set. If the
36-
environment variable `$XDG_CACHE_HOME` is set on either Linux or
37-
macOS, the value `${XDG_CACHE_HOME}/bazel` will override the default.
38-
If the environment variable `$TEST_TMPDIR` is set, as in a test of Bazel
39-
itself, then that value overrides any defaults.
32+
* The _outputRoot_ directory defaults to ~/.cache/bazel on Linux,
33+
`~/Library/Caches/bazel` on macOS (when using Bazel 9 and newer),
34+
and on Windows it defaults to `%HOME%` if set, else `%USERPROFILE%`
35+
if set, else the result of calling `SHGetKnownFolderPath()` with the
36+
`FOLDERID_Profile` flag set. If the environment variable `$XDG_CACHE_HOME`
37+
is set on either Linux or macOS, the value `${XDG_CACHE_HOME}/bazel` will
38+
override the default. If the environment variable `$TEST_TMPDIR` is set,
39+
as in a test of Bazel itself, then that value overrides any defaults.
40+
* Note that Bazel 8.x and earlier on macOS used `/private/var/tmp` as _outputRoot_,
41+
and ignored `$XDG_CACHE_HOME`.
4042
* The Bazel user's build state is located beneath `outputRoot/_bazel_$USER`.
4143
This is called the _outputUserRoot_ directory.
4244
* Beneath the `outputUserRoot` directory there is an `install` directory, and in

site/en/remote/output-directories.md

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,25 +26,27 @@ Requirements for an output directory layout:
2626

2727
The solution that's currently implemented:
2828

29-
* Bazel must be invoked from a directory containing a repo boundary file, or a
30-
subdirectory thereof. In other words, Bazel must be invoked from inside a
29+
* Bazel must be invoked from a directory containing a repository boundary file,
30+
or a subdirectory thereof. In other words, Bazel must be invoked from inside a
3131
[repository](../external/overview#repository). Otherwise, an error is
3232
reported.
33-
* The _outputRoot_ directory defaults to `~/.cache/bazel` on Linux,
34-
`/private/var/tmp` on macOS, and on Windows it defaults to `%HOME%` if
35-
set, else `%USERPROFILE%` if set, else the result of calling
36-
`SHGetKnownFolderPath()` with the `FOLDERID_Profile` flag set. If the
37-
environment variable `$XDG_CACHE_HOME` is set on either Linux or
38-
macOS, the value `${XDG_CACHE_HOME}/bazel` will override the default.
39-
If the environment variable `$TEST_TMPDIR` is set, as in a test of Bazel
40-
itself, then that value overrides any defaults.
33+
* The _outputRoot_ directory defaults to ~/.cache/bazel on Linux,
34+
`~/Library/Caches/bazel` on macOS (when using Bazel 9 and newer),
35+
and on Windows it defaults to `%HOME%` if set, else `%USERPROFILE%`
36+
if set, else the result of calling `SHGetKnownFolderPath()` with the
37+
`FOLDERID_Profile` flag set. If the environment variable `$XDG_CACHE_HOME`
38+
is set on either Linux or macOS, the value `${XDG_CACHE_HOME}/bazel` will
39+
override the default. If the environment variable `$TEST_TMPDIR` is set,
40+
as in a test of Bazel itself, then that value overrides any defaults.
41+
* Note that Bazel 8.x and earlier on macOS used `/private/var/tmp` as _outputR
42+
oot_,and ignored `$XDG_CACHE_HOME`.
4143
* The Bazel user's build state is located beneath `outputRoot/_bazel_$USER`.
4244
This is called the _outputUserRoot_ directory.
4345
* Beneath the `outputUserRoot` directory there is an `install` directory, and in
4446
it is an `installBase` directory whose name is the MD5 hash of the Bazel
4547
installation manifest.
4648
* Beneath the `outputUserRoot` directory, an `outputBase` directory
47-
is also created whose name is the MD5 hash of the path name of the workspace
49+
is also created whose name is the MD5 hash of the path of the workspace
4850
root. So, for example, if Bazel is running in the workspace root
4951
`/home/user/src/my-project` (or in a directory symlinked to that one), then
5052
an output base directory is created called:

src/main/cpp/blaze_util_darwin.cc

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
#include "src/main/cpp/blaze_util_platform.h"
16-
15+
#include <CoreFoundation/CoreFoundation.h>
1716
#include <libproc.h>
1817
#include <pthread/spawn.h>
18+
#include <pwd.h>
1919
#include <signal.h>
2020
#include <spawn.h>
2121
#include <stdlib.h>
@@ -28,13 +28,12 @@
2828
#include <time.h>
2929
#include <unistd.h>
3030

31-
#include <CoreFoundation/CoreFoundation.h>
32-
3331
#include <cerrno>
3432
#include <cstdio>
3533
#include <cstring>
3634

3735
#include "src/main/cpp/blaze_util.h"
36+
#include "src/main/cpp/blaze_util_platform.h"
3837
#include "src/main/cpp/startup_options.h"
3938
#include "src/main/cpp/util/errors.h"
4039
#include "src/main/cpp/util/exit_code.h"
@@ -96,24 +95,42 @@ static string DescriptionFromCFError(CFErrorRef cf_err) {
9695
return UTF8StringFromCFStringRef(cf_err_string);
9796
}
9897

98+
// ${XDG_CACHE_HOME}/bazel, falling back to ~/Library/Caches/bazel if
99+
// ${XDG_CACHE_HOME} is empty.
100+
//
101+
// Historically, Bazel 8.x and earlier used /private/var/tmp by default, due to
102+
// path length limitations stemming from use of Unix domain sockets. However,
103+
// these limitations are no longer relevant as we do not create Unix domain
104+
// sockets under the output base. The standard location for application caches
105+
// on macOS is $HOME/Library/Caches.
106+
//
107+
// See also:
108+
// https://stackoverflow.com/questions/3373948/equivalents-of-xdg-config-home-and-xdg-data-home-on-mac-os-x
99109
string GetCacheDir() {
100-
// On macOS, the standard location for application caches is
101-
// $HOME/Library/Caches. Bazel historically has not used this location, and
102-
// instead has used /var/tmp, due to Unix domain socket path length
103-
// limitations. These limitations are no longer relevant as we no longer
104-
// create Unix domain sockets under the output base.
105-
//
106-
// However, respecting $XDG_CACHE_HOME is still useful as it allows users to
107-
// easily override the cache directory, and is respected by many Linux derived
108-
// tools.
109-
//
110-
// See also:
111-
// https://stackoverflow.com/questions/3373948/equivalents-of-xdg-config-home-and-xdg-data-home-on-mac-os-x
112110
string xdg_cache_home = GetPathEnv("XDG_CACHE_HOME");
113-
if (!xdg_cache_home.empty()) {
114-
return blaze_util::JoinPath(xdg_cache_home, "bazel");
111+
if (xdg_cache_home.empty()) {
112+
string home = GetHomeDir(); // via $HOME env variable
113+
if (home.empty()) {
114+
// Fall back to home dir from password database
115+
struct passwd pwbuf;
116+
struct passwd* pw = nullptr;
117+
uid_t uid = getuid();
118+
int strbufsize;
119+
if ((strbufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) == -1) {
120+
return "/var/tmp";
121+
}
122+
string strbuf(strbufsize, 0);
123+
int r = getpwuid_r(uid, &pwbuf, &strbuf[0], strbufsize, &pw);
124+
if (r == 0 && pw != nullptr) {
125+
home = pw->pw_dir;
126+
} else {
127+
return "/var/tmp";
128+
}
129+
}
130+
xdg_cache_home = blaze_util::JoinPath(home, "Library/Caches");
115131
}
116-
return "/var/tmp";
132+
133+
return blaze_util::JoinPath(xdg_cache_home, "bazel");
117134
}
118135

119136
void WarnFilesystemType(const blaze_util::Path &output_base) {

src/test/cpp/bazel_startup_options_test.cc

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,16 @@ TEST_F(BazelStartupOptionsTest, EmptyFlagsAreInvalid) {
8484
EXPECT_FALSE(startup_options_->IsUnary("--"));
8585
}
8686

87-
#ifdef __linux
88-
TEST_F(BazelStartupOptionsTest, UpdateConfigurationOnLinuxWithHome) {
87+
#if defined(__linux) || defined(__APPLE__)
88+
TEST_F(BazelStartupOptionsTest, UpdateConfigurationOnLinuxOrDarwinWithHome) {
8989
SetEnv("USER", "gandalf");
9090
SetEnv("HOME", "/nonexistent/home");
9191
UnsetEnv("TEST_TMPDIR");
9292
UnsetEnv("XDG_CACHE_HOME");
9393
ReinitStartupOptions();
9494
UpdateConfiguration();
9595

96+
#ifdef __linux
9697
ASSERT_EQ(blaze_util::Path("/nonexistent/home/.cache/bazel/_bazel_gandalf"),
9798
startup_options_->output_user_root);
9899
ASSERT_EQ(
@@ -102,28 +103,20 @@ TEST_F(BazelStartupOptionsTest, UpdateConfigurationOnLinuxWithHome) {
102103
ASSERT_EQ(blaze_util::Path("/nonexistent/home/.cache/bazel/_bazel_gandalf/"
103104
"1629dee48cc4e53161f9b2be8614e062"),
104105
startup_options_->output_base);
105-
}
106-
#endif // __linux
107-
108-
#ifdef __APPLE__
109-
TEST_F(BazelStartupOptionsTest, UpdateConfigurationOnDarwin) {
110-
SetEnv("USER", "gandalf");
111-
SetEnv("HOME", "/nonexistent/home");
112-
UnsetEnv("TEST_TMPDIR");
113-
ReinitStartupOptions();
114-
UpdateConfiguration();
115-
116-
ASSERT_EQ(blaze_util::Path("/var/tmp/_bazel_gandalf"),
117-
startup_options_->output_user_root);
118-
ASSERT_EQ(blaze_util::Path("/var/tmp/_bazel_gandalf/install/deadbeef"),
106+
#elif defined(__APPLE__)
107+
ASSERT_EQ(
108+
blaze_util::Path("/nonexistent/home/Library/Caches/bazel/_bazel_gandalf"),
109+
startup_options_->output_user_root);
110+
ASSERT_EQ(blaze_util::Path("/nonexistent/home/Library/Caches/bazel/"
111+
"_bazel_gandalf/install/deadbeef"),
119112
startup_options_->install_base);
120-
ASSERT_EQ(blaze_util::Path("/var/tmp/_bazel_gandalf/"
121-
"1629dee48cc4e53161f9b2be8614e062"),
122-
startup_options_->output_base);
113+
ASSERT_EQ(
114+
blaze_util::Path("/nonexistent/home/Library/Caches/bazel/_bazel_gandalf/"
115+
"1629dee48cc4e53161f9b2be8614e062"),
116+
startup_options_->output_base);
117+
#endif
123118
}
124-
#endif // __APPLE__
125119

126-
#if defined(__linux) || defined(__APPLE__)
127120
TEST_F(BazelStartupOptionsTest,
128121
UpdateConfigurationOnLinuxOrDarwinWithTestTmpdir) {
129122
SetEnv("USER", "gandalf");
@@ -193,7 +186,9 @@ TEST_F(BazelStartupOptionsTest,
193186
"/~/home$(echo baz)/.cache/bazel/_bazel_gandalf"),
194187
startup_options_->output_user_root);
195188
#elif defined(__APPLE__)
196-
ASSERT_EQ(blaze_util::Path("/var/tmp/_bazel_gandalf"),
189+
ASSERT_EQ(blaze_util::Path(
190+
blaze_util::GetCwd() +
191+
"/~/home$(echo baz)/Library/Caches/bazel/_bazel_gandalf"),
197192
startup_options_->output_user_root);
198193
#endif
199194
}

0 commit comments

Comments
 (0)