Index: tools/gn/setup.cc |
diff --git a/tools/gn/setup.cc b/tools/gn/setup.cc |
index 774d877691e58ba8cfac76df38e2a4ceae92b9c3..459b87bc5d6e3da36a1856dc89b192131d33f513 100644 |
--- a/tools/gn/setup.cc |
+++ b/tools/gn/setup.cc |
@@ -16,6 +16,7 @@ |
#include "base/process/launch.h" |
#include "base/strings/string_split.h" |
#include "base/strings/string_util.h" |
+#include "base/strings/sys_string_conversions.h" |
#include "base/strings/utf_string_conversions.h" |
#include "build/build_config.h" |
#include "tools/gn/commands.h" |
@@ -149,7 +150,38 @@ void DecrementWorkCount() { |
} |
#if defined(OS_WIN) |
+ |
+// Given the path to a batch file that runs Python, extracts the name of the |
+// executable actually implementing Python. Generally people write a batch file |
+// to put something named "python" on the path, which then just redirects to |
+// a python.exe somewhere else. This step decodes that setup. On failure, |
+// returns empty path. |
+base::FilePath PythonBatToExe(const base::FilePath& bat_path) { |
+ // Note exciting double-quoting to allow spaces. The /c switch seems to check |
+ // for quotes around the whole thing and then deletes them. If you want to |
+ // quote the first argument in addition (to allow for spaces in the Python |
+ // path, you need *another* set of quotes around that, likewise, we need |
+ // two quotes at the end. |
+ base::string16 command = L"cmd.exe /c \"\""; |
+ command.append(bat_path.value()); |
+ command.append(L"\" -c \"import sys; print sys.executable\"\""); |
+ |
+ std::string python_path; |
+ if (base::GetAppOutput(command, &python_path)) { |
+ base::TrimWhitespaceASCII(python_path, base::TRIM_ALL, &python_path); |
+ |
+ // Python uses the system multibyte code page for sys.executable. |
+ base::FilePath exe_path(base::SysNativeMBToWide(python_path)); |
+ |
+ // Check for reasonable output, cmd may have output an error message. |
+ if (base::PathExists(exe_path)) |
+ return exe_path; |
+ } |
+ return base::FilePath(); |
+} |
+ |
const base::char16 kPythonExeName[] = L"python.exe"; |
+const base::char16 kPythonBatName[] = L"python.bat"; |
base::FilePath FindWindowsPython() { |
base::char16 current_directory[MAX_PATH]; |
@@ -179,6 +211,15 @@ base::FilePath FindWindowsPython() { |
base::FilePath(component).Append(kPythonExeName); |
if (base::PathExists(candidate_exe)) |
return candidate_exe; |
+ |
+ // Also allow python.bat, but convert into the .exe. |
+ base::FilePath candidate_bat = |
+ base::FilePath(component).Append(kPythonBatName); |
+ if (base::PathExists(candidate_bat)) { |
+ base::FilePath python_exe = PythonBatToExe(candidate_bat); |
+ if (!python_exe.empty()) |
+ return python_exe; |
+ } |
} |
return base::FilePath(); |
} |