/// <summary> /// Compiles the fragment and adds the compile time to the list /// </summary> public void Compile(DirectoryReference IntermediateDir, int SampleIdx) { FileReference LogFile = FileReference.Combine(IntermediateDir, String.Format("{0}.sample{1}.txt", UniqueName, SampleIdx + 1)); using (StreamWriter LogWriter = new StreamWriter(LogFile.FullName, true)) { FileReference ResponseFile = FileReference.Combine(IntermediateDir, String.Format("{0}.sample{1}.response", UniqueName, SampleIdx + 1)); // Write the response file CompileEnvironment WorkerCompileEnvironment = new CompileEnvironment(CompileEnvironment); if (WorkerCompileEnvironment.CompilerType == CompilerType.Clang) { WorkerCompileEnvironment.Options.Add(new CompileOption("-o", FileReference.Combine(IntermediateDir, UniqueName + ".o").FullName)); } else if (WorkerCompileEnvironment.CompilerType == CompilerType.VisualC) { WorkerCompileEnvironment.Options.RemoveAll(x => x.Name == "/Z7" || x.Name == "/Zi" || x.Name == "/ZI"); WorkerCompileEnvironment.Options.Add(new CompileOption("/Fo", IntermediateFile.FullName + ".obj")); WorkerCompileEnvironment.Options.Add(new CompileOption("/WX", null)); WorkerCompileEnvironment.Options.Add(new CompileOption("/Bt", null)); } else { throw new NotImplementedException(); } WorkerCompileEnvironment.WriteResponseFile(ResponseFile, IntermediateFile); // Spawn the compiler using (Process NewProcess = new Process()) { List <string> LogLines = new List <string>(); DataReceivedEventHandler OutputHandler = (x, y) => { if (!String.IsNullOrEmpty(y.Data)) { LogWriter.WriteLine(y.Data); LogLines.Add(y.Data); } }; NewProcess.StartInfo.FileName = CompileEnvironment.Compiler.FullName; NewProcess.StartInfo.Arguments = String.Format("\"@{0}\"", ResponseFile); NewProcess.StartInfo.UseShellExecute = false; NewProcess.StartInfo.RedirectStandardOutput = true; NewProcess.StartInfo.RedirectStandardError = true; NewProcess.OutputDataReceived += OutputHandler; NewProcess.ErrorDataReceived += OutputHandler; Stopwatch Timer = Stopwatch.StartNew(); NewProcess.Start(); NewProcess.BeginOutputReadLine(); NewProcess.BeginErrorReadLine(); if (NewProcess.WaitForExit(10 * 60 * 1000)) { // WaitForExit with a timeout does not wait for output data to be flushed, so issue a normal WaitForExit call here too NewProcess.WaitForExit(); Timer.Stop(); FragmentTimingSample Sample = new FragmentTimingSample(); Sample.TotalTime = Timer.Elapsed.TotalSeconds; if (WorkerCompileEnvironment.CompilerType == CompilerType.VisualC) { foreach (string LogLine in LogLines) { if (TryParseCompileTime(LogLine, "c1xx.dll", out Sample.FrontendTime)) { break; } } foreach (string LogLine in LogLines) { if (TryParseCompileTime(LogLine, "c2.dll", out Sample.BackendTime)) { break; } } } Samples.Add(Sample); LogWriter.WriteLine("Compile finished in {0}s", Timer.Elapsed.TotalSeconds); } else { NewProcess.Kill(); NewProcess.WaitForExit(); Timer.Stop(); Samples.Add(new FragmentTimingSample()); LogWriter.WriteLine("Timeout; terminating process after {0}s", Timer.Elapsed.TotalSeconds); } LogWriter.WriteLine(); } } }