Browse Source

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
shortcuts
Daniel Grunwald 21 years ago
parent
commit
9b9699e934
  1. 9
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  2. 220
      src/Main/Base/Project/Src/Project/MSBuildEngine.cs
  3. 106
      src/Main/Base/Project/Src/Project/MSBuildProject.cs

9
src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@ -13,6 +13,10 @@ @@ -13,6 +13,10 @@
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>Resources\ICSharpCode.SharpDevelop.snk</AssemblyOriginatorKeyFile>
<AssemblyOriginatorKeyMode>File</AssemblyOriginatorKeyMode>
<RootNamespace>ICSharpCode.SharpDevelop</RootNamespace>
<StartupObject />
<ApplicationIcon />
<Win32Resource />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>True</DebugSymbols>
@ -45,6 +49,8 @@ @@ -45,6 +49,8 @@
<Reference Include="System.Web.Services" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.XML" />
<Reference Include="Microsoft.Build.Framework, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<Reference Include="Microsoft.Build.Engine, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</ItemGroup>
<ItemGroup>
<Compile Include="Src\Internal\ExternalTool\ExternalTool.cs" />
@ -638,6 +644,7 @@ @@ -638,6 +644,7 @@
<Compile Include="Src\Dom\ResolveResult.cs" />
<Compile Include="Src\TextEditor\Commands\NavigationCommands.cs" />
<Compile Include="Src\Dom\FilePosition.cs" />
<Compile Include="Src\Project\MSBuildEngine.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Libraries\DockPanel_Src\WinFormsUI\WinFormsUI.csproj">

220
src/Main/Base/Project/Src/Project/MSBuildEngine.cs

@ -0,0 +1,220 @@ @@ -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
{
/// <summary>
/// Class responsible for building a project using MSBuild.
/// Is called by MSBuildProject.
/// </summary>
public class MSBuildEngine
{
MessageViewCategory messageView;
/// <summary>
/// The <see cref="MessageViewCategory"/> the output is written to.
/// </summary>
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<string> projectFiles = new Stack<string>();
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
}
}
}

106
src/Main/Base/Project/Src/Project/MSBuildProject.cs

@ -241,7 +241,6 @@ namespace ICSharpCode.SharpDevelop.Project @@ -241,7 +241,6 @@ namespace ICSharpCode.SharpDevelop.Project
}
// static void BeforeBuild()
// {
// TaskService.NotifyTaskChange();
@ -267,111 +266,18 @@ namespace ICSharpCode.SharpDevelop.Project @@ -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(@"^(?<file>\S.*)\((?<line>\d+),(?<column>\d+)\):\s+(?<error>\w+)\s+(?<number>[\d\w]+):\s+(?<message>.*)$", RegexOptions.Compiled);
readonly static Regex compilerError = new Regex(@"^(?<who>[^:]*):\s+(?<error>\w+)\s+(?<number>[\d\w]+):\s+(?<message>.*)$", RegexOptions.Compiled);
readonly static Regex generalError = new Regex(@"^(?<error>\S.+)\s+(?<number>[\d\w]+):\s+(?<message>.*)$", RegexOptions.Compiled);
readonly static Regex projectName = new Regex(@"^Project\s+\""[^""]*\""[^""]*\""(?<name>[^""]*)\""", 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()

Loading…
Cancel
Save