public static RemoteProjectBuilder GetProjectBuilder (TargetRuntime runtime, string minToolsVersion, string file, string solutionFile)
{
lock (builders) {
//attempt to use 12.0 builder first if available
string toolsVersion = "12.0";
string binDir = runtime.GetMSBuildBinPath ("12.0");
if (binDir == null) {
//fall back to 4.0, we know it's always available
toolsVersion = "4.0";
}
//check the ToolsVersion we found can handle the project
Version tv, mtv;
if (Version.TryParse (toolsVersion, out tv) && Version.TryParse (minToolsVersion, out mtv) && tv < mtv) {
string error = null;
if (runtime is MsNetTargetRuntime && minToolsVersion == "12.0")
error = "MSBuild 2013 is not installed. Please download and install it from " +
"http://www.microsoft.com/en-us/download/details.aspx?id=40760";
throw new InvalidOperationException (error ?? string.Format (
"Runtime '{0}' does not have MSBuild '{1}' ToolsVersion installed",
runtime.Id, toolsVersion)
);
}
//one builder per solution
string builderKey = runtime.Id + " # " + solutionFile;
RemoteBuildEngine builder;
if (builders.TryGetValue (builderKey, out builder)) {
builder.ReferenceCount++;
return new RemoteProjectBuilder (file, builder);
}
//always start the remote process explicitly, even if it's using the current runtime and fx
//else it won't pick up the assembly redirects from the builder exe
var exe = GetExeLocation (runtime, toolsVersion);
MonoDevelop.Core.Execution.RemotingService.RegisterRemotingChannel ();
var pinfo = new ProcessStartInfo (exe) {
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardError = true,
RedirectStandardInput = true,
};
runtime.GetToolsExecutionEnvironment ().MergeTo (pinfo);
Process p = null;
try {
p = runtime.ExecuteAssembly (pinfo);
p.StandardInput.WriteLine (Process.GetCurrentProcess ().Id.ToString ());
string sref = p.StandardError.ReadLine ();
byte[] data = Convert.FromBase64String (sref);
MemoryStream ms = new MemoryStream (data);
BinaryFormatter bf = new BinaryFormatter ();
var engine = (IBuildEngine)bf.Deserialize (ms);
engine.Initialize (solutionFile, GettextCatalog.UICulture);
builder = new RemoteBuildEngine (p, engine);
} catch {
if (p != null) {
try {
p.Kill ();
} catch { }
}
throw;
}
builders [builderKey] = builder;
builder.ReferenceCount = 1;
return new RemoteProjectBuilder (file, builder);
}
}