Repository: bazelbuild/bazel
Issue: Windows: Bazel requires MSYS for every command
Labels: type: bug
P2
area-Windows
team-OSS

### Description of the problem / feature request:

On a fresh Windows 10 installation with only Bazel 0.18.0 and MSVC redistributable DLLs [1] and _without_ MSYS, running any command in a minimal workspace (just an empty WORKSPACE file) requires MSYS bash.

[1] https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x64.exe


### Bugs: what's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.

On a fresh Windows 10:

1. download Bazel 0.18.0 
2. install the [MSVC redistributable DLLs](https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x64.exe)
3. in cmd.exe:
  ```
  C:\>md c:\src\foo

  C:\>cd c:\src\foo

  C:\src\foo>echo # hello>WORKSPACE

  C:\src\foo>bazel info release
  Bazel on Windows requires MSYS2 Bash, but we could not find it.
  If you do not have it installed, you can install MSYS2 from
         http://repo.msys2.org/distrib/msys2-x86_64-latest.exe

  If you already have it installed but Bazel cannot find it,
  set BAZEL_SH environment variable to its location:
         set BAZEL_SH=c:\path\to\msys2\usr\bin\bash.exe
  [bazel ERROR src/main/cpp/blaze_util_windows.cc:1453] bash.exe not found on PATH
  [bazel INFO src/main/cpp/blaze_util_windows.cc:1473] BAZEL_SH detection took 0 msec, found
  ```

### What operating system are you running Bazel on?

Windows Server 2016 (v1607)

Issue comments:
This is a bad first-time experience. See https://github.com/bazelbuild/bazel/issues/5254
@laszlocsomor 

I get the same error: `Bazel on Windows requires MSYS2 Bash, but we could not find it` for every command using the binaries for Bazel  provided by the `@bazel/bazel` v0.20.0 npm package.

So the only way to run Bazel on Windows is to install MSYS2 bash and disable the path conversion?

The doc says to prefer Command Prompt or PowerShell: https://docs.bazel.build/versions/master/windows.html#running-bazel-msys2-shell-vs-command-prompt-vs-powershell
@robisim74 : try Bazel 0.21, that should no longer complain about a missing MSYS2 Bash. Please let me know if you still find problems with it!
Ok, thanks! I will try to install v0.21 (still not published on npm) and let you know.
@laszlocsomor I tried to download version 0.21 directly on my machine in `c:\bazel`, and run `C:\> .\bazel help`, but nothing: same error.

For the moment, I installed MSYS2 bash to work.
@robisim74 : You're right. I never merged the corresponding PR (https://github.com/bazelbuild/bazel/pull/6582) because it broke some tests.

Installing MSYS2 is the best "workaround" for now. Sorry about that.
Bazel 0.23 still complains about missing MSYS2:
```
C:\src\tmp>c:\Users\laszlocsomor\Downloads\bazel-0.23.0-windows-x86_64.exe info release
ERROR: bash.exe not found on PATH
Bazel on Windows requires MSYS2 Bash, but we could not find it.
If you do not have it installed, you can install MSYS2 from
       http://repo.msys2.org/distrib/msys2-x86_64-latest.exe

If you already have it installed but Bazel cannot find it,
set BAZEL_SH environment variable to its location:
       set BAZEL_SH=c:\path\to\msys2\usr\bin\bash.exe
[bazel ERROR src/main/cpp/blaze_util_windows.cc:1462] bash.exe not found on PATH
[bazel INFO src/main/cpp/blaze_util_windows.cc:1477] BAZEL_SH detection took 0 msec, found
```

Pull request review comments:

