Pregunta

Hay un script de MSBuild, que incluye el número de proyectos de Delphi y C #, pruebas de unidad, etc.

El problema es: ¿cómo marcar la compilación fallida si se generaron advertencias (para propósitos de prueba, no para compilaciones de lanzamiento)? El uso de LogError en lugar de LogWarning en tareas personalizadas no parece ser una buena opción, ya que la compilación debe probar tanto como sea posible (hasta que se produzca un error real) para informar de la mayor cantidad de advertencias posible en un momento (el proyecto de compilación se usa en CruiseControl.NET ).

Puede ser, la solución es crear mi propio registrador que almacene el indicador de advertencias en el interior, pero no puedo encontrar si hay una manera de leer este indicador al final de la compilación.

P.S. No hay problema en fallar la compilación inmediatamente después de recibir una advertencia (la salida del compilador de Delphi se procesa mediante una tarea personalizada, y / warnaserror podría usarse para C #), pero el comportamiento deseado es "compilar todo"; recoger todas las advertencias; falla la compilación " para informar sobre todas las advertencias, no solo sobre la primera.

P.P.S. En la medida en que realmente no necesito un número de advertencias, sino solo una marca de su presencia, decidí simplificar el mecanismo de señalización y usar Mutex trivial en lugar de la memoria compartida. El código está abajo:

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++;
        }
    }
}
¿Fue útil?

Solución

AFAIK MSBuild no tiene soporte incorporado para recuperar el recuento de advertencias en un punto dado del script de compilación. Sin embargo, puede seguir estos pasos para lograr este objetivo:

  1. Cree un registrador personalizado que escuche el evento de advertencia y cuente el número de advertencias
  2. Cree una tarea personalizada que exponga una propiedad [Output] WarningCount
  3. La tarea personalizada obtiene de alguna manera el valor del recuento de advertencias del registrador personalizado

El paso más difícil es el paso 3. Para esto hay varias opciones y puedes buscarlas libremente en IPC - Inter Process Comunication. Sigue un ejemplo práctico de cómo puedes lograr esto. Cada elemento es una Biblioteca de clases diferente.

SharedMemory

http://weblogs.asp.net/rosherove/ archive / 2003/05/01 / 6295.aspx

  

He creado un contenedor para nombre   memoria compartida que era parte de una   proyecto más grande. Básicamente permite   Tipos serializados y gráficos de objetos para   ser almacenado y recuperado de compartido   memoria (incluyendo como usted esperaría   proceso cruzado). Si el mayor   proyecto alguna vez se completa es otro   materia ;-).

SampleLogger

Implementa el registrador personalizado que realiza un seguimiento del recuento de advertencias.

namespace SampleLogger
{
    using System;
    using Microsoft.Build.Utilities;
    using Microsoft.Build.Framework;
    using DM.SharedMemory;

    public class MySimpleLogger : Logger
    {
        private Segment s;
        private int warningCount;

        public override void Initialize(IEventSource eventSource)
        {
            eventSource.WarningRaised += new BuildWarningEventHandler(eventSource_WarningRaised);

            this.s = new Segment("MSBuildMetadata", SharedMemoryCreationFlag.Create, 65535);
            this.s.SetData(this.warningCount.ToString());
        }

        void eventSource_WarningRaised(object sender, BuildWarningEventArgs e)
        {
            this.warningCount++;
            this.s.SetData(this.warningCount.ToString());
        }

        public override void Shutdown()
        {
            this.s.Dispose();
            base.Shutdown();
        }
    }
}

Tramas de muestra

Implementa la tarea personalizada que lee la cantidad de advertencias generadas en el proyecto MSbuild. La tarea personalizada se lee de la memoria compartida escrita por el registrador personalizado implementado en la biblioteca de clases SampleLogger .

namespace SampleTasks
{
    using System;
    using Microsoft.Build.Utilities;
    using Microsoft.Build.Framework;
    using DM.SharedMemory;

    public class BuildMetadata : Task
    {
        public int warningCount;

        [Output]
        public int WarningCount
        {
            get
            {
                Segment s = new Segment("MSBuildMetadata", SharedMemoryCreationFlag.Attach, 0);
                int warningCount = Int32.Parse(s.GetData() as string);
                return warningCount;
            }
        }

        public override bool Execute()
        {
            return true;
        }
    }
}

Dando una vuelta.

<?xml version="1.0" encoding="UTF-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Main">
    <UsingTask TaskName="BuildMetadata" AssemblyFile="F:\temp\SampleLogger\bin\debug\SampleTasks.dll" />

    <Target Name="Main">
        <Warning Text="Sample warning #1" />
        <Warning Text="Sample warning #2" />

        <BuildMetadata>
            <Output
                TaskParameter="WarningCount"
                PropertyName="WarningCount" />
        </BuildMetadata>

        <Error Text="A total of $(WarningCount) warning(s) were raised." Condition="$(WarningCount) > 0" />
    </Target>
</Project>

Si ejecuta el siguiente comando:

c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild test.xml /logger:SampleLogger.dll

Esta será la salida:

Microsoft (R) Build Engine Version 2.0.50727.3053
[Microsoft .NET Framework, Version 2.0.50727.3053]
Copyright (C) Microsoft Corporation 2005. All rights reserved.

Build started 30-09-2008 13:04:39.
__________________________________________________
Project "F:\temp\SampleLogger\bin\debug\test.xml" (default targets):

Target Main:
    F:\temp\SampleLogger\bin\debug\test.xml : warning : Sample warning #1
    F:\temp\SampleLogger\bin\debug\test.xml : warning : Sample warning #2
    F:\temp\SampleLogger\bin\debug\test.xml(15,3): error : A total of 2 warning(s) were raised.
Done building target "Main" in project "test.xml" -- FAILED.

Done building project "test.xml" -- FAILED.

Build FAILED.
F:\temp\SampleLogger\bin\debug\test.xml : warning : Sample warning #1
F:\temp\SampleLogger\bin\debug\test.xml : warning : Sample warning #2
F:\temp\SampleLogger\bin\debug\test.xml(15,3): error : A total of 2 warning(s) were raised.
    2 Warning(s)
    1 Error(s)

Time Elapsed 00:00:00.01

Otros consejos

El compilador de C # (csc.exe) tiene un modificador / warnaserror que tratará las advertencias como errores y fallará la compilación. Esto también está disponible como una configuración en el archivo .csproj. Supongo que Delphi tiene una habilidad similar.

msbuild.exe %~nx1 /t:Rebuild /p:Configuration=Release >> %MrB-BUILDLOG%
findstr /r /c:"[1-9][0-9]* Error(s)" >> %MrB-BUILDLOG%
if not errorlevel 1 (
   echo ERROR: sending notification email for build errors in '%~nx1'. >> %MrB-BUILDLOG%
) else (
   findstr /r /c:"[1-9][0-9]* Warning(s)" >> %MrB-BUILDLOG%
   if not errorlevel 1 (
       echo ERROR: sending notification email for build warnings in '%~nx1'. >>

% MrB-BUILDLOG%        ) otra cosa           echo Compilación exitosa de '% ~ nx1'. > > % MrB-BUILDLOG%        )     )

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top