Merge pull request #1156 from felfert/master
[mono.git] / mcs / tools / msbuild / Main.cs
1 //
2 // Main.cs: Main program file of command line utility.
3 //
4 // Author:
5 //   Marek Sieradzki (marek.sieradzki@gmail.com)
6 //   Miguel de Icaza (miguel@ximian.com)
7 //   Marek Safar (marek.safar@seznam.cz)
8 //
9 // (C) 2005 Marek Sieradzki
10 // Copyright 2009 Novell, Inc (http://www.novell.com)
11 // Copyright 2011 Xamarin Inc (http://www.xamarin.com).
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using Microsoft.Build.Utilities;
32 using Microsoft.Build.Exceptions;
33 using Microsoft.Build.Construction;
34 using System.Xml;
35 using System.Xml.Schema;
36 using System.Linq;
37 using System.Collections.Generic;
38
39
40 using System;
41 using System.Collections;
42 using System.IO;
43 using System.Reflection;
44 using System.Text;
45 using Microsoft.Build.Evaluation;
46 using Microsoft.Build.Execution;
47 using Microsoft.Build.Framework;
48 using Microsoft.Build.Logging;
49 using Mono.XBuild.Framework;
50
51 class MonoTODOAttribute : Attribute
52 {
53 }
54
55 namespace Mono.XBuild.CommandLine {
56         public class MainClass {
57                 
58                 Parameters      parameters;
59                 string[]        args;
60                 string          defaultSchema;
61                 
62                 ProjectCollection               project_collection;
63                 ProjectRootElement              project;
64                 ConsoleReportPrinter printer;
65
66                 
67                 public static void Main (string[] args)
68                 {
69                         MainClass mc = new MainClass ();
70                         mc.args = args;
71                         mc.Execute ();
72                 }
73                 
74                 public MainClass ()
75                 {
76                         string binPath = ToolLocationHelper.GetPathToDotNetFramework (TargetDotNetFrameworkVersion.Version20);
77                         defaultSchema = Path.Combine (binPath, "Microsoft.Build.xsd");
78                         parameters = new Parameters ();
79                 }
80
81                 public void Execute ()
82                 {
83                         bool result = false;
84                         bool show_stacktrace = false;
85                         
86                         try {
87                                 parameters.ParseArguments (args);
88                                 show_stacktrace = (parameters.LoggerVerbosity == LoggerVerbosity.Detailed ||
89                                         parameters.LoggerVerbosity == LoggerVerbosity.Diagnostic);
90                                 
91                                 if (!parameters.NoLogo)
92                                         ErrorUtilities.ShowVersion (false);
93                                 
94                                 project_collection  = new ProjectCollection ();
95                                 if (!String.IsNullOrEmpty (parameters.ToolsVersion)) {
96                                         if (project_collection.GetToolset (parameters.ToolsVersion) == null)
97                                                 ErrorUtilities.ReportError (0, new InvalidToolsetDefinitionException ("Toolset " + parameters.ToolsVersion + " was not found").Message);
98
99                                         project_collection.DefaultToolsVersion = parameters.ToolsVersion;
100                                 }
101                                 
102                                 foreach (var p in parameters.Properties)
103                                         project_collection.GlobalProperties.Add (p.Key, p.Value);
104                                 
105                                 if (!parameters.NoConsoleLogger) {
106                                         printer = new ConsoleReportPrinter ();
107                                         ConsoleLogger cl = new ConsoleLogger (parameters.LoggerVerbosity,
108                                                         printer.Print, printer.SetForeground, printer.ResetColor);
109
110                                         cl.Parameters = parameters.ConsoleLoggerParameters;
111                                         cl.Verbosity = parameters.LoggerVerbosity; 
112                                         project_collection.RegisterLogger (cl);
113                                 }
114
115                                 if (parameters.FileLoggerParameters != null) {
116                                         for (int i = 0; i < parameters.FileLoggerParameters.Length; i ++) {
117                                                 string fl_params = parameters.FileLoggerParameters [i];
118                                                 if (fl_params == null)
119                                                         continue;
120
121                                                 var fl = new FileLogger ();
122                                                 if (fl_params.Length == 0 && i > 0)
123                                                         fl.Parameters = String.Format ("LogFile=msbuild{0}.log", i);
124                                                 else
125                                                         fl.Parameters = fl_params;
126                                                 project_collection.RegisterLogger (fl);
127                                         }
128                                 }
129                                 
130                                 foreach (LoggerInfo li in parameters.Loggers) {
131                                         Assembly assembly;
132                                         if (li.InfoType == LoadInfoType.AssemblyFilename)
133                                                 assembly = Assembly.LoadFrom (li.Filename);
134                                         else
135                                                 assembly = Assembly.Load (li.AssemblyName);
136                                         ILogger logger = (ILogger)Activator.CreateInstance (assembly.GetType (li.ClassName));
137                                         logger.Parameters = li.Parameters;
138                                         project_collection.RegisterLogger (logger); 
139                                 }
140                                 
141                                 string projectFile = parameters.ProjectFile;
142                                 if (!File.Exists (projectFile)) {
143                                         ErrorUtilities.ReportError (0, String.Format ("Project file '{0}' not found.", projectFile));
144                                         return;
145                                 }
146
147                                 XmlReaderSettings settings = new XmlReaderSettings ();
148                                 if (parameters.Validate) {
149                                         settings.ValidationType = ValidationType.Schema;
150                                         if (parameters.ValidationSchema == null)
151                                                 using (var xsdxml = XmlReader.Create (defaultSchema))
152                                                         settings.Schemas.Add (XmlSchema.Read (xsdxml, null));
153                                         else
154                                                 using (var xsdxml = XmlReader.Create (parameters.ValidationSchema))
155                                                         settings.Schemas.Add (XmlSchema.Read (xsdxml, null));
156                                 }
157
158                                 var projectInstances = new List<ProjectInstance> ();
159                                 if (string.Equals (Path.GetExtension (projectFile), ".sln", StringComparison.OrdinalIgnoreCase)) {
160                                         var parser = new SolutionParser ();
161                                         var root = ProjectRootElement.Create (project_collection);
162                                         root.FullPath = projectFile;
163                                         parser.ParseSolution (projectFile, project_collection, root, LogWarning);
164                                         projectInstances.Add (new Project (root, parameters.Properties, parameters.ToolsVersion, project_collection).CreateProjectInstance ());
165                                 } else {
166                                         project = ProjectRootElement.Create (XmlReader.Create (projectFile, settings), project_collection);
167                                         project.FullPath = projectFile;
168                                         var pi = new ProjectInstance (project, parameters.Properties, parameters.ToolsVersion, project_collection);
169                                         projectInstances.Add (pi);
170                                 }
171                                 foreach (var projectInstance in projectInstances) {
172                                         var targets = parameters.Targets.Length > 0 ? parameters.Targets : projectInstance.DefaultTargets.ToArray ();
173                                         result = projectInstance.Build (targets, parameters.Loggers.Count > 0 ? parameters.Loggers : project_collection.Loggers);
174                                         if (!result)
175                                                 break;
176                                 }
177                         }
178                         
179                         catch (InvalidProjectFileException ipfe) {
180                                 ErrorUtilities.ReportError (0, show_stacktrace ? ipfe.ToString () : ipfe.Message);
181                         }
182
183                         catch (InternalLoggerException ile) {
184                                 ErrorUtilities.ReportError (0, show_stacktrace ? ile.ToString () : ile.Message);
185                         }
186
187                         catch (CommandLineException cle) {
188                                 ErrorUtilities.ReportError(cle.ErrorCode, show_stacktrace ? cle.ToString() : cle.Message);
189                         }
190                         finally {
191                                 //if (project_collection != null)
192                                 //      project_collection.UnregisterAllLoggers ();
193
194                                 Environment.Exit (result ? 0 : 1);
195                         }
196                 }
197
198                 void LogWarning (int errorNumber, string message)
199                 {
200                         Console.Error.WriteLine ("Warning {0}: {1}", errorNumber, message);
201                 }
202         }
203
204         // code from mcs/report.cs
205         class ConsoleReportPrinter
206         {
207                 string prefix, postfix;
208                 bool color_supported;
209                 TextWriter writer;
210                 string [] colorPrefixes;
211
212                 public ConsoleReportPrinter ()
213                         : this (Console.Out)
214                 {
215                 }
216
217                 public ConsoleReportPrinter (TextWriter writer)
218                 {
219                         this.writer = writer;
220
221                         string term = Environment.GetEnvironmentVariable ("TERM");
222                         bool xterm_colors = false;
223
224                         color_supported = false;
225                         switch (term){
226                         case "xterm":
227                         case "rxvt":
228                         case "rxvt-unicode":
229                                 if (Environment.GetEnvironmentVariable ("COLORTERM") != null){
230                                         xterm_colors = true;
231                                 }
232                                 break;
233
234                         case "xterm-color":
235                         case "xterm-256color":
236                                 xterm_colors = true;
237                                 break;
238                         }
239                         if (!xterm_colors)
240                                 return;
241
242                         if (!(UnixUtils.isatty (1) && UnixUtils.isatty (2)))
243                                 return;
244
245                         color_supported = true;
246                         PopulateColorPrefixes ();
247                         postfix = "\x001b[0m";
248                 }
249
250                 void PopulateColorPrefixes ()
251                 {
252                         colorPrefixes = new string [16];
253
254                         colorPrefixes [(int)ConsoleColor.Black] = GetForeground ("black");
255                         colorPrefixes [(int)ConsoleColor.DarkBlue] = GetForeground ("blue");
256                         colorPrefixes [(int)ConsoleColor.DarkGreen] = GetForeground ("green");
257                         colorPrefixes [(int)ConsoleColor.DarkCyan] = GetForeground ("cyan");
258                         colorPrefixes [(int)ConsoleColor.DarkRed] = GetForeground ("red");
259                         colorPrefixes [(int)ConsoleColor.DarkMagenta] = GetForeground ("magenta");
260                         colorPrefixes [(int)ConsoleColor.DarkYellow] = GetForeground ("yellow");
261                         colorPrefixes [(int)ConsoleColor.DarkGray] = GetForeground ("grey");
262
263                         colorPrefixes [(int)ConsoleColor.Gray] = GetForeground ("brightgrey");
264                         colorPrefixes [(int)ConsoleColor.Blue] = GetForeground ("brightblue");
265                         colorPrefixes [(int)ConsoleColor.Green] = GetForeground ("brightgreen");
266                         colorPrefixes [(int)ConsoleColor.Cyan] = GetForeground ("brightcyan");
267                         colorPrefixes [(int)ConsoleColor.Red] = GetForeground ("brightred");
268                         colorPrefixes [(int)ConsoleColor.Magenta] = GetForeground ("brightmagenta");
269                         colorPrefixes [(int)ConsoleColor.Yellow] = GetForeground ("brightyellow");
270
271                         colorPrefixes [(int)ConsoleColor.White] = GetForeground ("brightwhite");
272                 }
273
274                 public void SetForeground (ConsoleColor color)
275                 {
276                         if (color_supported)
277                                 prefix = colorPrefixes [(int)color];
278                 }
279
280                 public void ResetColor ()
281                 {
282                         prefix = "\x001b[0m";
283                 }
284
285                 static int NameToCode (string s)
286                 {
287                         switch (s) {
288                         case "black":
289                                 return 0;
290                         case "red":
291                                 return 1;
292                         case "green":
293                                 return 2;
294                         case "yellow":
295                                 return 3;
296                         case "blue":
297                                 return 4;
298                         case "magenta":
299                                 return 5;
300                         case "cyan":
301                                 return 6;
302                         case "grey":
303                         case "white":
304                                 return 7;
305                         }
306                         return 7;
307                 }
308
309                 //
310                 // maps a color name to its xterm color code
311                 //
312                 static string GetForeground (string s)
313                 {
314                         string highcode;
315
316                         if (s.StartsWith ("bright")) {
317                                 highcode = "1;";
318                                 s = s.Substring (6);
319                         } else
320                                 highcode = "";
321
322                         return "\x001b[" + highcode + (30 + NameToCode (s)).ToString () + "m";
323                 }
324
325                 static string GetBackground (string s)
326                 {
327                         return "\x001b[" + (40 + NameToCode (s)).ToString () + "m";
328                 }
329
330                 string FormatText (string txt)
331                 {
332                         if (prefix != null && color_supported)
333                                 return prefix + txt + postfix;
334
335                         return txt;
336                 }
337
338                 public void Print (string message)
339                 {
340                         writer.WriteLine (FormatText (message));
341                 }
342
343         }
344
345         class UnixUtils {
346                 [System.Runtime.InteropServices.DllImport ("libc", EntryPoint="isatty")]
347                 extern static int _isatty (int fd);
348
349                 public static bool isatty (int fd)
350                 {
351                         try {
352                                 return _isatty (fd) == 1;
353                         } catch {
354                                 return false;
355                         }
356                 }
357         }
358
359 }
360