Make the system bazelrc configurable.
The master bazelrc is now defined by preprocessor macro at (Bazel's) compile time. The default is still /etc/bazel.bazelrc for most platforms, but windows now has a %ProgramData% relative default value as well. Users wishing to change this default when building Bazel for a new platform should edit BAZEL_SYSTEM_BAZELRC_PATH in src/main/cpp/BUILD.
Part of https://github.com/bazelbuild/bazel/issues/4502, relevant to the duplicate issue #4809.
TESTED: default settings were tested manually, since they cannot be tested in a sandbox
RELNOTES: Windows default system bazelrc is read from the user's ProgramData if present.
PiperOrigin-RevId: 201423446
diff --git a/src/main/cpp/BUILD b/src/main/cpp/BUILD
index 73bbf5d..f6b3110 100644
--- a/src/main/cpp/BUILD
+++ b/src/main/cpp/BUILD
@@ -122,6 +122,20 @@
"option_processor.h",
"option_processor-internal.h",
],
+ # The system bazelrc can be voided by setting BAZEL_SYSTEM_BAZELRC_PATH to
+ # /dev/null.
+ copts = select({
+ # We need to escape for multiple levels, here, this becomes
+ # /DBAZEL_SYSTEM_BAZELRC_PATH="%%ProgramData%%/bazel.bazelrc"',
+ # and the double % get reduced down to 1 by the compiler. A forward
+ # slash is used because \b is a special character, backspace.
+ "//src/conditions:windows": [
+ "/DBAZEL_SYSTEM_BAZELRC_PATH#\\\"%%ProgramData%%/bazel.bazelrc\\\"",
+ ],
+ "//conditions:default": [
+ "-DBAZEL_SYSTEM_BAZELRC_PATH=\\\"/etc/bazel.bazelrc\\\"",
+ ],
+ }),
visibility = [
"//src:__pkg__",
"//src/test/cpp:__pkg__",
diff --git a/src/main/cpp/blaze_util_platform.h b/src/main/cpp/blaze_util_platform.h
index 078e271..29596df 100644
--- a/src/main/cpp/blaze_util_platform.h
+++ b/src/main/cpp/blaze_util_platform.h
@@ -61,9 +61,6 @@
// On Linux/macOS, this is $HOME. On Windows this is %USERPROFILE%.
std::string GetHomeDir();
-// Returns the location of the global bazelrc file if it exists, otherwise "".
-std::string FindSystemWideBlazerc();
-
// Warn about dubious filesystem types, such as NFS, case-insensitive (?).
void WarnFilesystemType(const std::string& output_base);
diff --git a/src/main/cpp/blaze_util_posix.cc b/src/main/cpp/blaze_util_posix.cc
index 156b021..2398e17 100644
--- a/src/main/cpp/blaze_util_posix.cc
+++ b/src/main/cpp/blaze_util_posix.cc
@@ -142,14 +142,6 @@
string GetHomeDir() { return GetEnv("HOME"); }
-string FindSystemWideBlazerc() {
- string path = "/etc/bazel.bazelrc";
- if (blaze_util::CanReadFile(path)) {
- return path;
- }
- return "";
-}
-
string GetJavaBinaryUnderJavabase() { return "bin/java"; }
// NB: execve() requires pointers to non-const char arrays but .c_str() returns
diff --git a/src/main/cpp/option_processor-internal.h b/src/main/cpp/option_processor-internal.h
index 8ebfb64..47f0df4 100644
--- a/src/main/cpp/option_processor-internal.h
+++ b/src/main/cpp/option_processor-internal.h
@@ -30,6 +30,8 @@
std::vector<std::string> DedupeBlazercPaths(
const std::vector<std::string>& paths);
+std::string FindSystemWideRc();
+
std::string FindRcAlongsideBinary(const std::string& cwd,
const std::string& path_to_binary);
diff --git a/src/main/cpp/option_processor.cc b/src/main/cpp/option_processor.cc
index 582833a..11da52a 100644
--- a/src/main/cpp/option_processor.cc
+++ b/src/main/cpp/option_processor.cc
@@ -47,6 +47,10 @@
constexpr char WorkspaceLayout::WorkspacePrefix[];
static std::vector<std::string> GetProcessedEnv();
+// Path to the system-wide bazelrc configuration file.
+// This is a mutable global for testing purposes only.
+const char* system_bazelrc_path = BAZEL_SYSTEM_BAZELRC_PATH;
+
OptionProcessor::OptionProcessor(
const WorkspaceLayout* workspace_layout,
std::unique_ptr<StartupOptions> default_startup_options)
@@ -187,6 +191,20 @@
return result;
}
+string FindSystemWideRc() {
+ // MakeAbsoluteAndResolveWindowsEnvvars will standardize the form of the
+ // provided path. This also means we accept relative paths, which is
+ // is convenient for testing.
+ const string path = blaze_util::MakeAbsoluteAndResolveWindowsEnvvars(
+ system_bazelrc_path);
+ if (blaze_util::CanReadFile(path)) {
+ return path;
+ }
+ BAZEL_LOG(INFO) << "Looked for a system bazelrc at path '" << path
+ << "', but none was found.";
+ return "";
+}
+
string FindRcAlongsideBinary(const string& cwd, const string& path_to_binary) {
const string path = blaze_util::IsAbsolute(path_to_binary)
? path_to_binary
@@ -231,9 +249,13 @@
if (SearchNullaryOption(cmd_line->startup_args, "master_bazelrc", true)) {
const string workspace_rc =
workspace_layout->GetWorkspaceRcPath(workspace, cmd_line->startup_args);
+ // TODO(b/36168162): Remove the alongside-binary rc file. (Part of GitHub
+ // issue #4502)
const string binary_rc =
internal::FindRcAlongsideBinary(cwd, cmd_line->path_to_binary);
- const string system_rc = FindSystemWideBlazerc();
+ // TODO(b/36168162): This is not the desired order, see
+ // https://github.com/bazelbuild/bazel/issues/4502#issuecomment-372697374.
+ const string system_rc = internal::FindSystemWideRc();
BAZEL_LOG(INFO)
<< "Looking for master bazelrcs in the following three paths: "
<< workspace_rc << ", " << binary_rc << ", " << system_rc;
diff --git a/src/main/cpp/workspace_layout.cc b/src/main/cpp/workspace_layout.cc
index b1d3ff2..d781993 100644
--- a/src/main/cpp/workspace_layout.cc
+++ b/src/main/cpp/workspace_layout.cc
@@ -61,6 +61,9 @@
std::string WorkspaceLayout::GetWorkspaceRcPath(
const std::string &workspace,
const std::vector<std::string> &startup_args) const {
+ // TODO(b/36168162): Rename and remove the tools/ prefix. See
+ // https://github.com/bazelbuild/bazel/issues/4502#issuecomment-372697374
+ // for the final set of bazelrcs we want to have.
return blaze_util::JoinPath(workspace, "tools/bazel.rc");
}
diff --git a/src/test/cpp/rc_file_test.cc b/src/test/cpp/rc_file_test.cc
index f10287d..e46d039 100644
--- a/src/test/cpp/rc_file_test.cc
+++ b/src/test/cpp/rc_file_test.cc
@@ -22,6 +22,7 @@
#include "src/main/cpp/util/file.h"
#include "src/main/cpp/util/file_platform.h"
#include "src/main/cpp/util/path.h"
+#include "src/main/cpp/util/path_platform.h"
#include "src/main/cpp/workspace_layout.h"
#include "googlemock/include/gmock/gmock.h"
#include "googletest/include/gtest/gtest.h"
@@ -36,6 +37,8 @@
constexpr const char* kNullDevice = "/dev/null";
#endif
+extern const char* system_bazelrc_path;
+
class RcFileTest : public ::testing::Test {
protected:
RcFileTest()
@@ -45,11 +48,34 @@
binary_dir_(
blaze_util::JoinPath(blaze::GetEnv("TEST_TMPDIR"), "bazeldir")),
binary_path_(blaze_util::JoinPath(binary_dir_, "bazel")),
- workspace_layout_(new WorkspaceLayout()) {}
+ workspace_layout_(new WorkspaceLayout()),
+ old_system_bazelrc_path_(system_bazelrc_path) {}
void SetUp() override {
+ // We modify the global system_bazelrc_path to be a relative path.
+ // This test allows us to verify that the global bazelrc is read correctly,
+ // in the right order relative to the other files.
+ //
+ // However, this does not test the default path of this file, nor does it
+ // test that absolute paths are accepted properly. This is an unfortunate
+ // limitation of our testing - within the sandboxed environment of a test,
+ // we cannot place a file in arbitrary locations.
+ system_bazelrc_path = "bazel.bazelrc";
+
ASSERT_TRUE(blaze_util::MakeDirectories(workspace_, 0755));
ASSERT_TRUE(blaze_util::MakeDirectories(cwd_, 0755));
+ ASSERT_TRUE(blaze_util::ChangeDirectory(cwd_));
+#if defined(_WIN32) || defined(__CYGWIN__)
+ // GetCwd returns a short path on Windows, so we store this expectation now
+ // to keep assertions sane in the tests.
+ std::string short_cwd;
+ std::string error;
+ ASSERT_TRUE(blaze_util::AsShortWindowsPath(cwd_, &short_cwd, &error))
+ << error;
+ cwd_ = short_cwd;
+
+#endif
+
ASSERT_TRUE(blaze_util::MakeDirectories(binary_dir_, 0755));
option_processor_.reset(new OptionProcessor(
workspace_layout_.get(),
@@ -75,15 +101,21 @@
for (const std::string& file : files) {
blaze_util::UnlinkPath(file);
}
+ system_bazelrc_path = old_system_bazelrc_path_.c_str();
}
- // We only test 2 of the 3 master bazelrc locations in this test. The third
- // masterrc that should be loaded is the system wide bazelrc path,
- // /etc/bazel.bazelrc, which we do not mock within this test because it is not
- // within the sandbox. It may or may not exist on the system running the test,
- // so we do not check for it.
- // TODO(#4502): Make the system-wide master bazelrc location configurable and
- // add test coverage for it.
+ bool SetUpGlobalRcFile(const std::string& contents,
+ std::string* rcfile_path) const {
+ const std::string global_rc_path =
+ blaze_util::ConvertPath(blaze_util::JoinPath(cwd_, "bazel.bazelrc"));
+
+ if (blaze_util::WriteFile(contents, global_rc_path, 0755)) {
+ *rcfile_path = global_rc_path;
+ return true;
+ }
+ return false;
+ }
+
bool SetUpMasterRcFileInWorkspace(const std::string& contents,
std::string* rcfile_path) const {
const std::string tools_dir = blaze_util::JoinPath(workspace_, "tools");
@@ -121,10 +153,11 @@
}
const std::string workspace_;
- const std::string cwd_;
+ std::string cwd_;
const std::string binary_dir_;
const std::string binary_path_;
const std::unique_ptr<WorkspaceLayout> workspace_layout_;
+ const std::string old_system_bazelrc_path_;
std::unique_ptr<OptionProcessor> option_processor_;
};
@@ -135,6 +168,8 @@
ASSERT_TRUE(SetUpMasterRcFileInWorkspace("", &workspace_rc));
std::string binary_rc;
ASSERT_TRUE(SetUpMasterRcFileAlongsideBinary("", &binary_rc));
+ std::string global_rc;
+ ASSERT_TRUE(SetUpGlobalRcFile("", &global_rc));
const CommandLine cmd_line =
CommandLine(binary_path_, {"--bazelrc=/dev/null"}, "build", {});
@@ -146,19 +181,17 @@
EXPECT_EQ(blaze_exit_code::SUCCESS, exit_code);
EXPECT_EQ("check that this string is not modified", error);
- // There should be 3-4 rc files, "/dev/null" does in some sense count as a
- // file, and there's an optional /etc/ file the test environment cannot
- // control. The first 2 rcs parsed should be the two rc files we expect, and
- // the last file is the user-provided /dev/null.
- ASSERT_LE(3, parsed_rcs.size());
- ASSERT_GE(4, parsed_rcs.size());
+ // There should be 4 rc files, since "/dev/null" does count along with the 3
+ // master rcs.
+ ASSERT_EQ(4, parsed_rcs.size());
const std::deque<std::string> expected_workspace_rc_que = {workspace_rc};
const std::deque<std::string> expected_binary_rc_que = {binary_rc};
+ const std::deque<std::string> expected_global_rc_que = {global_rc};
const std::deque<std::string> expected_user_rc_que = {kNullDevice};
EXPECT_EQ(expected_workspace_rc_que, parsed_rcs[0].get()->sources());
EXPECT_EQ(expected_binary_rc_que, parsed_rcs[1].get()->sources());
- EXPECT_EQ(expected_user_rc_que,
- parsed_rcs[parsed_rcs.size() - 1].get()->sources());
+ EXPECT_EQ(expected_global_rc_que, parsed_rcs[2].get()->sources());
+ EXPECT_EQ(expected_user_rc_que, parsed_rcs[3].get()->sources());
}
TEST_F(GetRcFileTest, GetRcFilesRespectsNoMasterBazelrc) {
@@ -166,6 +199,8 @@
ASSERT_TRUE(SetUpMasterRcFileInWorkspace("", &workspace_rc));
std::string binary_rc;
ASSERT_TRUE(SetUpMasterRcFileAlongsideBinary("", &binary_rc));
+ std::string global_rc;
+ ASSERT_TRUE(SetUpGlobalRcFile("", &global_rc));
const CommandLine cmd_line = CommandLine(
binary_path_, {"--nomaster_bazelrc", "--bazelrc=/dev/null"}, "build", {});
@@ -242,6 +277,8 @@
std::string binary_rc;
ASSERT_TRUE(SetUpMasterRcFileAlongsideBinary("startup --binarymasterfoo",
&binary_rc));
+ std::string global_rc;
+ ASSERT_TRUE(SetUpGlobalRcFile("startup --globalmasterfoo", &global_rc));
const std::vector<std::string> args = {binary_path_, "--ignore_all_rc_files",
"build"};
@@ -295,6 +332,8 @@
std::string binary_rc;
ASSERT_TRUE(SetUpMasterRcFileAlongsideBinary("startup --binarymasterfoo",
&binary_rc));
+ std::string global_rc;
+ ASSERT_TRUE(SetUpGlobalRcFile("startup --globalmasterfoo", &global_rc));
const std::string cmdline_rc_path =
blaze_util::JoinPath(workspace_, "mybazelrc");
ASSERT_TRUE(
@@ -382,6 +421,8 @@
IncorrectMasterBazelrcIgnoredWhenNoMasterBazelrcIsPresent) {
std::string workspace_rc;
ASSERT_TRUE(SetUpMasterRcFileInWorkspace("startup --foo", &workspace_rc));
+ std::string global_rc;
+ ASSERT_TRUE(SetUpGlobalRcFile("startup --globalfoo", &global_rc));
const std::vector<std::string> args = {binary_path_, "--nomaster_bazelrc",
"build"};