예제 #1
0
        public virtual IEnumerable <string> GetToolsPaths()
        {
            string paths;

            if (!runtime.GetToolsExecutionEnvironment(framework).Variables.TryGetValue("PATH", out paths))
            {
                yield break;
            }
            foreach (string path in paths.Split(new char[] { Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries))
            {
                if (path.Length > 0 && path [0] == '"' && path [path.Length - 1] == '"')
                {
                    yield return(path.Substring(1, path.Length - 2));
                }
                else
                {
                    yield return(path);
                }
            }
        }
		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 async Task<RemoteProjectBuilder> GetProjectBuilder (TargetRuntime runtime, string minToolsVersion, string file, string solutionFile, int customId, bool requiresMicrosoftBuild, bool lockBuilder = false)
		{
			Version mtv = Version.Parse (minToolsVersion);
			if (mtv >= new Version (15,0))
				requiresMicrosoftBuild = true;

			using (await buildersLock.EnterAsync ())
			{
				string binDir;
				var toolsVersion = GetNewestInstalledToolsVersion (runtime, requiresMicrosoftBuild, out binDir);

				Version tv;
				if (Version.TryParse (toolsVersion, out tv) && Version.TryParse (minToolsVersion, out mtv) && tv < mtv) {
					throw new InvalidOperationException (string.Format (
						"Project requires MSBuild ToolsVersion '{0}' which is not supported by runtime '{1}'",
						toolsVersion, runtime.Id)
					);
				}

				//one builder per solution
				string builderKey = runtime.Id + " # " + solutionFile + " # " + customId + " # " + requiresMicrosoftBuild;

				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 (async () => {
					//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, requiresMicrosoftBuild);

					MonoDevelop.Core.Execution.RemotingService.RegisterRemotingChannel ();
					var pinfo = new ProcessStartInfo (exe) {
						WorkingDirectory = binDir,
						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
							var processStartedSignal = new TaskCompletionSource<bool> ();
							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);
									processStartedSignal.SetResult (true);
								} else
									Console.WriteLine (e.Data);
							};
							p.BeginErrorReadLine ();

							p.StandardInput.WriteLine (binDir);

							p.StandardInput.WriteLine (Process.GetCurrentProcess ().Id.ToString ());
							if (await Task.WhenAny (processStartedSignal.Task, Task.Delay (5000)) != processStartedSignal.Task)
								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);
				});
			}
		}
예제 #4
0
		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);
			}
		}
예제 #5
0
		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);
			}
		}
예제 #7
0
		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);
			}
		}