summaryrefslogtreecommitdiffstats
path: root/src/msvc_helper-win32.cc
diff options
context:
space:
mode:
authorEvan Martin <martine@danga.com>2012-08-12 21:52:18 (GMT)
committerEvan Martin <martine@danga.com>2012-08-12 21:52:18 (GMT)
commit1843f550d9b8b6d271cefdfb5fffd150bb8ef069 (patch)
tree6d4e9aa59249d5397f954ba541333126c5d52f38 /src/msvc_helper-win32.cc
parent031237133e33ee4eb5e9641396d6b0f566b575c8 (diff)
downloadNinja-1843f550d9b8b6d271cefdfb5fffd150bb8ef069.zip
Ninja-1843f550d9b8b6d271cefdfb5fffd150bb8ef069.tar.gz
Ninja-1843f550d9b8b6d271cefdfb5fffd150bb8ef069.tar.bz2
add subprocess-spawning to msvc_helper
Rather than using subprocess.h, reimplement the subprocess code. This allows: 1) using anonymous (instead of named) pipes 2) not using all the completion port craziness 3) printing the output as it happens 4) further variation, like adjusting the environment (in a forthcoming change) without affecting the main subprocess code
Diffstat (limited to 'src/msvc_helper-win32.cc')
-rw-r--r--src/msvc_helper-win32.cc98
1 files changed, 97 insertions, 1 deletions
diff --git a/src/msvc_helper-win32.cc b/src/msvc_helper-win32.cc
index ff18e80..ac957e4 100644
--- a/src/msvc_helper-win32.cc
+++ b/src/msvc_helper-win32.cc
@@ -15,8 +15,9 @@
#include "msvc_helper.h"
#include <string.h>
+#include <windows.h>
-#include "string_piece.h"
+#include "util.h"
// static
string CLWrapper::FilterShowIncludes(const string& line) {
@@ -33,3 +34,98 @@ string CLWrapper::FilterShowIncludes(const string& line) {
}
return "";
}
+
+int CLWrapper::Run(const string& command, string* extra_output) {
+ SECURITY_ATTRIBUTES security_attributes = {};
+ security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
+ security_attributes.bInheritHandle = TRUE;
+
+ // Must be inheritable so subprocesses can dup to children.
+ HANDLE nul = CreateFile("NUL", GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE |
+ FILE_SHARE_DELETE,
+ &security_attributes, OPEN_EXISTING, 0, NULL);
+ if (nul == INVALID_HANDLE_VALUE)
+ Fatal("couldn't open nul");
+
+ HANDLE stdout_read, stdout_write;
+ if (!CreatePipe(&stdout_read, &stdout_write, &security_attributes, 0))
+ Win32Fatal("CreatePipe");
+
+ if (!SetHandleInformation(stdout_read, HANDLE_FLAG_INHERIT, 0))
+ Win32Fatal("SetHandleInformation");
+
+ PROCESS_INFORMATION process_info = {};
+ STARTUPINFO startup_info = {};
+ startup_info.cb = sizeof(STARTUPINFO);
+ startup_info.hStdInput = nul;
+ startup_info.hStdError = stdout_write;
+ startup_info.hStdOutput = stdout_write;
+ startup_info.dwFlags |= STARTF_USESTDHANDLES;
+
+ if (!CreateProcessA(NULL, (char*)command.c_str(), NULL, NULL,
+ /* inherit handles */ TRUE, 0,
+ NULL, NULL,
+ &startup_info, &process_info)) {
+ Win32Fatal("CreateProcess");
+ }
+
+ if (!CloseHandle(nul) ||
+ !CloseHandle(stdout_write)) {
+ Win32Fatal("CloseHandle");
+ }
+
+ // Read output of the subprocess and parse it.
+ string output;
+ DWORD read_len = 1;
+ while (read_len) {
+ char buf[64 << 10];
+ read_len = 0;
+ if (!::ReadFile(stdout_read, buf, sizeof(buf), &read_len, NULL) &&
+ GetLastError() != ERROR_BROKEN_PIPE) {
+ Win32Fatal("ReadFile");
+ }
+ output.append(buf, read_len);
+
+ // Loop over all lines in the output and process them.
+ for (;;) {
+ size_t ofs = output.find_first_of("\r\n");
+ if (ofs == string::npos)
+ break;
+ string line = output.substr(0, ofs);
+
+ string include = FilterShowIncludes(line);
+ if (!include.empty()) {
+ includes_.push_back(include);
+ } else {
+ if (extra_output) {
+ extra_output->append(line);
+ extra_output->append("\n");
+ } else {
+ printf("%s\n", line.c_str());
+ }
+ }
+
+ if (ofs < output.size() && output[ofs] == '\r')
+ ++ofs;
+ if (ofs < output.size() && output[ofs] == '\n')
+ ++ofs;
+ output = output.substr(ofs);
+ }
+ }
+
+ if (WaitForSingleObject(process_info.hProcess, INFINITE) == WAIT_FAILED)
+ Win32Fatal("WaitForSingleObject");
+
+ DWORD exit_code = 0;
+ if (!GetExitCodeProcess(process_info.hProcess, &exit_code))
+ Win32Fatal("GetExitCodeProcess");
+
+ if (!CloseHandle(stdout_read) ||
+ !CloseHandle(process_info.hProcess) ||
+ !CloseHandle(process_info.hThread)) {
+ Win32Fatal("CloseHandle");
+ }
+
+ return exit_code;
+}