There is a MSBuild script, that includes number if Delphi and C# projects, unit tests etc.
The problem is: how to mark build failed if warnings were raised (for testing purposes, not for release builds)? Using LogError instead of LogWarning in custom tasks seems to be not a good option, because the build should test as much as it’s able (until real error) to report as much warnings as possible in a time (build project is using in CruiseControl.NET).
May be, the solution is to create my own logger that would store warnings flag inside, but I cannot find if there is a way to read this flag in the end of build?
P.S. There is no problem to fail the build immediately after receiving a warning (Delphi compiler output is processed by custom task, and /warnaserror could be used for C#), but the desired behavior is ‘build everything; collect all warnings; fail the build’ to report about all warnings, not only about the first one.
P.P.S. As far as I really need not number of warnings, but just flag of their presence, I decided to simplify signaling mechanism, and use trivial Mutex instead of shared memory. Code is below:
using System; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using System.Threading; namespace Intrahealth.Build.WarningLogger { public sealed class WarningLoggerCheck : Task { public override bool Execute() { Log.LogMessage('WarningLoggerCheck:' + mutexName + '...'); result = false; Mutex m = null; try { m = Mutex.OpenExisting(mutexName); } catch (WaitHandleCannotBeOpenedException) { result = true; } catch (Exception) { } if (result) Log.LogMessage('WarningLoggerCheck PASSED'); else Log.LogError('Build log contains warnings. Build is FAILED'); return result; } private bool result = true; [Output] public bool Result { get { return result; } } private string mutexName = 'WarningLoggerMutex'; public string MutexName { get { return mutexName; } set { mutexName = value ?? 'WarningLoggerMutex'; } } } public class WarningLogger : Logger { internal static int warningsCount = 0; private string mutexName = String.Empty; private Mutex mutex = null; public override void Initialize(IEventSource eventSource) { eventSource.WarningRaised += new BuildWarningEventHandler(eventSource_WarningRaised); } private void SetMutex() { if (mutexName == String.Empty) { mutexName = 'WarningLoggerMutex'; if (this.Parameters != null && this.Parameters != String.Empty) { mutexName = this.Parameters; } } mutex = new Mutex(false, mutexName); } void eventSource_WarningRaised(object sender, BuildWarningEventArgs e) { if (e.Message != null && e.Message.Contains('MSB3146')) return; if (e.Code != null && e.Code.Equals('MSB3146')) return; if (warningsCount == 0) SetMutex(); warningsCount++; } } }
AFAIK MSBuild has no built-in support to retrieve the warning count at a given point of the build script. You can however follow these steps to achieve this goal:
The most difficult step is step 3. For this there are several options and you can freely search them under IPC – Inter Process Comunication. Follows a working example of how you can achieve this. Each item is a different Class Library.
SharedMemory
http://weblogs.asp.net/rosherove/archive/2003/05/01/6295.aspx
SampleLogger
Implements the custom logger that keeps track of the warning count.
SampleTasks
Implements the custom task that reads the number of warnings raised in the MSbuild project. The custom task reads from the shared memory written by the custom logger implemented in class library SampleLogger.
Going for a spin.
If you run the following command:
This will be the output: