internal static async Task<RemoteProjectBuilder> GetProjectBuilder (TargetRuntime runtime, string minToolsVersion, string file, string solutionFile, int customId, bool lockBuilder = false) { using (await buildersLock.EnterAsync ()) { //attempt to use 14.0 builder first if available string toolsVersion = "14.0"; string binDir = runtime.GetMSBuildBinPath ("14.0"); if (binDir == null) { toolsVersion = "12.0"; 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 // The check is only done for the .NET framework since Mono doesn't really have the concept of ToolsVersion. // On Mono we'll just try to build with whatever is installed. Version tv, mtv; if (runtime is MsNetTargetRuntime && Version.TryParse (toolsVersion, out tv) && Version.TryParse (minToolsVersion, out mtv) && tv < mtv) { string error = null; if (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 + " # " + customId; RemoteBuildEngine builder = null; if (lockBuilder) { foreach (var b in builders.GetBuilders (builderKey)) { if (b.Lock ()) { builder = b; break; } b.Unlock (); } } else builder = builders.GetBuilders (builderKey).FirstOrDefault (); if (builder != null) { builder.ReferenceCount++; return new RemoteProjectBuilder (file, builder); } return await Task.Run (() => { //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 { IBuildEngine engine; if (!runLocal) { p = runtime.ExecuteAssembly (pinfo); // The builder app will write the build engine reference // after reading the process id from the standard input ManualResetEvent ev = new ManualResetEvent (false); string responseKey = "[MonoDevelop]"; string sref = null; p.ErrorDataReceived += (sender, e) => { if (e.Data == null) { if (string.IsNullOrEmpty (sref)) LoggingService.LogError ("The MSBuild builder exited before initializing"); return; } if (e.Data.StartsWith (responseKey, StringComparison.Ordinal)) { sref = e.Data.Substring (responseKey.Length); ev.Set (); } else Console.WriteLine (e.Data); }; p.BeginErrorReadLine (); p.StandardInput.WriteLine (Process.GetCurrentProcess ().Id.ToString ()); if (!ev.WaitOne (TimeSpan.FromSeconds (5))) throw new Exception ("MSBuild process could not be started"); byte [] data = Convert.FromBase64String (sref); MemoryStream ms = new MemoryStream (data); BinaryFormatter bf = new BinaryFormatter (); engine = (IBuildEngine)bf.Deserialize (ms); } else { var asm = System.Reflection.Assembly.LoadFrom (exe); var t = asm.GetType ("MonoDevelop.Projects.MSBuild.BuildEngine"); engine = (IBuildEngine)Activator.CreateInstance (t); } engine.SetCulture (GettextCatalog.UICulture); engine.SetGlobalProperties (GetCoreGlobalProperties (solutionFile)); foreach (var gpp in globalPropertyProviders) engine.SetGlobalProperties (gpp.GetGlobalProperties ()); builder = new RemoteBuildEngine (p, engine); } catch { if (p != null) { try { p.Kill (); } catch { } } throw; } builders.Add (builderKey, builder); builder.ReferenceCount = 1; builder.Disconnected += async delegate { using (await buildersLock.EnterAsync ()) builders.Remove (builder); }; if (lockBuilder) builder.Lock (); return new RemoteProjectBuilder (file, builder); }); } }
internal 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 responseKey = "[MonoDevelop]"; string sref; while (true) { sref = p.StandardError.ReadLine (); if (sref.StartsWith (responseKey, StringComparison.Ordinal)) { sref = sref.Substring (responseKey.Length); break; } } byte[] data = Convert.FromBase64String (sref); MemoryStream ms = new MemoryStream (data); BinaryFormatter bf = new BinaryFormatter (); var engine = (IBuildEngine)bf.Deserialize (ms); engine.SetCulture (GettextCatalog.UICulture); engine.SetGlobalProperties (GetCoreGlobalProperties (solutionFile)); foreach (var gpp in globalPropertyProviders) builder.SetGlobalProperties (gpp.GetGlobalProperties ()); 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); } }
static string GetNewestInstalledToolsVersion (TargetRuntime runtime, bool requiresMicrosoftBuild, out string binDir) { string [] supportedToolsVersions; if ((requiresMicrosoftBuild || Runtime.Preferences.BuildWithMSBuild) && !Platform.IsWindows) supportedToolsVersions = new [] { "15.0"}; else supportedToolsVersions = new [] { "14.0", "12.0", "4.0" }; foreach (var toolsVersion in supportedToolsVersions) { binDir = runtime.GetMSBuildBinPath (toolsVersion); if (binDir != null) { return toolsVersion; } } throw new Exception ("Did not find MSBuild for runtime " + runtime.Id); }
public static RemoteProjectBuilder GetProjectBuilder (TargetRuntime runtime, TargetFramework fx, string file) { lock (builders) { string binDir = runtime.GetMSBuildBinPath (fx); RemoteBuildEngine builder; if (builders.TryGetValue (runtime, out builder)) { builder.ReferenceCount++; return new RemoteProjectBuilder (file, binDir, builder); } if (runtime.IsRunning) { if (currentBuildEngine == null) currentBuildEngine = new RemoteBuildEngine (null, new BuildEngine ()); return new RemoteProjectBuilder (file, binDir, currentBuildEngine); } else { MonoDevelop.Core.Execution.RemotingService.RegisterRemotingChannel (); string exe = typeof(ProjectBuilder).Assembly.Location; ProcessStartInfo pinfo = new ProcessStartInfo (exe); runtime.GetToolsExecutionEnvironment (fx).MergeTo (pinfo); pinfo.UseShellExecute = false; pinfo.RedirectStandardError = true; pinfo.RedirectStandardInput = true; Process p = null; try { p = runtime.ExecuteAssembly (pinfo, fx); 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 (); builder = new RemoteBuildEngine (p, (IBuildEngine) bf.Deserialize (ms)); } catch { if (p != null) { try { p.Kill (); } catch { } } throw; } } builders [runtime] = builder; builder.ReferenceCount = 1; return new RemoteProjectBuilder (file, binDir, builder); } }
public static RemoteProjectBuilder GetProjectBuilder (TargetRuntime runtime, string toolsVersion, string file) { lock (builders) { var toolsFx = Runtime.SystemAssemblyService.GetTargetFramework (new TargetFrameworkMoniker (toolsVersion)); string binDir = runtime.GetMSBuildBinPath (toolsFx); if (!runtime.IsInstalled (toolsFx)) throw new InvalidOperationException (string.Format ( "Runtime '{0}' does not have the MSBuild '{1}' framework installed", runtime.Id, toolsVersion)); string builderKey = runtime.Id + " " + toolsVersion; RemoteBuildEngine builder; if (builders.TryGetValue (builderKey, out builder)) { builder.ReferenceCount++; return new RemoteProjectBuilder (file, binDir, 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 (toolsFx).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 (); builder = new RemoteBuildEngine (p, (IBuildEngine) bf.Deserialize (ms)); } catch { if (p != null) { try { p.Kill (); } catch { } } throw; } builders [builderKey] = builder; builder.ReferenceCount = 1; return new RemoteProjectBuilder (file, binDir, builder); } }
public static RemoteProjectBuilder GetProjectBuilder (TargetRuntime runtime, string toolsVersion, string file) { lock (builders) { var toolsFx = Runtime.SystemAssemblyService.GetTargetFramework (toolsVersion); string binDir = runtime.GetMSBuildBinPath (toolsFx); if (!runtime.IsInstalled (toolsFx)) throw new InvalidOperationException (string.Format ( "Runtime '{0}' cannot be used to build MSBuild '{1}' format projects", runtime.Id, toolsVersion)); string builderKey = runtime.Id + " " + toolsVersion; RemoteBuildEngine builder; if (builders.TryGetValue (builderKey, out builder)) { builder.ReferenceCount++; return new RemoteProjectBuilder (file, binDir, builder); } if (runtime.IsRunning && toolsVersion == REFERENCED_MSBUILD_TOOLS) { if (currentBuildEngine == null) currentBuildEngine = new RemoteBuildEngine (null, new BuildEngine ()); return new RemoteProjectBuilder (file, binDir, currentBuildEngine); } else { string exe = GetExeLocation (toolsVersion); MonoDevelop.Core.Execution.RemotingService.RegisterRemotingChannel (); ProcessStartInfo pinfo = new ProcessStartInfo (exe); runtime.GetToolsExecutionEnvironment (toolsFx).MergeTo (pinfo); pinfo.UseShellExecute = false; pinfo.RedirectStandardError = true; pinfo.RedirectStandardInput = true; 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 (); builder = new RemoteBuildEngine (p, (IBuildEngine) bf.Deserialize (ms)); } catch { if (p != null) { try { p.Kill (); } catch { } } throw; } } builders [builderKey] = builder; builder.ReferenceCount = 1; return new RemoteProjectBuilder (file, binDir, builder); } }
public static RemoteProjectBuilder GetProjectBuilder (TargetRuntime runtime, string toolsVersion, string file, string solutionFile) { lock (builders) { string binDir = runtime.GetMSBuildBinPath (toolsVersion); if (binDir == null) { string error = null; if (runtime is MsNetTargetRuntime) { if (toolsVersion == "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) ); } string builderKey = runtime.Id + " " + toolsVersion; RemoteBuildEngine builder; if (builders.TryGetValue (builderKey, out builder)) { builder.ReferenceCount++; return new RemoteProjectBuilder (file, solutionFile, binDir, 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.SetUICulture (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, solutionFile, binDir, builder); } }
static string GetNewestInstalledToolsVersion (TargetRuntime runtime, out string binDir) { var supportedToolsVersions = new [] { "14.1", "14.0", "12.0", "4.0" }; foreach (var toolsVersion in supportedToolsVersions) { binDir = runtime.GetMSBuildBinPath (toolsVersion); if (binDir != null) { return toolsVersion; } } throw new Exception ("Did not find MSBuild for runtime " + runtime.Id); }