[xbuild] Implement FileLogger . Fix #676650 .
authorAnkit Jain <radical@corewars.org>
Tue, 8 Mar 2011 12:38:13 +0000 (18:08 +0530)
committerAnkit Jain <radical@corewars.org>
Tue, 8 Mar 2011 12:42:30 +0000 (18:12 +0530)
* FileLogger.cs: Implement

Add corresponding command line args for file loggers.
Update man page.

man/xbuild.1
mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/FileLogger.cs
mcs/tools/xbuild/ErrorUtilities.cs
mcs/tools/xbuild/Main.cs
mcs/tools/xbuild/Parameters.cs

index f1f0858521af26c48bb911b52a5b78a6b7b914c4..b1ec1f28531e87bd146b0c224915458b491cb3dc 100644 (file)
@@ -41,8 +41,32 @@ Validate the project file against the schema
 .B \//validate:<schema>
 Validate the project file against the specified schema
 .TP
-.B \//consoleloggerparameters:<params>
-Parameters for the console logger : PerfomanceSummary, NoSummary, NoItemAndPropertyList
+.B \//consoleloggerparameters:<params> , /clp:<params>
+Parameters for the console logger : PerfomanceSummary, Summary, NoSummary, NoItemAndPropertyList, Verbosity
+.TP
+.B \//filelogger[n] , /fl[n]
+Logs the output to a file, named 'msbuild.log' by default. If the optional number 'n' is
+specified, then it logs to 'msbuild[n].log' . Parameters for this logger, including
+the log file name can be specified via a corresponding /flp[n] option. Default verbosity
+for file loggers is 'detailed. 'n' can be between 1-9.
+.TP
+.B \//fileloggerparameters[n]:<params> , /flp[n]:<params>
+Parameters for a file logger. This implies a corresponding /fl[n]. 'n' can be between
+1-9, and is used to add upto 10 file loggers. Parameters can be, besides the ones available
+for console logger:
+.RS
+.TP
+.I LogFile=<file>
+File to which the build log will be written.
+.TP
+.I Append
+If this is used, then the log file is appended to, else a new one will be created.
+.TP
+.I Encoding=<encoding>
+Encoding to use for the log file, eg. UTF-8, ASCII.
+.TP
+Eg: xbuild foo.csproj /flp:Verbosity=normal "/flp1:LogFile=build.log;Append;Encoding=ASCII"
+.RE
 .TP
 .B \//nologo
 Don't show the initial xbuild banner
@@ -162,7 +186,7 @@ looks in "/Library/Frameworks/Mono.framework/External/pkgconfig" .
 .SH SEE ALSO
 .BR mono(1), mcs(1)
 .SH COPYRIGHT
