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(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, 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)); } }
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)); } }
public static BuildResult Compile(ProjectItemCollection projectItems, DotNetProjectConfiguration configuration, ConfigurationSelector configSelector, IProgressMonitor monitor) { CSharpCompilerParameters compilerParameters = (CSharpCompilerParameters)configuration.CompilationParameters ?? new CSharpCompilerParameters(); CSharpProjectParameters projectParameters = (CSharpProjectParameters)configuration.ProjectParameters ?? new CSharpProjectParameters(); string outputName = configuration.CompiledOutputName; string responseFileName = Path.GetTempFileName(); TargetRuntime runtime = MonoDevelop.Core.Runtime.SystemAssemblyService.DefaultRuntime; DotNetProject project = configuration.ParentItem as DotNetProject; if (project != null) { runtime = project.TargetRuntime; } StringBuilder sb = new StringBuilder(); List <string> gacRoots = new List <string> (); sb.AppendFormat("\"/out:{0}\"", outputName); sb.AppendLine(); HashSet <string> alreadyAddedReference = new HashSet <string> (); foreach (ProjectReference lib in projectItems.GetAll <ProjectReference> ()) { if (lib.ReferenceType == ReferenceType.Project && !(lib.OwnerProject.ParentSolution.FindProjectByName(lib.Reference) is DotNetProject)) { continue; } foreach (string fileName in lib.GetReferencedFileNames(configSelector)) { switch (lib.ReferenceType) { case ReferenceType.Gac: SystemPackage pkg = lib.Package; if (pkg == null) { string msg = string.Format(GettextCatalog.GetString("{0} could not be found or is invalid."), lib.Reference); monitor.ReportWarning(msg); continue; } if (alreadyAddedReference.Add(fileName)) { AppendQuoted(sb, "/r:", fileName); } if (pkg.GacRoot != null && !gacRoots.Contains(pkg.GacRoot)) { gacRoots.Add(pkg.GacRoot); } if (!string.IsNullOrEmpty(pkg.Requires)) { foreach (string requiredPackage in pkg.Requires.Split(' ')) { SystemPackage rpkg = runtime.AssemblyContext.GetPackage(requiredPackage); if (rpkg == null) { continue; } foreach (SystemAssembly assembly in rpkg.Assemblies) { if (alreadyAddedReference.Add(assembly.Location)) { AppendQuoted(sb, "/r:", assembly.Location); } } } } break; default: if (alreadyAddedReference.Add(fileName)) { AppendQuoted(sb, "/r:", fileName); } break; } } } sb.AppendLine("/nologo"); sb.Append("/warn:"); sb.Append(compilerParameters.WarningLevel.ToString()); sb.AppendLine(); if (configuration.SignAssembly) { if (File.Exists(configuration.AssemblyKeyFile)) { AppendQuoted(sb, "/keyfile:", configuration.AssemblyKeyFile); } } if (configuration.DebugMode) { sb.AppendLine("/debug:+"); sb.AppendLine("/debug:full"); } switch (compilerParameters.LangVersion) { case LangVersion.Default: break; case LangVersion.ISO_1: sb.AppendLine("/langversion:ISO-1"); break; case LangVersion.ISO_2: sb.AppendLine("/langversion:ISO-2"); break; default: string message = "Invalid LangVersion enum value '" + compilerParameters.LangVersion.ToString() + "'"; monitor.ReportError(message, null); LoggingService.LogError(message); return(null); } // mcs default is + but others might not be if (compilerParameters.Optimize) { sb.AppendLine("/optimize+"); } else { sb.AppendLine("/optimize-"); } bool hasWin32Res = !string.IsNullOrEmpty(projectParameters.Win32Resource) && File.Exists(projectParameters.Win32Resource); if (hasWin32Res) { AppendQuoted(sb, "/win32res:", projectParameters.Win32Resource); } if (!string.IsNullOrEmpty(projectParameters.Win32Icon) && File.Exists(projectParameters.Win32Icon)) { if (hasWin32Res) { monitor.ReportWarning("Both Win32 icon and Win32 resource cannot be specified. Ignoring the icon."); } else { AppendQuoted(sb, "/win32icon:", projectParameters.Win32Icon); } } if (projectParameters.CodePage != 0) { sb.AppendLine("/codepage:" + projectParameters.CodePage); } else if (runtime is MonoTargetRuntime) { sb.AppendLine("/codepage:utf8"); } if (compilerParameters.UnsafeCode) { sb.AppendLine("-unsafe"); } if (compilerParameters.NoStdLib) { sb.AppendLine("-nostdlib"); } if (!string.IsNullOrEmpty(compilerParameters.PlatformTarget) && compilerParameters.PlatformTarget.ToLower() != "anycpu") { //HACK: to ignore the platform flag for Mono <= 2.4, because gmcs didn't support it if (runtime.RuntimeId == "Mono" && runtime.AssemblyContext.GetAssemblyLocation("Mono.Debugger.Soft", null) == null) { LoggingService.LogWarning("Mono runtime '" + runtime.DisplayName + "' appears to be too old to support the 'platform' C# compiler flag."); } else { sb.AppendLine("/platform:" + compilerParameters.PlatformTarget); } } if (compilerParameters.TreatWarningsAsErrors) { sb.AppendLine("-warnaserror"); if (!string.IsNullOrEmpty(compilerParameters.WarningsNotAsErrors)) { sb.AppendLine("-warnaserror-:" + compilerParameters.WarningsNotAsErrors); } } if (compilerParameters.DefineSymbols.Length > 0) { string define_str = string.Join(";", compilerParameters.DefineSymbols.Split(new char [] { ',', ' ', ';' }, StringSplitOptions.RemoveEmptyEntries)); if (define_str.Length > 0) { AppendQuoted(sb, "/define:", define_str); sb.AppendLine(); } } CompileTarget ctarget = configuration.CompileTarget; if (!string.IsNullOrEmpty(projectParameters.MainClass)) { sb.AppendLine("/main:" + projectParameters.MainClass); // mcs does not allow providing a Main class when compiling a dll // As a workaround, we compile as WinExe (although the output will still // have a .dll extension). if (ctarget == CompileTarget.Library) { ctarget = CompileTarget.WinExe; } } switch (ctarget) { case CompileTarget.Exe: sb.AppendLine("/t:exe"); break; case CompileTarget.WinExe: sb.AppendLine("/t:winexe"); break; case CompileTarget.Library: sb.AppendLine("/t:library"); break; } foreach (ProjectFile finfo in projectItems.GetAll <ProjectFile> ()) { if (finfo.Subtype == Subtype.Directory) { continue; } switch (finfo.BuildAction) { case "Compile": AppendQuoted(sb, "", finfo.Name); break; case "EmbeddedResource": string fname = finfo.Name; if (string.Compare(Path.GetExtension(fname), ".resx", true) == 0) { fname = Path.ChangeExtension(fname, ".resources"); } sb.Append('"'); sb.Append("/res:"); sb.Append(fname); sb.Append(','); sb.Append(finfo.ResourceId); sb.Append('"'); sb.AppendLine(); break; default: continue; } } if (compilerParameters.GenerateXmlDocumentation) { AppendQuoted(sb, "/doc:", Path.ChangeExtension(outputName, ".xml")); } if (!string.IsNullOrEmpty(compilerParameters.AdditionalArguments)) { sb.AppendLine(compilerParameters.AdditionalArguments); } if (!string.IsNullOrEmpty(compilerParameters.NoWarnings)) { AppendQuoted(sb, "/nowarn:", compilerParameters.NoWarnings); } if (runtime.RuntimeId == "MS.NET") { sb.AppendLine("/fullpaths"); sb.AppendLine("/utf8output"); } string output = ""; string error = ""; File.WriteAllText(responseFileName, sb.ToString()); string compilerName; try { compilerName = GetCompilerName(runtime, configuration.TargetFramework); } catch (Exception e) { string message = "Could not obtain a C# compiler"; monitor.ReportError(message, e); return(null); } monitor.Log.WriteLine(compilerName + " /noconfig " + sb.ToString().Replace('\n', ' ')); string workingDir = "."; if (configuration.ParentItem != null) { workingDir = configuration.ParentItem.BaseDirectory; if (workingDir == null) { // Dummy projects created for single files have no filename // and so no BaseDirectory. // This is a workaround for a bug in // ProcessStartInfo.WorkingDirectory - not able to handle null workingDir = "."; } } LoggingService.LogInfo(compilerName + " " + sb.ToString()); ExecutionEnvironment envVars = runtime.GetToolsExecutionEnvironment(project.TargetFramework); string cargs = "/noconfig @\"" + responseFileName + "\""; int exitCode = DoCompilation(compilerName, cargs, workingDir, envVars, gacRoots, ref output, ref error); BuildResult result = ParseOutput(output, error); if (result.CompilerOutput.Trim().Length != 0) { monitor.Log.WriteLine(result.CompilerOutput); } //if compiler crashes, output entire error string if (result.ErrorCount == 0 && exitCode != 0) { try { monitor.Log.Write(File.ReadAllText(error)); } catch (IOException) { } result.AddError("The compiler appears to have crashed. Check the build output pad for details."); LoggingService.LogError("C# compiler crashed. Response file '{0}', stdout file '{1}', stderr file '{2}'", responseFileName, output, error); } else { FileService.DeleteFile(responseFileName); FileService.DeleteFile(output); FileService.DeleteFile(error); } return(result); }
public static BuildResult Compile(ProjectItemCollection projectItems, DotNetProjectConfiguration configuration, ConfigurationSelector configSelector, ProgressMonitor monitor) { var compilerParameters = (CSharpCompilerParameters)configuration.CompilationParameters ?? new CSharpCompilerParameters(); var projectParameters = (CSharpProject)configuration.ParentItem; FilePath outputName = configuration.CompiledOutputName; string responseFileName = Path.GetTempFileName(); //make sure that the output file is writable if (File.Exists(outputName)) { bool isWriteable = false; int count = 0; do { try { outputName.MakeWritable(); using (var stream = File.OpenWrite(outputName)) { isWriteable = true; } } catch (Exception) { Thread.Sleep(20); } } while (count++ < 5 && !isWriteable); if (!isWriteable) { MessageService.ShowError(string.Format(GettextCatalog.GetString("Can't lock file: {0}."), outputName)); return(null); } } //get the runtime TargetRuntime runtime = MonoDevelop.Core.Runtime.SystemAssemblyService.DefaultRuntime; DotNetProject project = configuration.ParentItem as DotNetProject; if (project != null) { runtime = project.TargetRuntime; } //get the compiler name string compilerName; try { compilerName = GetCompilerName(runtime, configuration.TargetFramework); } catch (Exception e) { string message = "Could not obtain a C# compiler"; monitor.ReportError(message, e); return(null); } var sb = new StringBuilder(); HashSet <string> alreadyAddedReference = new HashSet <string> (); var monoRuntime = runtime as MonoTargetRuntime; if (!compilerParameters.NoStdLib && (monoRuntime == null || monoRuntime.HasMultitargetingMcs)) { string corlib = project.AssemblyContext.GetAssemblyFullName("mscorlib", project.TargetFramework); if (corlib != null) { corlib = project.AssemblyContext.GetAssemblyLocation(corlib, project.TargetFramework); } if (corlib == null) { var br = new BuildResult(); br.AddError(string.Format("Could not find mscorlib for framework {0}", project.TargetFramework.Id)); return(br); } AppendQuoted(sb, "/r:", corlib); sb.AppendLine("-nostdlib"); } List <string> gacRoots = new List <string> (); sb.AppendFormat("\"/out:{0}\"", outputName); sb.AppendLine(); foreach (ProjectReference lib in projectItems.GetAll <ProjectReference> ()) { if (lib.ReferenceType == ReferenceType.Project) { var ownerProject = lib.OwnerProject; if (ownerProject != null) { var parentSolution = ownerProject.ParentSolution; if (parentSolution != null && !(lib.ResolveProject(parentSolution) is DotNetProject)) { continue; } } } string refPrefix = string.IsNullOrEmpty(lib.Aliases) ? "" : lib.Aliases + "="; foreach (string fileName in lib.GetReferencedFileNames(configSelector)) { switch (lib.ReferenceType) { case ReferenceType.Package: SystemPackage pkg = lib.Package; if (pkg == null) { string msg = string.Format(GettextCatalog.GetString("{0} could not be found or is invalid."), lib.Reference); monitor.ReportWarning(msg); continue; } if (alreadyAddedReference.Add(fileName)) { AppendQuoted(sb, "/r:", refPrefix + fileName); } if (pkg.GacRoot != null && !gacRoots.Contains(pkg.GacRoot)) { gacRoots.Add(pkg.GacRoot); } if (!string.IsNullOrEmpty(pkg.Requires)) { foreach (string requiredPackage in pkg.Requires.Split(' ')) { SystemPackage rpkg = runtime.AssemblyContext.GetPackage(requiredPackage); if (rpkg == null) { continue; } foreach (SystemAssembly assembly in rpkg.Assemblies) { if (alreadyAddedReference.Add(assembly.Location)) { AppendQuoted(sb, "/r:", assembly.Location); } } } } break; default: if (alreadyAddedReference.Add(fileName)) { AppendQuoted(sb, "/r:", refPrefix + fileName); } break; } } } if (alreadyAddedReference.Any(reference => SystemAssemblyService.ContainsReferenceToSystemRuntime(reference))) { LoggingService.LogInfo("Found PCLv2 assembly."); var facades = runtime.FindFacadeAssembliesForPCL(project.TargetFramework); foreach (var facade in facades) { AppendQuoted(sb, "/r:", facade); } } string sysCore = project.AssemblyContext.GetAssemblyFullName("System.Core", project.TargetFramework); if (sysCore != null && !alreadyAddedReference.Contains(sysCore)) { var asm = project.AssemblyContext.GetAssemblyFromFullName(sysCore, null, project.TargetFramework); if (asm != null) { AppendQuoted(sb, "/r:", asm.Location); } } sb.AppendLine("/nologo"); sb.Append("/warn:"); sb.Append(compilerParameters.WarningLevel.ToString()); sb.AppendLine(); if (configuration.SignAssembly) { if (File.Exists(configuration.AssemblyKeyFile)) { AppendQuoted(sb, "/keyfile:", configuration.AssemblyKeyFile); } if (configuration.DelaySign) { sb.AppendLine("/delaySign"); } } var debugType = configuration.DebugType; if (string.IsNullOrEmpty(debugType)) { debugType = configuration.DebugSymbols ? "full" : "none"; } else if (string.Equals(debugType, "pdbonly", StringComparison.OrdinalIgnoreCase)) { //old Mono compilers don't support pdbonly if (monoRuntime != null && !monoRuntime.HasMultitargetingMcs) { debugType = "full"; } } if (!string.Equals(debugType, "none", StringComparison.OrdinalIgnoreCase)) { sb.AppendLine("/debug:" + debugType); } if (compilerParameters.LangVersion != LangVersion.Default) { var langVersionString = CSharpCompilerParameters.TryLangVersionToString(compilerParameters.LangVersion); if (langVersionString == null) { string message = "Invalid LangVersion enum value '" + compilerParameters.LangVersion.ToString() + "'"; monitor.ReportError(message, null); LoggingService.LogError(message); return(null); } sb.AppendLine("/langversion:" + langVersionString); } // mcs default is + but others might not be if (compilerParameters.Optimize) { sb.AppendLine("/optimize+"); } else { sb.AppendLine("/optimize-"); } bool hasWin32Res = !string.IsNullOrEmpty(projectParameters.Win32Resource) && File.Exists(projectParameters.Win32Resource); if (hasWin32Res) { AppendQuoted(sb, "/win32res:", projectParameters.Win32Resource); } if (!string.IsNullOrEmpty(projectParameters.Win32Icon) && File.Exists(projectParameters.Win32Icon)) { if (hasWin32Res) { monitor.ReportWarning("Both Win32 icon and Win32 resource cannot be specified. Ignoring the icon."); } else { AppendQuoted(sb, "/win32icon:", projectParameters.Win32Icon); } } if (projectParameters.CodePage != 0) { sb.AppendLine("/codepage:" + projectParameters.CodePage); } else if (runtime is MonoTargetRuntime) { sb.AppendLine("/codepage:utf8"); } if (compilerParameters.UnsafeCode) { sb.AppendLine("-unsafe"); } if (compilerParameters.NoStdLib) { sb.AppendLine("-nostdlib"); } if (!string.IsNullOrEmpty(compilerParameters.PlatformTarget) && compilerParameters.PlatformTarget.ToLower() != "anycpu") { //HACK: to ignore the platform flag for Mono <= 2.4, because gmcs didn't support it if (runtime.RuntimeId == "Mono" && runtime.AssemblyContext.GetAssemblyLocation("Mono.Debugger.Soft", null) == null) { LoggingService.LogWarning("Mono runtime '" + runtime.DisplayName + "' appears to be too old to support the 'platform' C# compiler flag."); } else { sb.AppendLine("/platform:" + compilerParameters.PlatformTarget); } } if (compilerParameters.TreatWarningsAsErrors) { sb.AppendLine("-warnaserror"); if (!string.IsNullOrEmpty(compilerParameters.WarningsNotAsErrors)) { sb.AppendLine("-warnaserror-:" + compilerParameters.WarningsNotAsErrors); } } foreach (var define in configuration.GetDefineSymbols()) { AppendQuoted(sb, "/define:", define); sb.AppendLine(); } CompileTarget ctarget = configuration.CompileTarget; if (!string.IsNullOrEmpty(projectParameters.MainClass)) { sb.AppendLine("/main:" + projectParameters.MainClass); // mcs does not allow providing a Main class when compiling a dll // As a workaround, we compile as WinExe (although the output will still // have a .dll extension). if (ctarget == CompileTarget.Library) { ctarget = CompileTarget.WinExe; } } switch (ctarget) { case CompileTarget.Exe: sb.AppendLine("/t:exe"); break; case CompileTarget.WinExe: sb.AppendLine("/t:winexe"); break; case CompileTarget.Library: sb.AppendLine("/t:library"); break; } foreach (ProjectFile finfo in projectItems.GetAll <ProjectFile> ()) { if (finfo.Subtype == Subtype.Directory) { continue; } switch (finfo.BuildAction) { case "Compile": AppendQuoted(sb, "", finfo.Name); break; case "EmbeddedResource": string fname = finfo.Name; if (string.Compare(Path.GetExtension(fname), ".resx", StringComparison.OrdinalIgnoreCase) == 0) { fname = Path.ChangeExtension(fname, ".resources"); } sb.Append('"'); sb.Append("/res:"); sb.Append(fname); sb.Append(','); sb.Append(finfo.ResourceId); sb.Append('"'); sb.AppendLine(); break; default: continue; } } if (!compilerParameters.DocumentationFile.IsNullOrEmpty) { AppendQuoted(sb, "/doc:", compilerParameters.DocumentationFile); } if (!string.IsNullOrEmpty(compilerParameters.NoWarnings)) { AppendQuoted(sb, "/nowarn:", compilerParameters.NoWarnings); } if (runtime.RuntimeId == "MS.NET") { sb.AppendLine("/fullpaths"); sb.AppendLine("/utf8output"); } string output = ""; string error = ""; File.WriteAllText(responseFileName, sb.ToString()); monitor.Log.WriteLine(compilerName + " /noconfig " + sb.ToString().Replace('\n', ' ')); // Dummy projects created for single files have no filename // and so no BaseDirectory. string workingDir = null; if (configuration.ParentItem != null) { workingDir = configuration.ParentItem.BaseDirectory; } LoggingService.LogInfo(compilerName + " " + sb); ExecutionEnvironment envVars = runtime.GetToolsExecutionEnvironment(project.TargetFramework); string cargs = "/noconfig @\"" + responseFileName + "\""; int exitCode = DoCompilation(monitor, compilerName, cargs, workingDir, envVars, gacRoots, ref output, ref error); BuildResult result = ParseOutput(workingDir, output, error); if (result.CompilerOutput.Trim().Length != 0) { monitor.Log.WriteLine(result.CompilerOutput); } //if compiler crashes, output entire error string if (result.ErrorCount == 0 && exitCode != 0) { try { monitor.Log.Write(File.ReadAllText(error)); } catch (IOException) { } result.AddError("The compiler appears to have crashed. Check the build output pad for details."); LoggingService.LogError("C# compiler crashed. Response file '{0}', stdout file '{1}', stderr file '{2}'", responseFileName, output, error); } else { FileService.DeleteFile(responseFileName); FileService.DeleteFile(output); FileService.DeleteFile(error); } return(result); }
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)); } }
internal static RemoteProjectBuilder GetProjectBuilder(TargetRuntime runtime, string minToolsVersion, string file, string solutionFile) { lock (builders) { //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 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 { 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) { 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.Formats.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 [builderKey] = builder; builder.ReferenceCount = 1; builder.Disconnected += delegate { lock (builders) builders.Remove(builderKey); }; return(new RemoteProjectBuilder(file, builder)); } }