From a1e8d3de9a3794443d27f0989f43bb96b31faf76 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Tue, 8 Mar 2011 18:08:13 +0530 Subject: [PATCH] [xbuild] Implement FileLogger . Fix #676650 . * FileLogger.cs: Implement Add corresponding command line args for file loggers. Update man page. --- man/xbuild.1 | 30 ++++- .../Microsoft.Build.BuildEngine/FileLogger.cs | 108 +++++++++++++++++- mcs/tools/xbuild/ErrorUtilities.cs | 4 + mcs/tools/xbuild/Main.cs | 15 +++ mcs/tools/xbuild/Parameters.cs | 33 +++++- 5 files changed, 183 insertions(+), 7 deletions(-) diff --git a/man/xbuild.1 b/man/xbuild.1 index f1f0858521a..b1ec1f28531 100644 --- a/man/xbuild.1 +++ b/man/xbuild.1 @@ -41,8 +41,32 @@ Validate the project file against the schema .B \//validate: Validate the project file against the specified schema .TP -.B \//consoleloggerparameters: -Parameters for the console logger : PerfomanceSummary, NoSummary, NoItemAndPropertyList +.B \//consoleloggerparameters: , /clp: +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]: , /flp[n]: +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 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 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 diff --git a/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/FileLogger.cs b/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/FileLogger.cs index 865a2b52ec8..d816b66a370 100644 --- a/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/FileLogger.cs +++ b/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/FileLogger.cs @@ -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 @@ -27,23 +29,125 @@ #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=, 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=, 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 diff --git a/mcs/tools/xbuild/ErrorUtilities.cs b/mcs/tools/xbuild/ErrorUtilities.cs index 06ca4536dbe..a21048644b8 100644 --- a/mcs/tools/xbuild/ErrorUtilities.cs +++ b/mcs/tools/xbuild/ErrorUtilities.cs @@ -90,7 +90,11 @@ namespace Mono.XBuild.CommandLine { " /validate Validate the project file against the schema\n" + " /validate: Validate the project file against the specified schema\n" + " /consoleloggerparameters:\n" + + " /clp:\n" + " Parameters for the console logger\n" + + " /fileloggerparameters[n]:\n" + + " /flp[n]:\n" + + " Parameters for the file logger, eg. LogFile=foo.log\n" + " /nologo Don't show the initial banner\n" + " /help Show this help\n" ); diff --git a/mcs/tools/xbuild/Main.cs b/mcs/tools/xbuild/Main.cs index 00384779b0a..16cf7ea2ed5 100644 --- a/mcs/tools/xbuild/Main.cs +++ b/mcs/tools/xbuild/Main.cs @@ -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; diff --git a/mcs/tools/xbuild/Parameters.cs b/mcs/tools/xbuild/Parameters.cs index 6932907ecab..f0a3dc70cc1 100644 --- a/mcs/tools/xbuild/Parameters.cs +++ b/mcs/tools/xbuild/Parameters.cs @@ -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; } -- 2.25.1