-Copyright (C) 2009 Novell, Inc (http://www.novell.com)
+Copyright (C) 2011 Novell, Inc (http://www.novell.com)
 .SH MAILING LISTS
 Visit http://lists.ximian.com/mailman/listinfo/mono-devel-list for details.
 .SH WEB SITE
index 865a2b52ec821e17ca0c500224db3974c638f6f9..d816b66a370701ac500b716591f29ae72327490e 100644 (file)
@@ -3,8 +3,10 @@
 //
 // Author:
 //   Marek Sieradzki (marek.sieradzki@gmail.com)
+//   Ankit Jain (jankit@novell.com)
 // 
 // (C) 2005 Marek Sieradzki
+// Copyright 2011 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 
 #if NET_2_0
 
+using System;
+using System.IO;
+using System.Text;
 using Microsoft.Build.Framework;
 
 namespace Microsoft.Build.BuildEngine {
        public class FileLogger : ConsoleLogger {
+               StreamWriter sw;
+               string logfile;
+               string encoding = null;
+               IEventSource eventSource;
+
                public FileLogger ()
                {
+                       base.Verbosity = LoggerVerbosity.Detailed;
                }
 
-               // FIXME: add our handlers to the events
                public override void Initialize (IEventSource eventSource)
                {
+                       this.eventSource = eventSource;
+                       logfile = "msbuild.log";
+
+                       bool append = false;
+                       string key, value;
+                       string[] splittedParameters = Parameters.Split (new char [] {';'}, StringSplitOptions.RemoveEmptyEntries);
+                       foreach (string s in splittedParameters) {
+                               if (String.Compare (s, "Append") == 0) {
+                                       append = true;
+                                       continue;
+                               }
+
+                               if (s.StartsWith ("Encoding")) {
+                                       if (!TrySplitKeyValuePair (s, out key, out value))
+                                               throw new LoggerException ("Encoding should be specified as: Encoding=<encoding>, eg. Encoding=UTF-8");
+
+                                       if (String.IsNullOrEmpty (value))
+                                               throw new LoggerException ("Encoding must be non-empty");
+
+                                       encoding = value;
+                                       continue;
+                               }
+
+                               if (s.StartsWith ("LogFile")) {
+                                       if (!TrySplitKeyValuePair (s, out key, out value))
+                                               throw new LoggerException ("LogFile should be specified as: LogFile=<encoding>, eg. LogFile=foo.log");
+
+                                       if (String.IsNullOrEmpty (value))
+                                               throw new LoggerException ("LogFile value must be non-empty");
+
+                                       logfile = value;
+                                       continue;
+                               }
+                       }
+
+                       // Attach *our* HandleBuildStarted as the first one,
+                       // as it needs to create the writer!
+                       eventSource.BuildStarted += HandleBuildStarted;
+                       base.Initialize (eventSource);
+                       // Attach *our* HandleBuildFinished as the last one,
+                       // as it needs to close the writer!
+                       eventSource.BuildFinished += HandleBuildFinished;
+
+                       CreateWriter (append);
+               }
+
+               void CreateWriter (bool append_to)
+               {
+                       if (sw != null)
+                               return;
+
+                       if (!String.IsNullOrEmpty (encoding))
+                               sw = new StreamWriter (logfile, append_to, Encoding.GetEncoding (encoding));
+                       else
+                               sw = new StreamWriter (logfile, append_to, Encoding.Default);
+                       WriteHandler = sw.WriteLine;
+               }
+
+               void HandleBuildStarted (object sender, BuildStartedEventArgs args)
+               {
+                       CreateWriter (true);
+               }
+
+               void HandleBuildFinished (object sender, BuildFinishedEventArgs args)
+               {
+                       base.WriteHandler = null;
+                       if (sw != null) {
+                               sw.Close ();
+                               sw = null;
+                       }
+               }
+
+               bool TrySplitKeyValuePair (string pair, out string key, out string value)
+               {
+                       key = value = null;
+                       string[] parts = pair.Split ('=');
+                       if (parts.Length != 2)
+                               return false;
+
+                       key = parts [0];
+                       value = parts [1];
+                       return true;
                }
 
                public override void Shutdown ()
                {
+                       base.WriteHandler = null;
+                       if (sw != null) {
+                               sw.Close ();
+                               sw = null;
+                       }
+
+                       if (eventSource != null) {
+                               eventSource.BuildStarted -= HandleBuildStarted;
+                               eventSource.BuildFinished -= HandleBuildFinished;
+                       }
+
+                       base.Shutdown ();
                }
        }
 }
 
-#endif
\ No newline at end of file
+#endif
index 06ca4536dbed52693c39056fed49320312735d84..a21048644b874a752367abc71a40125a008acbf0 100644 (file)
@@ -90,7 +90,11 @@ namespace Mono.XBuild.CommandLine {
                                "    /validate          Validate the project file against the schema\n" +
                                "    /validate:<schema> Validate the project file against the specified schema\n" +
                                "    /consoleloggerparameters:<params>\n" +
+                               "    /clp:<params>\n" +
                                "                       Parameters for the console logger\n" +
+                               "    /fileloggerparameters[n]:<params>\n" +
+                               "    /flp[n]:<params>\n" +
+                               "                       Parameters for the file logger, eg. LogFile=foo.log\n" +
                                "    /nologo            Don't show the initial banner\n" +
                                "    /help              Show this help\n"
                                );
index 00384779b0a70c1ce8aa939da0d2da2812bf07ab..16cf7ea2ed5a6573a8899041f95acce84ae93d3c 100644 (file)
@@ -98,6 +98,21 @@ namespace Mono.XBuild.CommandLine {
                                        cl.Verbosity = parameters.LoggerVerbosity; 
                                        engine.RegisterLogger (cl);
                                }
+
+                               if (parameters.FileLoggerParameters != null) {
+                                       for (int i = 0; i < parameters.FileLoggerParameters.Length; i ++) {
+                                               string fl_params = parameters.FileLoggerParameters [i];
+                                               if (fl_params == null)
+                                                       continue;
+
+                                               var fl = new FileLogger ();
+                                               if (fl_params.Length == 0 && i > 0)
+                                                       fl.Parameters = String.Format ("LogFile=msbuild{0}.log", i);
+                                               else
+                                                       fl.Parameters = fl_params;
+                                               engine.RegisterLogger (fl);
+                                       }
+                               }
                                
                                foreach (LoggerInfo li in parameters.Loggers) {
                                        Assembly assembly;
index 6932907ecabb25ada3d97bbe5820b139e41df658..f0a3dc70cc1a146a0503d31374376601d455becd 100644 (file)
@@ -81,6 +81,7 @@ namespace Mono.XBuild.CommandLine {
                        flatArguments = new ArrayList ();
                        remainingArguments = new ArrayList ();
                        responseFiles = new Hashtable ();
+                       FileLoggerParameters = new string[10];
                        foreach (string s in args) {
                                if (s.StartsWith ("/noautoresponse") || s.StartsWith ("/noautorsp")) {
                                        autoResponse = false;
@@ -222,8 +223,19 @@ namespace Mono.XBuild.CommandLine {
                        case "/val":
                                validate = true;
                                break;
+                       case "/fl":
+                       case "/filelogger":
+                               if (FileLoggerParameters [0] == null)
+                                       FileLoggerParameters [0] = String.Empty;
+                               break;
                        default:
-                               if (s.StartsWith ("/target:") || s.StartsWith ("/t:")) {
+                               if (s.StartsWith ("/fl") && s.Length == 4 && Char.IsDigit (s[3])) {
+                                       int index = Int32.Parse (s[3].ToString ());
+                                       if (FileLoggerParameters [index] == null)
+                                               FileLoggerParameters [index] = String.Empty;
+                               } else if (s.StartsWith ("/fileloggerparameters") || s.StartsWith ("/flp")) {
+                                       ProcessFileLoggerParameters (s);
+                               } else if (s.StartsWith ("/target:") || s.StartsWith ("/t:")) {
                                        ProcessTarget (s);
                                } else if (s.StartsWith ("/property:") || s.StartsWith ("/p:")) {
                                        if (!ProcessProperty (s))
@@ -327,7 +339,22 @@ namespace Mono.XBuild.CommandLine {
                                break;
                        }
                }
-               
+
+               void ProcessFileLoggerParameters (string s)
+               {
+                       int colon = s.IndexOf (':');
+                       if (colon + 1 == s.Length)
+                               ReportError (5, "Invalid syntax, specify parameters as /fileloggerparameters[n]:parameters");
+
+                       int index = 0;
+                       string key = s.Substring (0, colon);
+                       if (Char.IsDigit (key [key.Length - 1]))
+                       //if (key.Length == 22 && Char.IsDigit (key [21]))
+                               index = Int32.Parse (key [key.Length - 1].ToString ());
+
+                       FileLoggerParameters [index] = s.Substring (colon + 1);
+               }
+
                internal void ProcessConsoleLoggerParameters (string s)
                {
                        int colon = s.IndexOf (':');
@@ -379,6 +406,8 @@ namespace Mono.XBuild.CommandLine {
                public bool NoConsoleLogger {
                        get { return noConsoleLogger; }
                }
+
+               public string[] FileLoggerParameters { get; set; }
                
                public bool Validate {
                        get { return validate; }