~halega/+junk/sharpdevelop

« back to all changes in this revision

Viewing changes to src/Main/ICSharpCode.SharpDevelop.BuildWorker/Program.cs

  • Committer: sk
  • Date: 2011-09-10 05:17:57 UTC
  • Revision ID: halega@halega.com-20110910051757-qfouz1llya9m6boy
4.1.0.7915 Release Candidate 1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
 
2
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
 
3
 
 
4
// activate this define to see the build worker window
 
5
//#define WORKERDEBUG
 
6
 
 
7
using System;
 
8
using System.Collections.Generic;
 
9
using System.Diagnostics;
 
10
using System.IO;
 
11
using System.Runtime.Serialization;
 
12
using System.Threading;
 
13
 
 
14
using ICSharpCode.SharpDevelop.Interprocess;
 
15
using Microsoft.Build.Framework;
 
16
 
 
17
namespace ICSharpCode.SharpDevelop.BuildWorker
 
18
{
 
19
        sealed class Program
 
20
        {
 
21
                static HostProcess host;
 
22
                BuildJob currentJob;
 
23
                bool requestCancellation;
 
24
                
 
25
                [STAThread]
 
26
                internal static void Main(string[] args)
 
27
                {
 
28
                        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AppDomain_CurrentDomain_UnhandledException);
 
29
                        
 
30
                        if (args.Length == 3 && args[0] == "worker") {
 
31
                                try {
 
32
                                        host = new HostProcess(args[1], args[2]);
 
33
                                        host.Run(new Program().DataReceived);
 
34
                                } catch (Exception ex) {
 
35
                                        ShowMessageBox(ex.ToString());
 
36
                                }
 
37
                        } else {
 
38
                                Console.WriteLine("ICSharpCode.SharpDevelop.BuildWorker.exe is used to compile " +
 
39
                                                  "MSBuild projects inside SharpDevelop.");
 
40
                                Console.WriteLine("If you want to compile projects on the command line, use " +
 
41
                                                  "MSBuild.exe (part of the .NET Framework)");
 
42
                        }
 
43
                }
 
44
                
 
45
                readonly MSBuildWrapper buildWrapper = new MSBuildWrapper();
 
46
                
 
47
                void DataReceived(string command, BinaryReader reader)
 
48
                {
 
49
                        switch (command) {
 
50
                                case "StartBuild":
 
51
                                        StartBuild(BuildJob.ReadFrom(reader));
 
52
                                        break;
 
53
                                case "Cancel":
 
54
                                        CancelBuild();
 
55
                                        break;
 
56
                                default:
 
57
                                        throw new InvalidOperationException("Unknown command");
 
58
                        }
 
59
                }
 
60
                
 
61
                static void AppDomain_CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
 
62
                {
 
63
                        ShowMessageBox(e.ExceptionObject.ToString());
 
64
                }
 
65
                
 
66
                #if RELEASE && WORKERDEBUG
 
67
                #error WORKERDEBUG must not be defined if RELEASE is defined
 
68
                #endif
 
69
                
 
70
                [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1300:SpecifyMessageBoxOptions")]
 
71
                internal static void ShowMessageBox(string text)
 
72
                {
 
73
                        System.Windows.Forms.MessageBox.Show(text, "SharpDevelop Build Worker Process");
 
74
                }
 
75
                
 
76
                [Conditional("DEBUG")]
 
77
                internal static void Log(string text)
 
78
                {
 
79
                        Debug.WriteLine(text);
 
80
                        #if WORKERDEBUG
 
81
                        DateTime now = DateTime.Now;
 
82
                        Console.WriteLine(now.ToString() + "," + now.Millisecond.ToString("d3") + " " + text);
 
83
                        #endif
 
84
                }
 
85
                
 
86
                [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
 
87
                public void StartBuild(BuildJob job)
 
88
                {
 
89
                        if (job == null)
 
90
                                throw new ArgumentNullException("job");
 
91
                        lock (this) {
 
92
                                if (currentJob != null)
 
93
                                        throw new InvalidOperationException("Already running a job");
 
94
                                currentJob = job;
 
95
                                requestCancellation = false;
 
96
                        }
 
97
                        #if WORKERDEBUG
 
98
                        Console.Title = "BuildWorker - " + Path.GetFileName(job.ProjectFileName);
 
99
                        #endif
 
100
                        Program.Log("Got job:");
 
101
                        Program.Log(job.ToString());
 
102
                        Program.Log("Start build thread");
 
103
                        Thread thread = new Thread(RunThread);
 
104
                        thread.Name = "Build thread";
 
105
                        thread.SetApartmentState(ApartmentState.STA);
 
106
                        thread.Start();
 
107
                }
 
108
                
 
109
                public void CancelBuild()
 
110
                {
 
111
                        Program.Log("CancelBuild()");
 
112
                        lock (this) {
 
113
                                if (!requestCancellation) {
 
114
                                        requestCancellation = true;
 
115
                                        buildWrapper.Cancel();
 
116
                                }
 
117
                        }
 
118
                }
 
119
                
 
120
                [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
 
121
                void RunThread()
 
122
                {
 
123
                        Program.Log("In build thread");
 
124
                        bool success = false;
 
125
                        try {
 
126
                                if (File.Exists(currentJob.ProjectFileName)) {
 
127
                                        success = buildWrapper.DoBuild(currentJob, new ForwardingLogger(this));
 
128
                                } else {
 
129
                                        success = false;
 
130
                                        HostReportEvent(new BuildErrorEventArgs(null, null, currentJob.ProjectFileName, 0, 0, 0, 0, "Project file '" + Path.GetFileName(currentJob.ProjectFileName) + "' not found", null, null));
 
131
                                }
 
132
                        } catch (Exception ex) {
 
133
                                host.Writer.Write("ReportException");
 
134
                                host.Writer.Write(ex.ToString());
 
135
                        } finally {
 
136
                                Program.Log("BuildDone");
 
137
                                
 
138
                                #if WORKERDEBUG
 
139
                                Console.Title = "BuildWorker - no job";
 
140
                                DisplayEventCounts();
 
141
                                #endif
 
142
                                
 
143
                                lock (this) {
 
144
                                        currentJob = null;
 
145
                                }
 
146
                                // in the moment we call BuildDone, we can get the next job
 
147
                                host.Writer.Write("BuildDone");
 
148
                                host.Writer.Write(success);
 
149
                        }
 
150
                }
 
151
                
 
152
                void HostReportEvent(BuildEventArgs e)
 
153
                {
 
154
                        host.Writer.Write("ReportEvent");
 
155
                        EventSource.EncodeEvent(host.Writer, e);
 
156
                }
 
157
                
 
158
                sealed class ForwardingLogger : ILogger
 
159
                {
 
160
                        Program program;
 
161
                        
 
162
                        public ForwardingLogger(Program program)
 
163
                        {
 
164
                                this.program = program;
 
165
                        }
 
166
                        
 
167
                        IEventSource eventSource;
 
168
                        
 
169
                        public LoggerVerbosity Verbosity { get; set; }
 
170
                        public string Parameters { get; set; }
 
171
                        
 
172
                        public void Initialize(IEventSource eventSource)
 
173
                        {
 
174
                                this.eventSource = eventSource;
 
175
                                EventTypes eventMask = program.currentJob.EventMask;
 
176
                                if ((eventMask & EventTypes.Message) != 0)
 
177
                                        eventSource.MessageRaised += OnEvent;
 
178
                                if ((eventMask & EventTypes.Error) != 0)
 
179
                                        eventSource.ErrorRaised += OnEvent;
 
180
                                if ((eventMask & EventTypes.Warning) != 0)
 
181
                                        eventSource.WarningRaised += OnEvent;
 
182
                                if ((eventMask & EventTypes.BuildStarted) != 0)
 
183
                                        eventSource.BuildStarted += OnEvent;
 
184
                                if ((eventMask & EventTypes.BuildFinished) != 0)
 
185
                                        eventSource.BuildFinished += OnEvent;
 
186
                                if ((eventMask & EventTypes.ProjectStarted) != 0)
 
187
                                        eventSource.ProjectStarted += OnEvent;
 
188
                                if ((eventMask & EventTypes.ProjectFinished) != 0)
 
189
                                        eventSource.ProjectFinished += OnEvent;
 
190
                                if ((eventMask & EventTypes.TargetStarted) != 0)
 
191
                                        eventSource.TargetStarted += OnEvent;
 
192
                                if ((eventMask & EventTypes.TargetFinished) != 0)
 
193
                                        eventSource.TargetFinished += OnEvent;
 
194
                                if ((eventMask & EventTypes.TaskStarted) != 0)
 
195
                                        eventSource.TaskStarted += OnEvent;
 
196
                                else
 
197
                                        eventSource.TaskStarted += OnTaskStarted;
 
198
                                if ((eventMask & EventTypes.TaskFinished) != 0)
 
199
                                        eventSource.TaskFinished += OnEvent;
 
200
                                else
 
201
                                        eventSource.TaskFinished += OnTaskFinished;
 
202
                                if ((eventMask & EventTypes.Custom) != 0)
 
203
                                        eventSource.CustomEventRaised += OnEvent;
 
204
                                if ((eventMask & EventTypes.Unknown) != 0)
 
205
                                        eventSource.AnyEventRaised += OnUnknownEventRaised;
 
206
                                
 
207
                                #if WORKERDEBUG
 
208
                                eventSource.AnyEventRaised += CountEvent;
 
209
                                #endif
 
210
                        }
 
211
                        
 
212
                        public void Shutdown()
 
213
                        {
 
214
                                EventTypes eventMask = program.currentJob.EventMask;
 
215
                                if ((eventMask & EventTypes.Message) != 0)
 
216
                                        eventSource.MessageRaised -= OnEvent;
 
217
                                if ((eventMask & EventTypes.Error) != 0)
 
218
                                        eventSource.ErrorRaised -= OnEvent;
 
219
                                if ((eventMask & EventTypes.Warning) != 0)
 
220
                                        eventSource.WarningRaised -= OnEvent;
 
221
                                if ((eventMask & EventTypes.BuildStarted) != 0)
 
222
                                        eventSource.BuildStarted -= OnEvent;
 
223
                                if ((eventMask & EventTypes.BuildFinished) != 0)
 
224
                                        eventSource.BuildFinished -= OnEvent;
 
225
                                if ((eventMask & EventTypes.ProjectStarted) != 0)
 
226
                                        eventSource.ProjectStarted -= OnEvent;
 
227
                                if ((eventMask & EventTypes.ProjectFinished) != 0)
 
228
                                        eventSource.ProjectFinished -= OnEvent;
 
229
                                if ((eventMask & EventTypes.TargetStarted) != 0)
 
230
                                        eventSource.TargetStarted -= OnEvent;
 
231
                                if ((eventMask & EventTypes.TargetFinished) != 0)
 
232
                                        eventSource.TargetFinished -= OnEvent;
 
233
                                if ((eventMask & EventTypes.TaskStarted) != 0)
 
234
                                        eventSource.TaskStarted -= OnEvent;
 
235
                                else
 
236
                                        eventSource.TaskStarted -= OnTaskStarted;
 
237
                                if ((eventMask & EventTypes.TaskFinished) != 0)
 
238
                                        eventSource.TaskFinished -= OnEvent;
 
239
                                else
 
240
                                        eventSource.TaskFinished -= OnTaskFinished;
 
241
                                if ((eventMask & EventTypes.Custom) != 0)
 
242
                                        eventSource.CustomEventRaised -= OnEvent;
 
243
                                if ((eventMask & EventTypes.Unknown) != 0)
 
244
                                        eventSource.AnyEventRaised -= OnUnknownEventRaised;
 
245
                                
 
246
                                #if WORKERDEBUG
 
247
                                eventSource.AnyEventRaised -= CountEvent;
 
248
                                #endif
 
249
                        }
 
250
                        
 
251
                        // used for all events that should be forwarded
 
252
                        void OnEvent(object sender, BuildEventArgs e)
 
253
                        {
 
254
                                program.HostReportEvent(e);
 
255
                        }
 
256
                        
 
257
                        // registered for AnyEventRaised to forward unknown events
 
258
                        void OnUnknownEventRaised(object sender, BuildEventArgs e)
 
259
                        {
 
260
                                if (EventSource.GetEventType(e) == EventTypes.Unknown)
 
261
                                        OnEvent(sender, e);
 
262
                        }
 
263
                        
 
264
                        // registered when only specific tasks should be forwarded
 
265
                        void OnTaskStarted(object sender, TaskStartedEventArgs e)
 
266
                        {
 
267
                                if (program.currentJob.InterestingTaskNames.Contains(e.TaskName))
 
268
                                        OnEvent(sender, e);
 
269
                        }
 
270
                        
 
271
                        // registered when only specific tasks should be forwarded
 
272
                        void OnTaskFinished(object sender, TaskFinishedEventArgs e)
 
273
                        {
 
274
                                if (program.currentJob.InterestingTaskNames.Contains(e.TaskName))
 
275
                                        OnEvent(sender, e);
 
276
                        }
 
277
                        
 
278
                        
 
279
                        #if WORKERDEBUG
 
280
                        void CountEvent(object sender, BuildEventArgs e)
 
281
                        {
 
282
                                Program.CountEvent(EventSource.GetEventType(e));
 
283
                        }
 
284
                        #endif
 
285
                }
 
286
                
 
287
                #if WORKERDEBUG
 
288
                static Dictionary<EventTypes, int> eventCounts = new Dictionary<EventTypes, int>();
 
289
                
 
290
                static void CountEvent(EventTypes e)
 
291
                {
 
292
                        if (eventCounts.ContainsKey(e))
 
293
                                eventCounts[e] += 1;
 
294
                        else
 
295
                                eventCounts[e] = 1;
 
296
                }
 
297
                
 
298
                static void DisplayEventCounts()
 
299
                {
 
300
                        foreach (var pair in eventCounts) {
 
301
                                Console.WriteLine("    " + pair.Key.ToString() + ": " + pair.Value.ToString());
 
302
                        }
 
303
                }
 
304
                #endif
 
305
        }
 
306
}