Patch that resolved the issue:
diff --git a/src/main/cpp/blaze.cc b/src/main/cpp/blaze.cc
index f31155ff0a6cdb..da1dc5ff175c5b 100644
--- a/src/main/cpp/blaze.cc
+++ b/src/main/cpp/blaze.cc
@@ -1546,7 +1546,7 @@ int Main(int argc, const char *argv[], WorkspaceLayout *workspace_layout,
   // Must be done before command line parsing.
   // ParseOptions already populate --client_env, so detect bash before it
   // happens.
-  DetectBashOrDie();
+  (void) DetectBashAndExportBazelSh();
 #endif  // if defined(_WIN32) || defined(__CYGWIN__)
 
   globals->binary_path = CheckAndGetBinaryPath(argv[0]);
diff --git a/src/main/cpp/blaze_util_platform.h b/src/main/cpp/blaze_util_platform.h
index 832bfe0eca8065..3686aa72c238fb 100644
--- a/src/main/cpp/blaze_util_platform.h
+++ b/src/main/cpp/blaze_util_platform.h
@@ -264,7 +264,6 @@ bool UnlimitCoredumps();
 
 #if defined(_WIN32) || defined(__CYGWIN__)
 std::string DetectBashAndExportBazelSh();
-void DetectBashOrDie();
 #endif  // if defined(_WIN32) || defined(__CYGWIN__)
 
 // This function has no effect on Unix platforms.
diff --git a/src/main/cpp/blaze_util_windows.cc b/src/main/cpp/blaze_util_windows.cc
index b113c54dfefd45..a89a9afe5c59d0 100644
--- a/src/main/cpp/blaze_util_windows.cc
+++ b/src/main/cpp/blaze_util_windows.cc
@@ -1452,17 +1452,9 @@ static string GetBinaryFromPath(const string& binary_name) {
   return string();
 }
 
-static string LocateBash() {
+static string LocateBashMaybe() {
   string msys_bash = GetMsysBash();
-  if (!msys_bash.empty()) {
-    return msys_bash;
-  }
-
-  string result = GetBinaryFromPath("bash.exe");
-  if (result.empty()) {
-    BAZEL_LOG(ERROR) << "bash.exe not found on PATH";
-  }
-  return result;
+  return msys_bash.empty() ? GetBinaryFromPath("bash.exe") : msys_bash;
 }
 
 string DetectBashAndExportBazelSh() {
@@ -1473,33 +1465,19 @@ string DetectBashAndExportBazelSh() {
 
   uint64_t start = blaze::GetMillisecondsMonotonic();
 
-  bash = LocateBash();
+  bash = LocateBashMaybe();
   uint64_t end = blaze::GetMillisecondsMonotonic();
-  BAZEL_LOG(INFO) << "BAZEL_SH detection took " << end - start
-                  << " msec, found " << bash.c_str();
-
-  if (!bash.empty()) {
+  if (bash.empty()) {
+    BAZEL_LOG(INFO) << "BAZEL_SH detection took " << end - start
+                    << " msec, not found";
+  } else {
+    BAZEL_LOG(INFO) << "BAZEL_SH detection took " << end - start
+                    << " msec, found " << bash.c_str();
     // Set process environment variable.
     blaze::SetEnv("BAZEL_SH", bash);
   }
-  return bash;
-}
 
-void DetectBashOrDie() {
-  string bash = DetectBashAndExportBazelSh();
-  if (bash.empty()) {
-    // TODO(bazel-team) should this be printed to stderr? If so, it should use
-    // BAZEL_LOG(ERROR)
-    printf(
-        "Bazel on Windows requires MSYS2 Bash, but we could not find it.\n"
-        "If you do not have it installed, you can install MSYS2 from\n"
-        "       http://repo.msys2.org/distrib/msys2-x86_64-latest.exe\n"
-        "\n"
-        "If you already have it installed but Bazel cannot find it,\n"
-        "set BAZEL_SH environment variable to its location:\n"
-        "       set BAZEL_SH=c:\\path\\to\\msys2\\usr\\bin\\bash.exe\n");
-    exit(1);
-  }
+  return bash;
 }
 
 void EnsurePythonPathOption(std::vector<string>* options) {


Test patch: