diff options
-rwxr-xr-x | scripts/bash_completion_test.sh | 6 | ||||
-rw-r--r-- | site/docs/user-manual.html | 50 | ||||
-rw-r--r-- | src/main/cpp/bazel_startup_options.cc | 64 | ||||
-rw-r--r-- | src/main/cpp/bazel_startup_options.h | 4 | ||||
-rw-r--r-- | src/main/cpp/option_processor-internal.h | 14 | ||||
-rw-r--r-- | src/main/cpp/option_processor.cc | 222 | ||||
-rw-r--r-- | src/main/cpp/option_processor.h | 17 | ||||
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/bazel/BazelStartupOptionsModule.java | 35 | ||||
-rw-r--r-- | src/test/cpp/bazel_startup_options_test.cc | 21 | ||||
-rw-r--r-- | src/test/cpp/option_processor_test.cc | 6 | ||||
-rw-r--r-- | src/test/cpp/rc_file_test.cc | 350 | ||||
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/packages/BazelDocumentationTest.java | 4 | ||||
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/packages/util/DocumentationTestUtil.java | 7 | ||||
-rwxr-xr-x | src/test/shell/integration/bazel_command_log_test.sh | 1 |
14 files changed, 523 insertions, 278 deletions
diff --git a/scripts/bash_completion_test.sh b/scripts/bash_completion_test.sh index 2a7bef24e9..7029137a37 100755 --- a/scripts/bash_completion_test.sh +++ b/scripts/bash_completion_test.sh @@ -406,9 +406,9 @@ test_basic_subcommand_expansion() { 'shutdown ' } -test_common_options() { - # 'Test common option completion' - assert_expansion '--h' \ +test_common_startup_options() { + # 'Test common startup option completion' + assert_expansion '--hos' \ '--host_jvm_' assert_expansion '--host_jvm_a' \ '--host_jvm_args=' diff --git a/site/docs/user-manual.html b/site/docs/user-manual.html index 5488052e1d..c4c947bb70 100644 --- a/site/docs/user-manual.html +++ b/site/docs/user-manual.html @@ -134,41 +134,43 @@ title: User Manual Bazel allows you to specify options in a configuration file. </p> -<h4>Where are <code>.bazelrc</code> files?</h4> + +<h4>Where are the <code>.bazelrc</code> files?</h4> <p> Bazel looks for an optional configuration file in the following locations, - in order. It will stop searching once it has successfully found a file. + in the order shown below. The options are interpreted in this order, so + options in later files can override a value from an earlier file if a + conflict arises. All options to control which of these files are loaded are + startup options, which means they much occur after <code>bazel</code> and + before the command (<code>build</code>, etc). </p> <ol> <li> - The path specified by the <code class='flag'>--bazelrc=<var>file</var></code> - startup option. If specified, this option must appear <em>before</em> the - command name (e.g. <code>build</code>) + Unless the <code class='flag'>--nosystem_rc</code> is present, Bazel looks for + the system .bazelrc file: on Unix, it lives at <code>/etc/bazel.bazelrc</code>, + and on Windows at <code>%%ProgramData%%/bazel.bazelrc</code>. + + If another system-specified location is required, this value can be + changed by setting <code>BAZEL_SYSTEM_BAZELRC_PATH</code> in + <code>src/main/cpp:option_processor</code> and using this custom Bazel binary. </li> <li> - A file named <code>.bazelrc</code> in your base workspace directory + Unless the <code class='flag'>--noworkspace_rc</code> is present, Bazel looks + for the <code>.bazelrc</code> file in your workspace directory. + </li> + <li> + Unless the <code class='flag'>--nohome_rc</code> is present, Bazel looks for + the home, or user, bazelrc: the file <code>.bazelrc</code> in your home + directory. </li> <li> - A file named <code>.bazelrc</code> in your home directory + An additional .rc file can be specified by the + <code class='flag'>--bazelrc=<var>file</var></code> startup option. If this + option is not present, no additional file is loaded. Unlike in the three + default locations specified above, an incorrect path or non-existent file + will fail if passed explicitly. </li> </ol> -<p> - The option <code class='flag'>--bazelrc=/dev/null</code> effectively disables the - use of a configuration file. We strongly recommend that you use - this option when performing release builds, or automated tests that - invoke Bazel. -</p> - -<p> - Aside from the optional configuration file described above, Bazel also looks - for a master rc file named <code>bazel.bazelrc</code> next to the binary, in - the workspace at <code>tools/bazel.rc</code> or system-wide at - <code>/etc/bazel.bazelrc</code>. These files are here to support - installation-wide options or options shared between users. These files do not - override one another; if all of these files exist, all of them will be loaded. - Reading of these files can be disabled using the - <code class='flag'>--nomaster_bazelrc</code> option. -</p> <h4><code>.bazelrc</code> syntax and semantics</h4> <p> Like all UNIX "rc" files, the <code>.bazelrc</code> file is a text file with diff --git a/src/main/cpp/bazel_startup_options.cc b/src/main/cpp/bazel_startup_options.cc index 950647e55d..2ec8c8c4f5 100644 --- a/src/main/cpp/bazel_startup_options.cc +++ b/src/main/cpp/bazel_startup_options.cc @@ -25,8 +25,14 @@ BazelStartupOptions::BazelStartupOptions( const WorkspaceLayout *workspace_layout) : StartupOptions("Bazel", workspace_layout), user_bazelrc_(""), + use_system_rc(true), + use_workspace_rc(true), + use_home_rc(true), use_master_bazelrc_(true) { + RegisterNullaryStartupFlag("home_rc"); RegisterNullaryStartupFlag("master_bazelrc"); + RegisterNullaryStartupFlag("system_rc"); + RegisterNullaryStartupFlag("workspace_rc"); RegisterUnaryStartupFlag("bazelrc"); } @@ -42,6 +48,48 @@ blaze_exit_code::ExitCode BazelStartupOptions::ProcessArgExtra( return blaze_exit_code::BAD_ARGV; } user_bazelrc_ = *value; + } else if (GetNullaryOption(arg, "--system_rc")) { + if (!rcfile.empty()) { + *error = "Can't specify --system_rc in .bazelrc file."; + return blaze_exit_code::BAD_ARGV; + } + use_system_rc = true; + option_sources["system_rc"] = rcfile; + } else if (GetNullaryOption(arg, "--nosystem_rc")) { + if (!rcfile.empty()) { + *error = "Can't specify --nosystem_rc in .bazelrc file."; + return blaze_exit_code::BAD_ARGV; + } + use_system_rc = false; + option_sources["system_rc"] = rcfile; + } else if (GetNullaryOption(arg, "--workspace_rc")) { + if (!rcfile.empty()) { + *error = "Can't specify --workspace_rc in .bazelrc file."; + return blaze_exit_code::BAD_ARGV; + } + use_workspace_rc = true; + option_sources["workspace_rc"] = rcfile; + } else if (GetNullaryOption(arg, "--noworkspace_rc")) { + if (!rcfile.empty()) { + *error = "Can't specify --noworkspace_rc in .bazelrc file."; + return blaze_exit_code::BAD_ARGV; + } + use_workspace_rc = false; + option_sources["workspace_rc"] = rcfile; + } else if (GetNullaryOption(arg, "--home_rc")) { + if (!rcfile.empty()) { + *error = "Can't specify --home_rc in .bazelrc file."; + return blaze_exit_code::BAD_ARGV; + } + use_home_rc = true; + option_sources["home_rc"] = rcfile; + } else if (GetNullaryOption(arg, "--nohome_rc")) { + if (!rcfile.empty()) { + *error = "Can't specify --nohome_rc in .bazelrc file."; + return blaze_exit_code::BAD_ARGV; + } + use_home_rc = false; + option_sources["home_rc"] = rcfile; } else if (GetNullaryOption(arg, "--master_bazelrc")) { if (!rcfile.empty()) { *error = "Can't specify --master_bazelrc in .bazelrc file."; @@ -71,9 +119,19 @@ void BazelStartupOptions::MaybeLogStartupOptionWarnings() const { BAZEL_LOG(WARNING) << "Value of --bazelrc is ignored, since " "--ignore_all_rc_files is on."; } - if ((use_master_bazelrc_) && - option_sources.find("blazerc") != option_sources.end()) { - BAZEL_LOG(WARNING) << "Explicit value of --master_bazelrc is " + if ((use_home_rc) && + option_sources.find("home_rc") != option_sources.end()) { + BAZEL_LOG(WARNING) << "Explicit value of --home_rc is " + "ignored, since --ignore_all_rc_files is on."; + } + if ((use_system_rc) && + option_sources.find("system_rc") != option_sources.end()) { + BAZEL_LOG(WARNING) << "Explicit value of --system_rc is " + "ignored, since --ignore_all_rc_files is on."; + } + if ((use_workspace_rc) && + option_sources.find("workspace_rc") != option_sources.end()) { + BAZEL_LOG(WARNING) << "Explicit value of --workspace_rc is " "ignored, since --ignore_all_rc_files is on."; } } diff --git a/src/main/cpp/bazel_startup_options.h b/src/main/cpp/bazel_startup_options.h index b27aaef613..d84cfd2d38 100644 --- a/src/main/cpp/bazel_startup_options.h +++ b/src/main/cpp/bazel_startup_options.h @@ -34,6 +34,10 @@ class BazelStartupOptions : public StartupOptions { private: std::string user_bazelrc_; + bool use_system_rc; + bool use_workspace_rc; + bool use_home_rc; + // TODO(b/36168162): Remove the master rc flag. bool use_master_bazelrc_; }; diff --git a/src/main/cpp/option_processor-internal.h b/src/main/cpp/option_processor-internal.h index 47f0df4d16..c552db4e38 100644 --- a/src/main/cpp/option_processor-internal.h +++ b/src/main/cpp/option_processor-internal.h @@ -16,6 +16,7 @@ #define BAZEL_SRC_MAIN_CPP_OPTION_PROCESSOR_INTERNAL_H_ #include <algorithm> +#include <set> #include "src/main/cpp/rc_file.h" #include "src/main/cpp/util/exit_code.h" @@ -30,6 +31,19 @@ namespace internal { std::vector<std::string> DedupeBlazercPaths( const std::vector<std::string>& paths); +// Get the legacy list of rc files that would have been loaded - this is to +// provide a useful warning if files are being ignored that were loaded in a +// previous version of Bazel. +// TODO(b/3616816): Remove this once the warning is no longer useful. +std::set<std::string> GetOldRcPaths( + const WorkspaceLayout* workspace_layout, const std::string& workspace, + const std::string& cwd, const std::string& path_to_binary, + const std::vector<std::string>& startup_args); + +// Returns what the "user bazelrc" would have been in the legacy rc list. +std::string FindLegacyUserBazelrc(const char* cmd_line_rc_file, + const std::string& workspace); + std::string FindSystemWideRc(); std::string FindRcAlongsideBinary(const std::string& cwd, diff --git a/src/main/cpp/option_processor.cc b/src/main/cpp/option_processor.cc index 11da52a2cd..f4c246a9dc 100644 --- a/src/main/cpp/option_processor.cc +++ b/src/main/cpp/option_processor.cc @@ -13,6 +13,7 @@ // limitations under the License. #include "src/main/cpp/option_processor.h" +#include "src/main/cpp/option_processor-internal.h" #include <stdio.h> #include <stdlib.h> @@ -45,6 +46,7 @@ using std::string; using std::vector; constexpr char WorkspaceLayout::WorkspacePrefix[]; +static constexpr const char* kRcBasename = ".bazelrc"; static std::vector<std::string> GetProcessedEnv(); // Path to the system-wide bazelrc configuration file. @@ -135,51 +137,68 @@ std::unique_ptr<CommandLine> OptionProcessor::SplitCommandLine( new CommandLine(path_to_binary, startup_args, command, command_args)); } -blaze_exit_code::ExitCode OptionProcessor::FindUserBlazerc( - const char* cmd_line_rc_file, const string& workspace, - string* user_blazerc_file, string* error) const { - const string rc_basename = - "." + parsed_startup_options_->GetLowercaseProductName() + "rc"; +namespace internal { +std::string FindLegacyUserBazelrc(const char* cmd_line_rc_file, + const std::string& workspace) { if (cmd_line_rc_file != nullptr) { string rcFile = blaze::AbsolutePathFromFlag(cmd_line_rc_file); if (!blaze_util::CanReadFile(rcFile)) { - blaze_util::StringPrintf(error, - "Error: Unable to read %s file '%s'.", rc_basename.c_str(), - rcFile.c_str()); - return blaze_exit_code::BAD_ARGV; + // The actual rc file reading will catch this - we ignore this here in the + // legacy version since this is just a warning. Exit eagerly though. + return ""; } - *user_blazerc_file = rcFile; - return blaze_exit_code::SUCCESS; + return rcFile; } - string workspaceRcFile = blaze_util::JoinPath(workspace, rc_basename); + string workspaceRcFile = blaze_util::JoinPath(workspace, kRcBasename); if (blaze_util::CanReadFile(workspaceRcFile)) { - *user_blazerc_file = workspaceRcFile; - return blaze_exit_code::SUCCESS; + return workspaceRcFile; } string home = blaze::GetHomeDir(); if (!home.empty()) { - string userRcFile = blaze_util::JoinPath(home, rc_basename); + string userRcFile = blaze_util::JoinPath(home, kRcBasename); if (blaze_util::CanReadFile(userRcFile)) { - *user_blazerc_file = userRcFile; - return blaze_exit_code::SUCCESS; + return userRcFile; } } - - BAZEL_LOG(INFO) << "User provided no rc file."; - *user_blazerc_file = ""; - return blaze_exit_code::SUCCESS; + return ""; } -namespace internal { +std::set<std::string> GetOldRcPaths( + const WorkspaceLayout* workspace_layout, const std::string& workspace, + const std::string& cwd, const std::string& path_to_binary, + const std::vector<std::string>& startup_args) { + // Find the old list of rc files that would have been loaded here, so we can + // provide a useful warning about old rc files that might no longer be read. + std::vector<std::string> candidate_bazelrc_paths; + if (SearchNullaryOption(startup_args, "master_bazelrc", true)) { + const std::string workspace_rc = + workspace_layout->GetWorkspaceRcPath(workspace, startup_args); + const std::string binary_rc = + internal::FindRcAlongsideBinary(cwd, path_to_binary); + const std::string system_rc = internal::FindSystemWideRc(); + candidate_bazelrc_paths = {workspace_rc, binary_rc, system_rc}; + } + const std::vector<std::string> deduped_blazerc_paths = + internal::DedupeBlazercPaths(candidate_bazelrc_paths); + std::set<std::string> old_rc_paths(deduped_blazerc_paths.begin(), + deduped_blazerc_paths.end()); + string user_bazelrc_path = internal::FindLegacyUserBazelrc( + SearchUnaryOption(startup_args, "--bazelrc"), workspace); + if (!user_bazelrc_path.empty()) { + old_rc_paths.insert(user_bazelrc_path); + } + return old_rc_paths; +} -vector<string> DedupeBlazercPaths(const vector<string>& paths) { - set<string> canonical_paths; - vector<string> result; - for (const string& path : paths) { - const string canonical_path = blaze_util::MakeCanonical(path.c_str()); +std::vector<std::string> DedupeBlazercPaths( + const std::vector<std::string>& paths) { + std::set<std::string> canonical_paths; + std::vector<std::string> result; + for (const std::string& path : paths) { + const std::string canonical_path = blaze_util::MakeCanonical(path.c_str()); if (canonical_path.empty()) { // MakeCanonical returns an empty string when it fails. We ignore this // failure since blazerc paths may point to invalid locations. @@ -191,26 +210,22 @@ vector<string> DedupeBlazercPaths(const vector<string>& paths) { 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); +std::string FindSystemWideRc() { + const std::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 - : blaze_util::JoinPath(cwd, path_to_binary); - const string base = blaze_util::Basename(path_to_binary); - const string binary_blazerc_path = path + "." + base + "rc"; +std::string FindRcAlongsideBinary(const std::string& cwd, + const std::string& path_to_binary) { + const std::string path = blaze_util::IsAbsolute(path_to_binary) + ? path_to_binary + : blaze_util::JoinPath(cwd, path_to_binary); + const std::string base = blaze_util::Basename(path_to_binary); + const std::string binary_blazerc_path = path + "." + base + "rc"; if (blaze_util::CanReadFile(binary_blazerc_path)) { return binary_blazerc_path; } @@ -243,41 +258,72 @@ blaze_exit_code::ExitCode OptionProcessor::GetRcFiles( std::string* error) const { assert(cmd_line != nullptr); assert(result_rc_files != nullptr); - - // Find the master bazelrcs if requested. This list may contain duplicates. - vector<string> candidate_bazelrc_paths; - 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); - // 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; - candidate_bazelrc_paths = {workspace_rc, binary_rc, system_rc}; + assert(!workspace.empty()); + + std::vector<std::string> rc_files; + + // Get the system rc (unless --nosystem_rc). + if (SearchNullaryOption(cmd_line->startup_args, "system_rc", true)) { + // MakeAbsoluteAndResolveWindowsEnvvars will standardize the form of the + // provided path. This also means we accept relative paths, which is + // is convenient for testing. + const std::string system_rc = + blaze_util::MakeAbsoluteAndResolveWindowsEnvvars(system_bazelrc_path); + rc_files.push_back(system_rc); } - string user_bazelrc_path; - blaze_exit_code::ExitCode find_bazelrc_exit_code = - FindUserBlazerc(SearchUnaryOption(cmd_line->startup_args, "--bazelrc"), - workspace, &user_bazelrc_path, error); - if (find_bazelrc_exit_code != blaze_exit_code::SUCCESS) { - return find_bazelrc_exit_code; + // Get the workspace rc: %workspace%/.bazelrc (unless --noworkspace_rc) + if (SearchNullaryOption(cmd_line->startup_args, "workspace_rc", true)) { + const std::string workspaceRcFile = + blaze_util::JoinPath(workspace, kRcBasename); + rc_files.push_back(workspaceRcFile); } - vector<string> deduped_blazerc_paths = - internal::DedupeBlazercPaths(candidate_bazelrc_paths); - deduped_blazerc_paths.push_back(user_bazelrc_path); + // Get the user rc: $HOME/.bazelrc (unless --nohome_rc) + if (SearchNullaryOption(cmd_line->startup_args, "home_rc", true)) { + const std::string home = blaze::GetHomeDir(); + if (home.empty()) { + BAZEL_LOG(WARNING) << "The home directory is not defined, no home_rc " + "will be looked for."; + } else { + rc_files.push_back(blaze_util::JoinPath(home, kRcBasename)); + } + } - for (const auto& bazelrc_path : deduped_blazerc_paths) { - if (bazelrc_path.empty()) { - continue; + // Get the command-line provided rc, passed as --bazelrc or nothing if the + // flag is absent. + const char* cmd_line_rc_file = + SearchUnaryOption(cmd_line->startup_args, "--bazelrc"); + if (cmd_line_rc_file != nullptr) { + string absolute_cmd_line_rc = blaze::AbsolutePathFromFlag(cmd_line_rc_file); + // Unlike the previous 3 paths, where we ignore it if the file does not + // exist or is unreadable, since this path is explicitly passed, this is an + // error. Check this condition here. + if (!blaze_util::CanReadFile(absolute_cmd_line_rc)) { + BAZEL_LOG(ERROR) << "Error: Unable to read .bazelrc file '" + << absolute_cmd_line_rc << "'."; + return blaze_exit_code::BAD_ARGV; } + rc_files.push_back(absolute_cmd_line_rc); + } + + // Log which files we're looking for before removing duplicates and + // non-existent files, so that this can serve to debug why a certain file is + // not being read. The final files which are read will be logged as they are + // parsed, and can be found using --announce_rc. + std::string joined_rcs; + blaze_util::JoinStrings(rc_files, ',', &joined_rcs); + BAZEL_LOG(INFO) << "Looking for the following rc files: " << joined_rcs; + + // It's possible that workspace == home, that files are symlinks for each + // other, or that the --bazelrc flag is a duplicate. Dedupe them to minimize + // the likelihood of repeated options. Since bazelrcs can include one another, + // this isn't sufficient to prevent duplicate options, but it's good enough. + // This also has the effect of removing paths that don't point to real files. + rc_files = internal::DedupeBlazercPaths(rc_files); + + // Parse these potential files, in priority order; + for (const auto& bazelrc_path : rc_files) { std::unique_ptr<RcFile> parsed_rc; blaze_exit_code::ExitCode parse_rcfile_exit_code = ParseRcFile( workspace_layout, workspace, bazelrc_path, &parsed_rc, error); @@ -287,6 +333,42 @@ blaze_exit_code::ExitCode OptionProcessor::GetRcFiles( result_rc_files->push_back(std::move(parsed_rc)); } + // Provide a warning for any old file that might have been missed with the new + // expectations. This compares "canonical" paths to one another, so should not + // require additional transformation. + // TODO(b/36168162): Remove this warning along with + // internal::GetOldRcPaths and internal::FindLegacyUserBazelrc after + // the transition period has passed. + std::set<std::string> read_files; + for (auto& result_rc : *result_rc_files) { + const std::deque<std::string>& sources = result_rc->sources(); + read_files.insert(sources.begin(), sources.end()); + } + + const std::set<std::string> old_files = + internal::GetOldRcPaths(workspace_layout, workspace, cwd, + cmd_line->path_to_binary, cmd_line->startup_args); + + // std::vector<std::string> old_files = internal::GetOldRcPathsInOrder( + // workspace_layout, workspace, cwd, cmd_line->path_to_binary, + // cmd_line->startup_args); + // + // std::sort(old_files.begin(), old_files.end()); + std::vector<std::string> lost_files(old_files.size()); + std::vector<std::string>::iterator end_iter = std::set_difference( + old_files.begin(), old_files.end(), read_files.begin(), read_files.end(), + lost_files.begin()); + lost_files.resize(end_iter - lost_files.begin()); + if (!lost_files.empty()) { + std::string joined_lost_rcs; + blaze_util::JoinStrings(lost_files, '\n', &joined_lost_rcs); + BAZEL_LOG(WARNING) + << "The following rc files are no longer being read, please transfer " + "their contents or import their path into one of the standard rc " + "files:\n" + << joined_lost_rcs; + } + return blaze_exit_code::SUCCESS; } diff --git a/src/main/cpp/option_processor.h b/src/main/cpp/option_processor.h index 2ae1798f85..0d7277fb96 100644 --- a/src/main/cpp/option_processor.h +++ b/src/main/cpp/option_processor.h @@ -115,24 +115,17 @@ class OptionProcessor { const std::vector<std::unique_ptr<RcFile>>& blazercs, const std::vector<std::string>& env); - // Finds and parses the appropriate RcFiles. - // TODO(#4502) Change where the bazelrcs are read from. + // Finds and parses the appropriate RcFiles: + // - system rc (unless --nosystem_rc) + // - workspace, %workspace%/.bazelrc (unless --noworkspace_rc) + // - user, $HOME/.bazelrc (unless --nohome_rc) + // - command-line provided, if a value is passed with --bazelrc. virtual blaze_exit_code::ExitCode GetRcFiles( const WorkspaceLayout* workspace_layout, const std::string& workspace, const std::string& cwd, const CommandLine* cmd_line, std::vector<std::unique_ptr<RcFile>>* result_rc_files, std::string* error) const; - protected: - // Return the path to the user's rc file. If cmd_line_rc_file != NULL, - // use it, dying if it is not readable. Otherwise, return the first - // readable file called rc_basename from [workspace, $HOME] - // - // If no readable .blazerc file is found, return the empty string. - virtual blaze_exit_code::ExitCode FindUserBlazerc( - const char* cmd_line_rc_file, const std::string& workspace, - std::string* user_blazerc_file, std::string* error) const; - private: blaze_exit_code::ExitCode ParseStartupOptions( const std::vector<std::unique_ptr<RcFile>>& rc_files, diff --git a/src/main/java/com/google/devtools/build/lib/bazel/BazelStartupOptionsModule.java b/src/main/java/com/google/devtools/build/lib/bazel/BazelStartupOptionsModule.java index fa0d66ee5f..da2f9038f6 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/BazelStartupOptionsModule.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/BazelStartupOptionsModule.java @@ -23,6 +23,7 @@ import com.google.devtools.build.lib.util.AbruptExitException; import com.google.devtools.common.options.Option; import com.google.devtools.common.options.OptionDocumentationCategory; import com.google.devtools.common.options.OptionEffectTag; +import com.google.devtools.common.options.OptionMetadataTag; import com.google.devtools.common.options.OptionsBase; /** Provides Bazel startup flags. */ @@ -43,17 +44,47 @@ public class BazelStartupOptionsModule extends BlazeModule { + "release builds.") public String blazerc; + // TODO(b/36168162): Remove this after the transition period is ower. This now only serves to + // provide accurate warnings about which old files are being missed. @Option( name = "master_bazelrc", defaultValue = "true", // NOTE: purely decorative, rc files are read by the client. - documentationCategory = OptionDocumentationCategory.BAZEL_CLIENT_OPTIONS, - effectTags = {OptionEffectTag.CHANGES_INPUTS}, + documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, + effectTags = {OptionEffectTag.NO_OP}, + metadataTags = {OptionMetadataTag.DEPRECATED}, help = "If this option is false, the master bazelrcs are not read. Otherwise, Bazel looks for " + "master rcs in three locations, reading them all, in order: " + "$workspace/tools/bazel.rc, a .bazelrc file near the bazel binary, and the " + "global rc, /etc/bazel.bazelrc.") public boolean masterBlazerc; + + // For the system_rc, it can be /etc/bazel.bazelrc, or a special Windows value, or can be + // custom-set by the Bazel distributor. We don't list a known path in the help output in order + // to avoid misdocumentation here. + @Option( + name = "system_rc", + defaultValue = "true", // NOTE: purely decorative, rc files are read by the client. + documentationCategory = OptionDocumentationCategory.BAZEL_CLIENT_OPTIONS, + effectTags = {OptionEffectTag.CHANGES_INPUTS}, + help = "Whether or not to look for the system-wide bazelrc.") + public boolean systemRc; + + @Option( + name = "workspace_rc", + defaultValue = "true", // NOTE: purely decorative, rc files are read by the client. + documentationCategory = OptionDocumentationCategory.BAZEL_CLIENT_OPTIONS, + effectTags = {OptionEffectTag.CHANGES_INPUTS}, + help = "Whether or not to look for the workspace bazelrc file at $workspace/.bazelrc") + public boolean workspaceRc; + + @Option( + name = "home_rc", + defaultValue = "true", // NOTE: purely decorative, rc files are read by the client. + documentationCategory = OptionDocumentationCategory.BAZEL_CLIENT_OPTIONS, + effectTags = {OptionEffectTag.CHANGES_INPUTS}, + help = "Whether or not to look for the home bazelrc file at $HOME/.bazelrc") + public boolean homeRc; } @Override diff --git a/src/test/cpp/bazel_startup_options_test.cc b/src/test/cpp/bazel_startup_options_test.cc index 4f0e460693..3e372e4a88 100644 --- a/src/test/cpp/bazel_startup_options_test.cc +++ b/src/test/cpp/bazel_startup_options_test.cc @@ -85,10 +85,13 @@ TEST_F(BazelStartupOptionsTest, ValidStartupFlags) { ExpectIsNullaryOption(options, "deep_execroot"); ExpectIsNullaryOption(options, "experimental_oom_more_eagerly"); ExpectIsNullaryOption(options, "fatal_event_bus_exceptions"); + ExpectIsNullaryOption(options, "home_rc"); ExpectIsNullaryOption(options, "host_jvm_debug"); ExpectIsNullaryOption(options, "ignore_all_rc_files"); ExpectIsNullaryOption(options, "master_bazelrc"); + ExpectIsNullaryOption(options, "system_rc"); ExpectIsNullaryOption(options, "watchfs"); + ExpectIsNullaryOption(options, "workspace_rc"); ExpectIsNullaryOption(options, "write_command_log"); ExpectIsUnaryOption(options, "bazelrc"); ExpectIsUnaryOption(options, "command_port"); @@ -128,28 +131,28 @@ TEST_F(BazelStartupOptionsTest, IgnoredBazelrcFlagWarnsWhenAfterIgnore) { "on.\n"); } -TEST_F(BazelStartupOptionsTest, IgnoredMasterBazelrcFlagWarns) { +TEST_F(BazelStartupOptionsTest, IgnoredWorkspaceRcFlagWarns) { ParseStartupOptionsAndExpectWarning( - startup_options_.get(), {"--master_bazelrc", "--ignore_all_rc_files"}, - "WARNING: Explicit value of --master_bazelrc is ignored, " + startup_options_.get(), {"--workspace_rc", "--ignore_all_rc_files"}, + "WARNING: Explicit value of --workspace_rc is ignored, " "since --ignore_all_rc_files is on.\n"); } -TEST_F(BazelStartupOptionsTest, IgnoredMasterBazelrcFlagWarnsAfterIgnore) { +TEST_F(BazelStartupOptionsTest, IgnoredWorkspaceRcFlagWarnsAfterIgnore) { ParseStartupOptionsAndExpectWarning( - startup_options_.get(), {"--ignore_all_rc_files", "--master_bazelrc"}, - "WARNING: Explicit value of --master_bazelrc is ignored, " + startup_options_.get(), {"--ignore_all_rc_files", "--workspace_rc"}, + "WARNING: Explicit value of --workspace_rc is ignored, " "since --ignore_all_rc_files is on.\n"); } TEST_F(BazelStartupOptionsTest, MultipleIgnoredRcFlagsWarnOnceEach) { ParseStartupOptionsAndExpectWarning( startup_options_.get(), - {"--master_bazelrc", "--bazelrc=somefile", "--ignore_all_rc_files", - "--bazelrc=thefinalfile", "--master_bazelrc"}, + {"--workspace_rc", "--bazelrc=somefile", "--ignore_all_rc_files", + "--bazelrc=thefinalfile", "--workspace_rc"}, "WARNING: Value of --bazelrc is ignored, " "since --ignore_all_rc_files is on.\n" - "WARNING: Explicit value of --master_bazelrc is ignored, " + "WARNING: Explicit value of --workspace_rc is ignored, " "since --ignore_all_rc_files is on.\n"); } diff --git a/src/test/cpp/option_processor_test.cc b/src/test/cpp/option_processor_test.cc index 6048b80b00..f008d035c9 100644 --- a/src/test/cpp/option_processor_test.cc +++ b/src/test/cpp/option_processor_test.cc @@ -310,6 +310,12 @@ TEST_F(OptionProcessorTest, TestDedupePathsOmitsInvalidPath) { ASSERT_EQ(expected, internal::DedupeBlazercPaths(input)); } +TEST_F(OptionProcessorTest, TestDedupePathsOmitsEmptyPath) { + std::vector<std::string> input = {""}; + std::vector<std::string> expected = {}; + ASSERT_EQ(expected, internal::DedupeBlazercPaths(input)); +} + TEST_F(OptionProcessorTest, TestDedupePathsWithDifferentFiles) { std::string foo_path = blaze_util::JoinPath(workspace_, "foo"); std::string bar_path = blaze_util::JoinPath(workspace_, "bar"); diff --git a/src/test/cpp/rc_file_test.cc b/src/test/cpp/rc_file_test.cc index e46d039a7a..f23d6390a3 100644 --- a/src/test/cpp/rc_file_test.cc +++ b/src/test/cpp/rc_file_test.cc @@ -43,7 +43,7 @@ class RcFileTest : public ::testing::Test { protected: RcFileTest() : workspace_( - blaze_util::JoinPath(blaze::GetEnv("TEST_TMPDIR"), "testdir")), + blaze_util::JoinPath(blaze::GetEnv("TEST_TMPDIR"), "workspace")), cwd_(blaze_util::JoinPath(blaze::GetEnv("TEST_TMPDIR"), "cwd")), binary_dir_( blaze_util::JoinPath(blaze::GetEnv("TEST_TMPDIR"), "bazeldir")), @@ -104,20 +104,34 @@ class RcFileTest : public ::testing::Test { system_bazelrc_path = old_system_bazelrc_path_.c_str(); } - bool SetUpGlobalRcFile(const std::string& contents, + bool SetUpSystemRcFile(const std::string& contents, std::string* rcfile_path) const { - const std::string global_rc_path = + const std::string system_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; + if (blaze_util::WriteFile(contents, system_rc_path, 0755)) { + *rcfile_path = system_rc_path; return true; } return false; } - bool SetUpMasterRcFileInWorkspace(const std::string& contents, - std::string* rcfile_path) const { + bool SetUpWorkspaceRcFile(const std::string& contents, + std::string* rcfile_path) const { + const std::string workspace_user_rc_path = + blaze_util::JoinPath(workspace_, ".bazelrc"); + if (blaze_util::WriteFile(contents, workspace_user_rc_path, 0755)) { + *rcfile_path = workspace_user_rc_path; + return true; + } + return false; + } + + // TODO(b/36168162): Make it possible to configure the home directory so we + // can test --home_rc as well. + + bool SetUpLegacyMasterRcFileInWorkspace(const std::string& contents, + std::string* rcfile_path) const { const std::string tools_dir = blaze_util::JoinPath(workspace_, "tools"); const std::string workspace_rc_path = blaze_util::JoinPath(tools_dir, "bazel.rc"); @@ -129,8 +143,8 @@ class RcFileTest : public ::testing::Test { return false; } - bool SetUpMasterRcFileAlongsideBinary(const std::string& contents, - std::string* rcfile_path) const { + bool SetUpLegacyMasterRcFileAlongsideBinary(const std::string& contents, + std::string* rcfile_path) const { const std::string binary_rc_path = blaze_util::JoinPath(binary_dir_, "bazel.bazelrc"); if (blaze_util::WriteFile(contents, binary_rc_path, 0755)) { @@ -140,18 +154,6 @@ class RcFileTest : public ::testing::Test { return false; } - // This file is looked for if no --bazelrc is explicitly provided. - bool SetUpUserRcFileInWorkspace(const std::string& contents, - std::string* rcfile_path) const { - const std::string workspace_user_rc_path = - blaze_util::JoinPath(workspace_, ".bazelrc"); - if (blaze_util::WriteFile(contents, workspace_user_rc_path, 0755)) { - *rcfile_path = workspace_user_rc_path; - return true; - } - return false; - } - const std::string workspace_; std::string cwd_; const std::string binary_dir_; @@ -163,16 +165,38 @@ class RcFileTest : public ::testing::Test { using GetRcFileTest = RcFileTest; -TEST_F(GetRcFileTest, GetRcFilesLoadsAllMasterBazelrcs) { +TEST_F(GetRcFileTest, GetRcFilesLoadsAllDefaultBazelrcs) { + std::string system_rc; + ASSERT_TRUE(SetUpSystemRcFile("", &system_rc)); std::string workspace_rc; - ASSERT_TRUE(SetUpMasterRcFileInWorkspace("", &workspace_rc)); - std::string binary_rc; - ASSERT_TRUE(SetUpMasterRcFileAlongsideBinary("", &binary_rc)); - std::string global_rc; - ASSERT_TRUE(SetUpGlobalRcFile("", &global_rc)); + ASSERT_TRUE(SetUpWorkspaceRcFile("", &workspace_rc)); + + const CommandLine cmd_line = CommandLine(binary_path_, {}, "build", {}); + std::string error = "check that this string is not modified"; + std::vector<std::unique_ptr<RcFile>> parsed_rcs; + const blaze_exit_code::ExitCode exit_code = + option_processor_->GetRcFiles(workspace_layout_.get(), workspace_, cwd_, + &cmd_line, &parsed_rcs, &error); + EXPECT_EQ(blaze_exit_code::SUCCESS, exit_code); + EXPECT_EQ("check that this string is not modified", error); + + // There should be 2 rc files: the system one and the workspace one. --bazelrc + // is not passed and therefore is not relevant. + ASSERT_EQ(2, parsed_rcs.size()); + const std::deque<std::string> expected_system_rc_que = {system_rc}; + const std::deque<std::string> expected_workspace_rc_que = {workspace_rc}; + EXPECT_EQ(expected_system_rc_que, parsed_rcs[0].get()->sources()); + EXPECT_EQ(expected_workspace_rc_que, parsed_rcs[1].get()->sources()); +} + +TEST_F(GetRcFileTest, GetRcFilesRespectsNoSystemRc) { + std::string system_rc; + ASSERT_TRUE(SetUpSystemRcFile("", &system_rc)); + std::string workspace_rc; + ASSERT_TRUE(SetUpWorkspaceRcFile("", &workspace_rc)); const CommandLine cmd_line = - CommandLine(binary_path_, {"--bazelrc=/dev/null"}, "build", {}); + CommandLine(binary_path_, {"--nosystem_rc"}, "build", {}); std::string error = "check that this string is not modified"; std::vector<std::unique_ptr<RcFile>> parsed_rcs; const blaze_exit_code::ExitCode exit_code = @@ -181,29 +205,40 @@ TEST_F(GetRcFileTest, GetRcFilesLoadsAllMasterBazelrcs) { EXPECT_EQ(blaze_exit_code::SUCCESS, exit_code); EXPECT_EQ("check that this string is not modified", error); - // There should be 4 rc files, since "/dev/null" does count along with the 3 - // master rcs. - ASSERT_EQ(4, parsed_rcs.size()); + ASSERT_EQ(1, 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_global_rc_que, parsed_rcs[2].get()->sources()); - EXPECT_EQ(expected_user_rc_que, parsed_rcs[3].get()->sources()); } -TEST_F(GetRcFileTest, GetRcFilesRespectsNoMasterBazelrc) { +TEST_F(GetRcFileTest, GetRcFilesRespectsNoWorkspaceRc) { + std::string system_rc; + ASSERT_TRUE(SetUpSystemRcFile("", &system_rc)); std::string workspace_rc; - ASSERT_TRUE(SetUpMasterRcFileInWorkspace("", &workspace_rc)); - std::string binary_rc; - ASSERT_TRUE(SetUpMasterRcFileAlongsideBinary("", &binary_rc)); - std::string global_rc; - ASSERT_TRUE(SetUpGlobalRcFile("", &global_rc)); + ASSERT_TRUE(SetUpWorkspaceRcFile("", &workspace_rc)); + + const CommandLine cmd_line = + CommandLine(binary_path_, {"--noworkspace_rc"}, "build", {}); + std::string error = "check that this string is not modified"; + std::vector<std::unique_ptr<RcFile>> parsed_rcs; + const blaze_exit_code::ExitCode exit_code = + option_processor_->GetRcFiles(workspace_layout_.get(), workspace_, cwd_, + &cmd_line, &parsed_rcs, &error); + EXPECT_EQ(blaze_exit_code::SUCCESS, exit_code); + EXPECT_EQ("check that this string is not modified", error); + + ASSERT_EQ(1, parsed_rcs.size()); + const std::deque<std::string> expected_system_rc_que = {system_rc}; + EXPECT_EQ(expected_system_rc_que, parsed_rcs[0].get()->sources()); +} + +TEST_F(GetRcFileTest, GetRcFilesRespectsNoWorkspaceRcAndNoSystemCombined) { + std::string system_rc; + ASSERT_TRUE(SetUpSystemRcFile("", &system_rc)); + std::string workspace_rc; + ASSERT_TRUE(SetUpWorkspaceRcFile("", &workspace_rc)); const CommandLine cmd_line = CommandLine( - binary_path_, {"--nomaster_bazelrc", "--bazelrc=/dev/null"}, "build", {}); + binary_path_, {"--noworkspace_rc", "--nosystem_rc"}, "build", {}); std::string error = "check that this string is not modified"; std::vector<std::unique_ptr<RcFile>> parsed_rcs; const blaze_exit_code::ExitCode exit_code = @@ -212,12 +247,68 @@ TEST_F(GetRcFileTest, GetRcFilesRespectsNoMasterBazelrc) { EXPECT_EQ(blaze_exit_code::SUCCESS, exit_code); EXPECT_EQ("check that this string is not modified", error); - // /dev/null is technically a file, but no master rcs should have been loaded. - const std::deque<std::string> expected_user_rc_que = {kNullDevice}; - EXPECT_EQ(expected_user_rc_que, parsed_rcs[0].get()->sources()); + ASSERT_EQ(0, parsed_rcs.size()); } -TEST_F(GetRcFileTest, GetRcFilesReadsCommandLineUserRc) { +TEST_F(GetRcFileTest, GetRcFilesWarnsAboutIgnoredMasterRcFiles) { + std::string workspace_rc; + ASSERT_TRUE(SetUpLegacyMasterRcFileInWorkspace("", &workspace_rc)); + std::string binary_rc; + ASSERT_TRUE(SetUpLegacyMasterRcFileAlongsideBinary("", &binary_rc)); + + const CommandLine cmd_line = CommandLine(binary_path_, {}, "build", {}); + std::string error = "check that this string is not modified"; + std::vector<std::unique_ptr<RcFile>> parsed_rcs; + + testing::internal::CaptureStderr(); + const blaze_exit_code::ExitCode exit_code = + option_processor_->GetRcFiles(workspace_layout_.get(), workspace_, cwd_, + &cmd_line, &parsed_rcs, &error); + const std::string& output = testing::internal::GetCapturedStderr(); + + EXPECT_EQ(blaze_exit_code::SUCCESS, exit_code); + EXPECT_EQ("check that this string is not modified", error); + + // Expect that GetRcFiles outputs a warning about these files that are not + // read as expected. + EXPECT_THAT(output, + HasSubstr("The following rc files are no longer being read")); + EXPECT_THAT(output, HasSubstr(workspace_rc)); + EXPECT_THAT(output, HasSubstr(binary_rc)); +} + +TEST_F( + GetRcFileTest, + GetRcFilesDoesNotWarnAboutIgnoredMasterRcFilesWhenNoMasterBazelrcIsPassed) { + std::string workspace_rc; + ASSERT_TRUE(SetUpLegacyMasterRcFileInWorkspace("", &workspace_rc)); + std::string binary_rc; + ASSERT_TRUE(SetUpLegacyMasterRcFileAlongsideBinary("", &binary_rc)); + + const CommandLine cmd_line = + CommandLine(binary_path_, {"--nomaster_bazelrc"}, "build", {}); + std::string error = "check that this string is not modified"; + std::vector<std::unique_ptr<RcFile>> parsed_rcs; + + testing::internal::CaptureStderr(); + const blaze_exit_code::ExitCode exit_code = + option_processor_->GetRcFiles(workspace_layout_.get(), workspace_, cwd_, + &cmd_line, &parsed_rcs, &error); + const std::string& output = testing::internal::GetCapturedStderr(); + + EXPECT_EQ(blaze_exit_code::SUCCESS, exit_code); + EXPECT_EQ("check that this string is not modified", error); + + // Expect that nothing is logged to stderr about ignored rc files when these + // files are disabled. + EXPECT_THAT( + output, + Not(HasSubstr("The following rc files are no longer being read"))); + EXPECT_THAT(output, Not(HasSubstr(workspace_rc))); + EXPECT_THAT(output, Not(HasSubstr(binary_rc))); +} + +TEST_F(GetRcFileTest, GetRcFilesReadsCommandLineRc) { const std::string cmdline_rc_path = blaze_util::JoinPath(workspace_, "mybazelrc"); ASSERT_TRUE( @@ -242,25 +333,24 @@ TEST_F(GetRcFileTest, GetRcFilesReadsCommandLineUserRc) { EXPECT_THAT(parsed_rcs[0].get()->sources().front(), HasSubstr("mybazelrc")); } -TEST_F(GetRcFileTest, GetRcFilesReadsUserRcInWorkspace) { - // We expect the user rc to be read when from the workspace if no alternative - // --bazelrc is provided. - std::string user_workspace_rc; - ASSERT_TRUE(SetUpUserRcFileInWorkspace("", &user_workspace_rc)); - +TEST_F(GetRcFileTest, GetRcFilesAcceptsNullCommandLineRc) { const CommandLine cmd_line = - CommandLine(binary_path_, {"--nomaster_bazelrc"}, "build", {}); + CommandLine(binary_path_, + {"--nosystem_rc", "--noworkspace_rc", "--nohome_rc", + "--bazelrc=/dev/null"}, + "build", {}); std::string error = "check that this string is not modified"; std::vector<std::unique_ptr<RcFile>> parsed_rcs; const blaze_exit_code::ExitCode exit_code = option_processor_->GetRcFiles(workspace_layout_.get(), workspace_, cwd_, &cmd_line, &parsed_rcs, &error); + // /dev/null is not an error EXPECT_EQ(blaze_exit_code::SUCCESS, exit_code); EXPECT_EQ("check that this string is not modified", error); - - const std::deque<std::string> expected_user_rc_que = {user_workspace_rc}; + // but it does technically count as a file ASSERT_EQ(1, parsed_rcs.size()); - EXPECT_EQ(expected_user_rc_que, parsed_rcs[0].get()->sources()); + const std::deque<std::string> expected_rc_que = {kNullDevice}; + EXPECT_EQ(expected_rc_que, parsed_rcs[0].get()->sources()); } using ParseOptionsTest = RcFileTest; @@ -268,17 +358,15 @@ using ParseOptionsTest = RcFileTest; TEST_F(ParseOptionsTest, IgnoreAllRcFilesIgnoresAllMasterAndUserRcFiles) { // Put fake options in different expected rc files, to check that none of them // are read. - std::string user_workspace_rc; - ASSERT_TRUE( - SetUpUserRcFileInWorkspace("startup --userfoo", &user_workspace_rc)); std::string workspace_rc; - ASSERT_TRUE(SetUpMasterRcFileInWorkspace("startup --workspacemasterfoo", - &workspace_rc)); - std::string binary_rc; - ASSERT_TRUE(SetUpMasterRcFileAlongsideBinary("startup --binarymasterfoo", - &binary_rc)); - std::string global_rc; - ASSERT_TRUE(SetUpGlobalRcFile("startup --globalmasterfoo", &global_rc)); + ASSERT_TRUE(SetUpWorkspaceRcFile("startup --workspacefoo", &workspace_rc)); + std::string system_rc; + ASSERT_TRUE(SetUpSystemRcFile("startup --systemfoo", &system_rc)); + const std::string cmdline_rc_path = + blaze_util::JoinPath(workspace_, "mybazelrc"); + ASSERT_TRUE( + blaze_util::MakeDirectories(blaze_util::Dirname(cmdline_rc_path), 0755)); + ASSERT_TRUE(blaze_util::WriteFile("startup --myfoo", cmdline_rc_path, 0755)); const std::vector<std::string> args = {binary_path_, "--ignore_all_rc_files", "build"}; @@ -297,10 +385,9 @@ TEST_F(ParseOptionsTest, IgnoreAllRcFilesIgnoresAllMasterAndUserRcFiles) { EXPECT_EQ(output, ""); } -TEST_F(ParseOptionsTest, LaterIgnoreRcFileValueWins) { +TEST_F(ParseOptionsTest, LaterIgnoreAllRcFilesValueWins) { std::string workspace_rc; - ASSERT_TRUE(SetUpMasterRcFileInWorkspace("startup --workspacemasterfoo", - &workspace_rc)); + ASSERT_TRUE(SetUpWorkspaceRcFile("startup --workspacefoo", &workspace_rc)); const std::vector<std::string> args = {binary_path_, "--ignore_all_rc_files", "--noignore_all_rc_files", "build"}; @@ -308,7 +395,7 @@ TEST_F(ParseOptionsTest, LaterIgnoreRcFileValueWins) { EXPECT_EQ(blaze_exit_code::BAD_ARGV, option_processor_->ParseOptions(args, workspace_, cwd_, &error)); ASSERT_EQ( - "Unknown startup option: '--workspacemasterfoo'.\n For more info, run " + "Unknown startup option: '--workspacefoo'.\n For more info, run " "'bazel help startup_options'.", error); @@ -318,28 +405,26 @@ TEST_F(ParseOptionsTest, LaterIgnoreRcFileValueWins) { option_processor_->PrintStartupOptionsProvenanceMessage(); const std::string& output = testing::internal::GetCapturedStderr(); - EXPECT_THAT(output, - MatchesRegex("INFO: Reading 'startup' options from .*bazel.rc: " - "--workspacemasterfoo\n")); + EXPECT_THAT( + output, + MatchesRegex("INFO: Reading 'startup' options from .*workspace.*bazelrc: " + "--workspacefoo\n")); } TEST_F(ParseOptionsTest, IgnoreAllRcFilesIgnoresCommandLineRcFileToo) { // Put fake options in different expected rc files, to check that none of them // are read. std::string workspace_rc; - ASSERT_TRUE(SetUpMasterRcFileInWorkspace("startup --workspacemasterfoo", - &workspace_rc)); - std::string binary_rc; - ASSERT_TRUE(SetUpMasterRcFileAlongsideBinary("startup --binarymasterfoo", - &binary_rc)); - std::string global_rc; - ASSERT_TRUE(SetUpGlobalRcFile("startup --globalmasterfoo", &global_rc)); + ASSERT_TRUE(SetUpWorkspaceRcFile("startup --workspacefoo", &workspace_rc)); + std::string system_rc; + ASSERT_TRUE(SetUpSystemRcFile("startup --systemfoo", &system_rc)); + const std::string cmdline_rc_path = blaze_util::JoinPath(workspace_, "mybazelrc"); ASSERT_TRUE( blaze_util::MakeDirectories(blaze_util::Dirname(cmdline_rc_path), 0755)); ASSERT_TRUE( - blaze_util::WriteFile("startup --userfoo", cmdline_rc_path, 0755)); + blaze_util::WriteFile("startup --cmdlinefoo", cmdline_rc_path, 0755)); const std::vector<std::string> args = {binary_path_, "--ignore_all_rc_files", "--bazelrc=" + cmdline_rc_path, @@ -390,9 +475,9 @@ TEST_F(ParseOptionsTest, CommandLineBazelrcHasUnknownOption) { "INFO: Reading 'startup' options from .*mybazelrc: --foo\n")); } -TEST_F(ParseOptionsTest, MasterBazelrcHasUnknownOption) { +TEST_F(ParseOptionsTest, BazelrcHasUnknownOption) { std::string workspace_rc; - ASSERT_TRUE(SetUpMasterRcFileInWorkspace("startup --foo", &workspace_rc)); + ASSERT_TRUE(SetUpWorkspaceRcFile("startup --foo", &workspace_rc)); const std::vector<std::string> args = {binary_path_, "build"}; @@ -411,20 +496,16 @@ TEST_F(ParseOptionsTest, MasterBazelrcHasUnknownOption) { option_processor_->PrintStartupOptionsProvenanceMessage(); const std::string& output = testing::internal::GetCapturedStderr(); - EXPECT_THAT( - output, - MatchesRegex( - "INFO: Reading 'startup' options from .*tools.bazel.rc: --foo\n")); + EXPECT_THAT(output, MatchesRegex("INFO: Reading 'startup' options from " + ".*workspace.*bazelrc: --foo\n")); } TEST_F(ParseOptionsTest, - IncorrectMasterBazelrcIgnoredWhenNoMasterBazelrcIsPresent) { + IncorrectWorkspaceBazelrcIgnoredWhenNoWorkspaceRcIsPresent) { std::string workspace_rc; - ASSERT_TRUE(SetUpMasterRcFileInWorkspace("startup --foo", &workspace_rc)); - std::string global_rc; - ASSERT_TRUE(SetUpGlobalRcFile("startup --globalfoo", &global_rc)); + ASSERT_TRUE(SetUpWorkspaceRcFile("startup --foo", &workspace_rc)); - const std::vector<std::string> args = {binary_path_, "--nomaster_bazelrc", + const std::vector<std::string> args = {binary_path_, "--noworkspace_rc", "build"}; // Expect no error due to the incorrect --foo. @@ -442,43 +523,13 @@ TEST_F(ParseOptionsTest, EXPECT_EQ(output, ""); } -TEST_F(ParseOptionsTest, UserBazelrcHasPriorityOverMasterBazelrc) { - std::string user_rc; - ASSERT_TRUE( - SetUpUserRcFileInWorkspace("startup --max_idle_secs=123", &user_rc)); - std::string workspace_rc; - ASSERT_TRUE(SetUpMasterRcFileInWorkspace("startup --max_idle_secs=42", - &workspace_rc)); - - const std::vector<std::string> args = {binary_path_, "build"}; - std::string error; - ASSERT_EQ(blaze_exit_code::SUCCESS, - option_processor_->ParseOptions(args, workspace_, cwd_, &error)) - << error; - - EXPECT_EQ(123, option_processor_->GetParsedStartupOptions()->max_idle_secs); - - // Check that the startup options' provenance message contains the correct - // information for the provided rc, and prints nothing for the master bazelrc. - testing::internal::CaptureStderr(); - option_processor_->PrintStartupOptionsProvenanceMessage(); - const std::string& output = testing::internal::GetCapturedStderr(); - - const std::string expected_message = "INFO: Reading 'startup' options from " + - workspace_rc + - ": --max_idle_secs=42\n" - "INFO: Reading 'startup' options from " + - user_rc + ": --max_idle_secs=123\n"; - EXPECT_EQ(output, expected_message); -} - -TEST_F(ParseOptionsTest, MasterBazelrcOverridesNoMasterBazelrc) { +TEST_F(ParseOptionsTest, PositiveOptionOverridesNegativeOption) { std::string workspace_rc; - ASSERT_TRUE(SetUpMasterRcFileInWorkspace("startup --max_idle_secs=123", - &workspace_rc)); + ASSERT_TRUE( + SetUpWorkspaceRcFile("startup --max_idle_secs=123", &workspace_rc)); - const std::vector<std::string> args = {"bazel", "--nomaster_bazelrc", - "--master_bazelrc", "build"}; + const std::vector<std::string> args = {"bazel", "--noworkspace_rc", + "--workspace_rc", "build"}; std::string error; ASSERT_EQ(blaze_exit_code::SUCCESS, option_processor_->ParseOptions(args, workspace_, cwd_, &error)) @@ -491,16 +542,16 @@ TEST_F(ParseOptionsTest, MasterBazelrcOverridesNoMasterBazelrc) { option_processor_->PrintStartupOptionsProvenanceMessage(); const std::string& output = testing::internal::GetCapturedStderr(); - EXPECT_THAT(output, MatchesRegex("INFO: Reading 'startup' options from " - ".*tools.bazel.rc: --max_idle_secs=123\n")); + EXPECT_THAT(output, + MatchesRegex("INFO: Reading 'startup' options from " + ".*workspace.*bazelrc: --max_idle_secs=123\n")); } TEST_F(ParseOptionsTest, MultipleStartupArgsInMasterBazelrcWorksCorrectly) { // Add startup flags to the master bazelrc. - std::string master_rc_path; - ASSERT_TRUE(SetUpMasterRcFileInWorkspace( - "startup --max_idle_secs=42\nstartup --io_nice_level=6", - &master_rc_path)); + std::string workspace_rc; + ASSERT_TRUE(SetUpWorkspaceRcFile( + "startup --max_idle_secs=42\nstartup --io_nice_level=6", &workspace_rc)); const std::vector<std::string> args = {binary_path_, "build"}; std::string error; @@ -519,16 +570,15 @@ TEST_F(ParseOptionsTest, MultipleStartupArgsInMasterBazelrcWorksCorrectly) { EXPECT_THAT( output, - MatchesRegex("INFO: Reading 'startup' options from .*tools.bazel.rc: " + MatchesRegex("INFO: Reading 'startup' options from .*workspace.*bazelrc: " "--max_idle_secs=42 --io_nice_level=6\n")); } -TEST_F(ParseOptionsTest, CustomBazelrcOverridesMasterBazelrc) { - // Add startup flags to the master bazelrc. - std::string master_rc_path; - ASSERT_TRUE(SetUpMasterRcFileInWorkspace( - "startup --max_idle_secs=42\nstartup --io_nice_level=6", - &master_rc_path)); +TEST_F(ParseOptionsTest, CommandLineBazelrcHasPriorityOverDefaultBazelrc) { + // Add startup flags to the workspace bazelrc. + std::string workspace_rc; + ASSERT_TRUE(SetUpWorkspaceRcFile( + "startup --max_idle_secs=42\nstartup --io_nice_level=6", &workspace_rc)); // Override one of the master bazelrc's flags in the commandline rc. const std::string cmdline_rc_path = @@ -556,7 +606,7 @@ TEST_F(ParseOptionsTest, CustomBazelrcOverridesMasterBazelrc) { EXPECT_THAT( output, - MatchesRegex("INFO: Reading 'startup' options from .*tools.*bazel.rc: " + MatchesRegex("INFO: Reading 'startup' options from .*workspace.*bazelrc: " "--max_idle_secs=42 --io_nice_level=6\n" "INFO: Reading 'startup' options from .*mybazelrc: " "--max_idle_secs=123\n")); @@ -573,11 +623,11 @@ TEST_F(ParseOptionsTest, BazelRcImportsMaintainsFlagOrdering) { imported_rc_path, 0755)); // Add startup flags the imported bazelrc. - std::string master_rc_path; - ASSERT_TRUE(SetUpMasterRcFileInWorkspace( - "startup --max_idle_secs=42\nimport " + imported_rc_path + - "\nstartup --io_nice_level=6", - &master_rc_path)); + std::string workspace_rc; + ASSERT_TRUE(SetUpWorkspaceRcFile("startup --max_idle_secs=42\nimport " + + imported_rc_path + + "\nstartup --io_nice_level=6", + &workspace_rc)); const std::vector<std::string> args = {"bazel", "build"}; std::string error; @@ -596,11 +646,11 @@ TEST_F(ParseOptionsTest, BazelRcImportsMaintainsFlagOrdering) { EXPECT_THAT( output, - MatchesRegex("INFO: Reading 'startup' options from .*tools.*bazel.rc: " + MatchesRegex("INFO: Reading 'startup' options from .*workspace.*bazelrc: " "--max_idle_secs=42\n" "INFO: Reading 'startup' options from .*myimportedbazelrc: " "--max_idle_secs=123 --io_nice_level=4\n" - "INFO: Reading 'startup' options from .*tools.*bazel.rc: " + "INFO: Reading 'startup' options from .*workspace.*bazelrc: " "--io_nice_level=6\n")); } diff --git a/src/test/java/com/google/devtools/build/lib/packages/BazelDocumentationTest.java b/src/test/java/com/google/devtools/build/lib/packages/BazelDocumentationTest.java index 79d4eea62b..8d3f7b3dfc 100644 --- a/src/test/java/com/google/devtools/build/lib/packages/BazelDocumentationTest.java +++ b/src/test/java/com/google/devtools/build/lib/packages/BazelDocumentationTest.java @@ -16,6 +16,7 @@ package com.google.devtools.build.lib.packages; import static java.nio.charset.StandardCharsets.UTF_8; +import com.google.common.collect.ImmutableSet; import com.google.common.io.Files; import com.google.devtools.build.lib.bazel.Bazel; import com.google.devtools.build.lib.bazel.rules.BazelRuleClassProvider; @@ -46,6 +47,7 @@ public class BazelDocumentationTest { DocumentationTestUtil.validateUserManual( Bazel.BAZEL_MODULES, BazelRuleClassProvider.create(), - Files.asCharSource(documentationFile, UTF_8).read()); + Files.asCharSource(documentationFile, UTF_8).read(), + ImmutableSet.of()); } } diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/DocumentationTestUtil.java b/src/test/java/com/google/devtools/build/lib/packages/util/DocumentationTestUtil.java index ca5ecb32b0..fafefe98a0 100644 --- a/src/test/java/com/google/devtools/build/lib/packages/util/DocumentationTestUtil.java +++ b/src/test/java/com/google/devtools/build/lib/packages/util/DocumentationTestUtil.java @@ -57,7 +57,8 @@ public abstract class DocumentationTestUtil { public static void validateUserManual( List<Class<? extends BlazeModule>> modules, ConfiguredRuleClassProvider ruleClassProvider, - String documentationSource) + String documentationSource, + Set<String> extraValidOptions) throws Exception { // if there is a class missing, one can find it using // find . -name "*.java" -exec grep -Hn "@Option(name = " {} \; | grep "xxx" @@ -71,9 +72,7 @@ public abstract class DocumentationTestUtil { BlazeCommandUtils.getStartupOptions(blazeModules)) { validOptions.addAll(Options.getDefaults(optionsClass).asMap().keySet()); } - // --bazelrc and --master_bazelrc are aliases for blaze equivalents. Add these explicitly. - validOptions.add("bazelrc"); - validOptions.add("master_bazelrc"); + validOptions.addAll(extraValidOptions); // collect all command options ServerBuilder serverBuilder = new ServerBuilder(); diff --git a/src/test/shell/integration/bazel_command_log_test.sh b/src/test/shell/integration/bazel_command_log_test.sh index 8094e65a19..6379601631 100755 --- a/src/test/shell/integration/bazel_command_log_test.sh +++ b/src/test/shell/integration/bazel_command_log_test.sh @@ -44,6 +44,7 @@ function strip_lines_from_bazel_cc() { -e '/server needs to be killed, because the startup options are different/d' \ -e '/^WARNING: Waiting for server process to terminate (waited 5 seconds, waiting at most 60)$/d' \ -e '/^WARNING: The startup option --host_javabase is deprecated; prefer --server_javabase.$/d' \ + -e '/^WARNING: The home directory is not defined, no home_rc will be looked for.$/d' \ $TEST_log) echo "$clean_log" > $TEST_log |