public int InvokeCompiler(IEnumerable<string> args, Action<string> onStdErr, Action<string> onStdOut, bool showIncludes, List<string> foundIncludes)
{
int rv = -1;
bool retry;
do
{
retry = false;
Logging.Emit("invoking real compiler: {0} {1} [{2}]", CompilerExe, WorkingDirectory, string.Join(" ", args.ToArray()));
if (string.IsNullOrWhiteSpace(CompilerExe) || !FileUtils.Exists(CompilerExe))
throw new FileNotFoundException("cant find cl.exe");
if (string.IsNullOrWhiteSpace(compworkdir))
throw new InvalidOperationException("no working directory set");
if (compenvs == null || compenvs.Count == 0)
throw new InvalidOperationException("no environment set");
var cla = JoinAguments(FixupArgs(args));
if (showIncludes) cla += " /showIncludes";
var psi = new ProcessStartInfo(CompilerExe, cla)
{
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true,
WorkingDirectory = compworkdir,
};
psi.EnvironmentVariables.Clear();
foreach (var row in compenvs)
{
psi.EnvironmentVariables[row.Key] = row.Value;
}
psi.EnvironmentVariables["PATH"] = Path.GetDirectoryName(CompilerExe) + ";" + psi.EnvironmentVariables["PATH"];
psi.ErrorDialog = true;
var p = Process.Start(psi);
p.OutputDataReceived += (o, a) =>
{
if (a.Data != null)
{
if (showIncludes && a.Data.StartsWith("Note: including file:"))
{
var inc = a.Data.Substring("Note: including file:".Length + 1).TrimStart(' ');
if (inc.Contains('/'))
{
inc = inc.Replace('/', '\\');
}
foundIncludes.Add(inc);
}
else
{
if (StdOutputCallback != null) {
StdOutputCallback(a.Data + Environment.NewLine);
}
if (onStdOut != null) {
onStdOut(a.Data + Environment.NewLine);
}
//if (Settings.DebugEnabled)
// Logging.Emit("stdout {0}", a.Data);
}
}
};
p.ErrorDataReceived += (o, a) =>
{
if (a.Data != null)
{
if (StdErrorCallback != null) {
StdErrorCallback(a.Data + Environment.NewLine);
}
if (onStdErr != null) {
onStdErr(a.Data + Environment.NewLine);
}
if (Settings.DebugEnabled)
Logging.Emit("stderr {0}", a.Data);
}
};
p.BeginErrorReadLine();
p.BeginOutputReadLine();
p.WaitForExit();
rv = p.ExitCode;
p.Close();
Logging.Emit("cl exit {0}", rv);
if (rv == 0)
{
if (IsSupported)
{
if (!string.IsNullOrEmpty(ObjectTarget))
{
var sw = new Stopwatch();
sw.Start();
int waited = 0;
while (!File.Exists(ObjectTarget) && (sw.ElapsedMilliseconds < 100000))
{
Logging.Emit("compiler slow to write object! {0} {1}ms", ObjectTarget, (int)sw.Elapsed.TotalMilliseconds);
waited++;
System.Threading.Thread.Sleep(Math.Min(1000, 100 * waited));
}
if (!File.Exists(ObjectTarget))
{
string logmsg = string.Format("cl exited with zero but failed to create the object file! {0}", ObjectTarget);
// let the retry system have a go with this
Logging.Warning("{0}, re-running!", logmsg);
retry = true;
}
Logging.Emit("output: {0} seen", ObjectTarget);
}
}
}
if (rv != 0)
{
Logging.Emit("non-zero exit");
}
} while (retry);
return rv;
}