From 9b9699e9346ba264c3ff9405784e76b15be60e36 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Thu, 10 Mar 2005 14:41:45 +0000 Subject: [PATCH] MSBuildProject now uses Microsoft.Build.Engine instead of calling MSBuild.exe. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@84 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/ICSharpCode.SharpDevelop.csproj | 9 +- .../Base/Project/Src/Project/MSBuildEngine.cs | 220 ++++++++++++++++++ .../Project/Src/Project/MSBuildProject.cs | 106 +-------- 3 files changed, 234 insertions(+), 101 deletions(-) create mode 100644 src/Main/Base/Project/Src/Project/MSBuildEngine.cs diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index 93cdc62559..00eccc07c2 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -1,4 +1,4 @@ - + Debug AnyCPU @@ -13,6 +13,10 @@ True Resources\ICSharpCode.SharpDevelop.snk File + ICSharpCode.SharpDevelop + + + True @@ -45,6 +49,8 @@ + + @@ -638,6 +644,7 @@ + diff --git a/src/Main/Base/Project/Src/Project/MSBuildEngine.cs b/src/Main/Base/Project/Src/Project/MSBuildEngine.cs new file mode 100644 index 0000000000..34a5433d19 --- /dev/null +++ b/src/Main/Base/Project/Src/Project/MSBuildEngine.cs @@ -0,0 +1,220 @@ +using System; +using System.Collections.Generic; +using System.CodeDom.Compiler; +using System.IO; +using System.Text; +using System.Threading; +using System.Windows.Forms; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Gui; +using Microsoft.Build.Framework; +using Microsoft.Build.BuildEngine; + +namespace ICSharpCode.SharpDevelop.Project +{ + /// + /// Class responsible for building a project using MSBuild. + /// Is called by MSBuildProject. + /// + public class MSBuildEngine + { + MessageViewCategory messageView; + + /// + /// The the output is written to. + /// + public MessageViewCategory MessageView { + get { + return messageView; + } + set { + messageView = value; + } + } + + public CompilerResults Run(string buildFile) + { + return Run(buildFile, null); + } + + public CompilerResults Run(string buildFile, string[] targets) + { + CompilerResults results = new CompilerResults(null); + Engine engine = new Engine(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()); + SharpDevelopLogger logger = new SharpDevelopLogger(this, results); + engine.RegisterLogger(logger); + engine.BuildProjectFile(buildFile, targets, null, null); + logger.FlushText(); + return results; + } + + class SharpDevelopLogger : ILogger + { + MSBuildEngine engine; + CompilerResults results; + Thread mainThread; + + public SharpDevelopLogger(MSBuildEngine engine, CompilerResults results) + { + mainThread = Thread.CurrentThread; + this.engine = engine; + this.results = results; + } + + StringBuilder textToWrite = new StringBuilder(); + + void AppendText(string text) + { + lock (textToWrite) { + textToWrite.AppendLine(text); + if (Thread.CurrentThread == mainThread) { + FlushText(); + } + } + } + + public void FlushText() + { + if (engine.MessageView != null) + engine.MessageView.AppendText(textToWrite.ToString()); + textToWrite.Length = 0; + } + + void OnBuildStarted(object sender, BuildStartedEventArgs e) + { + AppendText("Build started."); + } + + void OnBuildFinished(object sender, BuildFinishedEventArgs e) + { + if (e.Succeeded) { + AppendText("Build finished successfully."); + StatusBarService.SetMessage("Build finished successfully."); + } else { + AppendText("Build failed."); + StatusBarService.SetMessage("Build failed."); + } + } + + Stack projectFiles = new Stack(); + + void OnProjectStarted(object sender, ProjectStartedEventArgs e) + { + projectFiles.Push(e.ProjectFile); + StatusBarService.SetMessage("Building " + Path.GetFileNameWithoutExtension(e.ProjectFile) + "..."); + Application.DoEvents(); + } + + void OnProjectFinished(object sender, ProjectFinishedEventArgs e) + { + projectFiles.Pop(); + if (projectFiles.Count > 0) { + StatusBarService.SetMessage("Building " + Path.GetFileNameWithoutExtension(projectFiles.Peek()) + "..."); + Application.DoEvents(); + } + } + + void OnTargetStarted(object sender, TargetStartedEventArgs e) + { + // do not display + } + + void OnTargetFinished(object sender, TargetFinishedEventArgs e) + { + // do not display + } + + void OnTaskStarted(object sender, TaskStartedEventArgs e) + { + // TODO: Give addins ability to extend the logger + switch (e.TaskName.ToLower()) { + case "csc": + case "vbc": + AppendText("Compiling " + Path.GetFileNameWithoutExtension(e.ProjectFile)); + break; + } + } + + void OnTaskFinished(object sender, TaskFinishedEventArgs e) + { + // do not display + } + + void OnError(object sender, BuildErrorEventArgs e) + { + AppendError(e.File, e.LineNumber, e.ColumnNumber, e.Code, e.Message, false); + } + + void OnWarning(object sender, BuildWarningEventArgs e) + { + AppendError(e.File, e.LineNumber, e.ColumnNumber, e.Code, e.Message, true); + } + + void AppendError(string file, int lineNumber, int columnNumber, string code, string message, bool isWarning) + { + CompilerError error = new CompilerError(file, lineNumber, columnNumber, code, message); + error.IsWarning = isWarning; + AppendText(error.ToString()); + if (projectFiles.Count > 0) + error.FileName = Path.Combine(Path.GetDirectoryName(projectFiles.Peek()), file); + results.Errors.Add(error); + } + + void OnMessage(object sender, BuildMessageEventArgs e) + { + //AppendText(e.Message); + } + + void OnCustomEvent(object sender, CustomBuildEventArgs e) + { + //AppendText(e.Message); + } + + #region ILogger interface implementation + LoggerVerbosity verbosity = LoggerVerbosity.Minimal; + + public LoggerVerbosity Verbosity { + get { + return verbosity; + } + set { + verbosity = value; + } + } + + string parameters; + + public string Parameters { + get { + return parameters; + } + set { + parameters = value; + } + } + + public void Initialize(IEventSource eventSource) + { + eventSource.BuildStarted += new BuildStartedEventHandler(OnBuildStarted); + eventSource.BuildFinished += new BuildFinishedEventHandler(OnBuildFinished); + eventSource.ProjectStarted += new ProjectStartedEventHandler(OnProjectStarted); + eventSource.ProjectFinished += new ProjectFinishedEventHandler(OnProjectFinished); + eventSource.TargetStarted += new TargetStartedEventHandler(OnTargetStarted); + eventSource.TargetFinished += new TargetFinishedEventHandler(OnTargetFinished); + eventSource.TaskStarted += new TaskStartedEventHandler(OnTaskStarted); + eventSource.TaskFinished += new TaskFinishedEventHandler(OnTaskFinished); + + eventSource.ErrorRaised += new BuildErrorEventHandler(OnError); + eventSource.WarningRaised += new BuildWarningEventHandler(OnWarning); + eventSource.MessageRaised += new BuildMessageEventHandler(OnMessage); + eventSource.CustomEventRaised += new CustomBuildEventHandler(OnCustomEvent); + } + + public void Shutdown() + { + + } + #endregion + } + } +} diff --git a/src/Main/Base/Project/Src/Project/MSBuildProject.cs b/src/Main/Base/Project/Src/Project/MSBuildProject.cs index c7ffb05b73..cd846dd70a 100644 --- a/src/Main/Base/Project/Src/Project/MSBuildProject.cs +++ b/src/Main/Base/Project/Src/Project/MSBuildProject.cs @@ -241,7 +241,6 @@ namespace ICSharpCode.SharpDevelop.Project } - // static void BeforeBuild() // { // TaskService.NotifyTaskChange(); @@ -267,111 +266,18 @@ namespace ICSharpCode.SharpDevelop.Project // TaskService.BuildMessageViewCategory.AppendText(StringParser.Parse("${res:MainWindow.CompilerMessages.ProjectStatsOutput}", new string[,] { {"ERRORS", TaskService.Errors.ToString()}, {"WARNINGS", TaskService.Warnings.ToString()} }) + Environment.NewLine + Environment.NewLine); // isDirty = TaskService.Errors != 0; // } -// - readonly static Regex normalError = new Regex(@"^(?\S.*)\((?\d+),(?\d+)\):\s+(?\w+)\s+(?[\d\w]+):\s+(?.*)$", RegexOptions.Compiled); - readonly static Regex compilerError = new Regex(@"^(?[^:]*):\s+(?\w+)\s+(?[\d\w]+):\s+(?.*)$", RegexOptions.Compiled); - readonly static Regex generalError = new Regex(@"^(?\S.+)\s+(?[\d\w]+):\s+(?.*)$", RegexOptions.Compiled); - - readonly static Regex projectName = new Regex(@"^Project\s+\""[^""]*\""[^""]*\""(?[^""]*)\""", RegexOptions.Compiled); - - - static CompilerError GetCompilerError(string line, string workingPath) - { - Match match = normalError.Match(line); - if (match.Success) { - CompilerError error = new CompilerError(); - error.Column = Int32.Parse(match.Result("${column}")); - error.Line = Int32.Parse(match.Result("${line}")); - error.FileName = Path.Combine(workingPath, match.Result("${file}")); - error.IsWarning = match.Result("${error}") == "warning"; - error.ErrorNumber = match.Result("${number}"); - error.ErrorText = match.Result("${message}"); - return error; - } - match = compilerError.Match(line); - if (match.Success) { - CompilerError error = new CompilerError(); - error.IsWarning = match.Result("${error}") == "warning"; - error.ErrorNumber = match.Result("${number}"); - error.ErrorText = match.Result("${who}") + ":" + match.Result("${message}"); - return error; - } - - match = generalError.Match(line); - if (match.Success) { - CompilerError error = new CompilerError(); - error.IsWarning = match.Result("${error}") == "warning"; - error.ErrorNumber = match.Result("${number}"); - error.ErrorText = match.Result("${message}"); - return error; - } - return null; - } public static CompilerResults RunMSBuild(string fileName, string target) { WorkbenchSingleton.Workbench.GetPad(typeof(CompilerMessageView)).BringPadToFront(); - CompilerResults results = new CompilerResults(null); // BeforeBuild(); - string runtimeDirectory = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(); - ProcessStartInfo startInfo = new ProcessStartInfo("\"" + Path.Combine(runtimeDirectory, "msbuild.exe") + "\""); - if (target != null) { - startInfo.Arguments = "/nologo /verbosity:m \"" + fileName + "\" \"/t:" + target + "\""; - } else { - startInfo.Arguments = "/nologo /verbosity:m \"" + fileName; - } - string workingDirectory = Path.GetDirectoryName(fileName); - startInfo.WorkingDirectory = workingDirectory; - - startInfo.UseShellExecute = false; - startInfo.RedirectStandardOutput = true; - Process p = Process.Start(startInfo); - - StreamReader reader = p.StandardOutput; - while (!p.HasExited) { - string line = reader.ReadLine(); - if (line != null) { - TaskService.BuildMessageViewCategory.AppendText(line + Environment.NewLine); - Match match = projectName.Match(line); - if (match.Success) { - string name = match.Result("${name}"); - if (name != null) { - workingDirectory = Path.GetDirectoryName(name); - } - } else { - CompilerError error = GetCompilerError(line, workingDirectory); - if (error != null) { - results.Errors.Add(error); - } - } - results.Output.Add(line); - } - System.Windows.Forms.Application.DoEvents(); - } - while (true) { - string line = reader.ReadLine(); - if (line == null) { - break; - } - TaskService.BuildMessageViewCategory.AppendText(line + Environment.NewLine); - Match match = projectName.Match(line); - if (match.Success) { - string name = match.Result("${name}"); - if (name != null) { - workingDirectory = Path.GetDirectoryName(name); - } - } else { - CompilerError error = GetCompilerError(line, workingDirectory); - if (error != null) { - results.Errors.Add(error); - } - } - results.Output.Add(line); - } -// TaskService.BuildMessageViewCategory.AppendText(reader.ReadToEnd() + Environment.NewLine); - p.WaitForExit(); + MSBuildEngine engine = new MSBuildEngine(); + engine.MessageView = TaskService.BuildMessageViewCategory; + if (target == null) + return engine.Run(fileName); + else + return engine.Run(fileName, new string[] { target }); // AfterBuild(); - return results; } public override CompilerResults Build()