OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "tools/gn/setup.h" | 5 #include "tools/gn/setup.h" |
6 | 6 |
7 #include <stdlib.h> | 7 #include <stdlib.h> |
8 #include <algorithm> | 8 #include <algorithm> |
9 #include <sstream> | 9 #include <sstream> |
10 #include <utility> | 10 #include <utility> |
11 | 11 |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
14 #include "base/files/file_path.h" | 14 #include "base/files/file_path.h" |
15 #include "base/files/file_util.h" | 15 #include "base/files/file_util.h" |
16 #include "base/process/launch.h" | 16 #include "base/process/launch.h" |
17 #include "base/strings/string_split.h" | 17 #include "base/strings/string_split.h" |
18 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 19 #include "base/strings/sys_string_conversions.h" |
19 #include "base/strings/utf_string_conversions.h" | 20 #include "base/strings/utf_string_conversions.h" |
20 #include "build/build_config.h" | 21 #include "build/build_config.h" |
21 #include "tools/gn/commands.h" | 22 #include "tools/gn/commands.h" |
22 #include "tools/gn/filesystem_utils.h" | 23 #include "tools/gn/filesystem_utils.h" |
23 #include "tools/gn/input_file.h" | 24 #include "tools/gn/input_file.h" |
24 #include "tools/gn/parse_tree.h" | 25 #include "tools/gn/parse_tree.h" |
25 #include "tools/gn/parser.h" | 26 #include "tools/gn/parser.h" |
26 #include "tools/gn/source_dir.h" | 27 #include "tools/gn/source_dir.h" |
27 #include "tools/gn/source_file.h" | 28 #include "tools/gn/source_file.h" |
28 #include "tools/gn/standard_out.h" | 29 #include "tools/gn/standard_out.h" |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 DCHECK(item); | 143 DCHECK(item); |
143 main_loop->PostTask(FROM_HERE, base::Bind(&Builder::ItemDefined, builder, | 144 main_loop->PostTask(FROM_HERE, base::Bind(&Builder::ItemDefined, builder, |
144 base::Passed(&item))); | 145 base::Passed(&item))); |
145 } | 146 } |
146 | 147 |
147 void DecrementWorkCount() { | 148 void DecrementWorkCount() { |
148 g_scheduler->DecrementWorkCount(); | 149 g_scheduler->DecrementWorkCount(); |
149 } | 150 } |
150 | 151 |
151 #if defined(OS_WIN) | 152 #if defined(OS_WIN) |
| 153 |
| 154 // Given the path to a batch file that runs Python, extracts the name of the |
| 155 // executable actually implementing Python. Generally people write a batch file |
| 156 // to put something named "python" on the path, which then just redirects to |
| 157 // a python.exe somewhere else. This step decodes that setup. On failure, |
| 158 // returns empty path. |
| 159 base::FilePath PythonBatToExe(const base::FilePath& bat_path) { |
| 160 // Note exciting double-quoting to allow spaces. The /c switch seems to check |
| 161 // for quotes around the whole thing and then deletes them. If you want to |
| 162 // quote the first argument in addition (to allow for spaces in the Python |
| 163 // path, you need *another* set of quotes around that, likewise, we need |
| 164 // two quotes at the end. |
| 165 base::string16 command = L"cmd.exe /c \"\""; |
| 166 command.append(bat_path.value()); |
| 167 command.append(L"\" -c \"import sys; print sys.executable\"\""); |
| 168 |
| 169 std::string python_path; |
| 170 if (base::GetAppOutput(command, &python_path)) { |
| 171 base::TrimWhitespaceASCII(python_path, base::TRIM_ALL, &python_path); |
| 172 |
| 173 // Python uses the system multibyte code page for sys.executable. |
| 174 base::FilePath exe_path(base::SysNativeMBToWide(python_path)); |
| 175 |
| 176 // Check for reasonable output, cmd may have output an error message. |
| 177 if (base::PathExists(exe_path)) |
| 178 return exe_path; |
| 179 } |
| 180 return base::FilePath(); |
| 181 } |
| 182 |
152 const base::char16 kPythonExeName[] = L"python.exe"; | 183 const base::char16 kPythonExeName[] = L"python.exe"; |
| 184 const base::char16 kPythonBatName[] = L"python.bat"; |
153 | 185 |
154 base::FilePath FindWindowsPython() { | 186 base::FilePath FindWindowsPython() { |
155 base::char16 current_directory[MAX_PATH]; | 187 base::char16 current_directory[MAX_PATH]; |
156 ::GetCurrentDirectory(MAX_PATH, current_directory); | 188 ::GetCurrentDirectory(MAX_PATH, current_directory); |
157 | 189 |
158 // First search for python.exe in the current directory. | 190 // First search for python.exe in the current directory. |
159 base::FilePath cur_dir_candidate_exe = | 191 base::FilePath cur_dir_candidate_exe = |
160 base::FilePath(current_directory).Append(kPythonExeName); | 192 base::FilePath(current_directory).Append(kPythonExeName); |
161 if (base::PathExists(cur_dir_candidate_exe)) | 193 if (base::PathExists(cur_dir_candidate_exe)) |
162 return cur_dir_candidate_exe; | 194 return cur_dir_candidate_exe; |
163 | 195 |
164 // Get the path. | 196 // Get the path. |
165 const base::char16 kPathEnvVarName[] = L"Path"; | 197 const base::char16 kPathEnvVarName[] = L"Path"; |
166 DWORD path_length = ::GetEnvironmentVariable(kPathEnvVarName, nullptr, 0); | 198 DWORD path_length = ::GetEnvironmentVariable(kPathEnvVarName, nullptr, 0); |
167 if (path_length == 0) | 199 if (path_length == 0) |
168 return base::FilePath(); | 200 return base::FilePath(); |
169 scoped_ptr<base::char16[]> full_path(new base::char16[path_length]); | 201 scoped_ptr<base::char16[]> full_path(new base::char16[path_length]); |
170 DWORD actual_path_length = | 202 DWORD actual_path_length = |
171 ::GetEnvironmentVariable(kPathEnvVarName, full_path.get(), path_length); | 203 ::GetEnvironmentVariable(kPathEnvVarName, full_path.get(), path_length); |
172 CHECK_EQ(path_length, actual_path_length + 1); | 204 CHECK_EQ(path_length, actual_path_length + 1); |
173 | 205 |
174 // Search for python.exe in the path. | 206 // Search for python.exe in the path. |
175 for (const auto& component : base::SplitStringPiece( | 207 for (const auto& component : base::SplitStringPiece( |
176 base::StringPiece16(full_path.get(), path_length), L";", | 208 base::StringPiece16(full_path.get(), path_length), L";", |
177 base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { | 209 base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { |
178 base::FilePath candidate_exe = | 210 base::FilePath candidate_exe = |
179 base::FilePath(component).Append(kPythonExeName); | 211 base::FilePath(component).Append(kPythonExeName); |
180 if (base::PathExists(candidate_exe)) | 212 if (base::PathExists(candidate_exe)) |
181 return candidate_exe; | 213 return candidate_exe; |
| 214 |
| 215 // Also allow python.bat, but convert into the .exe. |
| 216 base::FilePath candidate_bat = |
| 217 base::FilePath(component).Append(kPythonBatName); |
| 218 if (base::PathExists(candidate_bat)) { |
| 219 base::FilePath python_exe = PythonBatToExe(candidate_bat); |
| 220 if (!python_exe.empty()) |
| 221 return python_exe; |
| 222 } |
182 } | 223 } |
183 return base::FilePath(); | 224 return base::FilePath(); |
184 } | 225 } |
185 #endif | 226 #endif |
186 | 227 |
187 } // namespace | 228 } // namespace |
188 | 229 |
189 const char Setup::kBuildArgFileName[] = "args.gn"; | 230 const char Setup::kBuildArgFileName[] = "args.gn"; |
190 | 231 |
191 Setup::Setup() | 232 Setup::Setup() |
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
650 if (err.has_error()) { | 691 if (err.has_error()) { |
651 err.PrintToStdout(); | 692 err.PrintToStdout(); |
652 return false; | 693 return false; |
653 } | 694 } |
654 } | 695 } |
655 build_settings_.set_exec_script_whitelist(std::move(whitelist)); | 696 build_settings_.set_exec_script_whitelist(std::move(whitelist)); |
656 } | 697 } |
657 | 698 |
658 return true; | 699 return true; |
659 } | 700 } |
OLD | NEW |