2010-04-29 11 views
13

Estoy trabajando en un MSBuild Target reutilizable que será consumido por otras tareas. Este objetivo requiere que se definan varias propiedades. ¿Cuál es la mejor manera de validar que las propiedades estén definidas, arrojando un error si no lo están?MSBuild Validating Properties

Dos intentos que casi como:

<?xml version="1.0" encoding="utf-8" ?> 
    <Project ToolsVersion="3.5" DefaultTarget="Release" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 

    <Target Name="Release"> 
    <Error 
     Text="Property PropA required" 
     Condition="'$(PropA)' == ''"/> 
    <Error 
     Text="Property PropB required" 
     Condition="'$(PropB)' == ''"/> 

    <!-- The body of the task --> 

    </Target> 
</Project> 

Esto es un intento de procesamiento por lotes. Es feo por el parámetro adicional "Nombre". ¿Es posible utilizar el atributo Incluir en su lugar?

<?xml version="1.0" encoding="utf-8" ?> 
<Project ToolsVersion="3.5" DefaultTarget="Release" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <Target Name="Release"> 
    <!-- MSBuild BuildInParallel="true" Projects="@(ProjectsToBuild)"/ --> 
    <ItemGroup> 
     <RequiredProperty Include="PropA"><Name>PropA</Name></RequiredProperty> 
     <RequiredProperty Include="PropB"><Name>PropB</Name></RequiredProperty> 
     <RequiredProperty Include="PropC"><Name>PropC</Name></RequiredProperty> 
    </ItemGroup> 

    <Error 
     Text="Property %(RequiredProperty.Name) required" 
     Condition="'$(%(RequiredProperty.Name))' == ''" /> 

    </Target> 

</Project> 

Respuesta

16

¡Gran pregunta! He escrito sobre esto en profundidad en mi book y en una publicación de blog, Elements of Reusable MSBuild Scripts: Validation. Mi enfoque cubrirá propiedades y artículos.

Aquí está el descuidado. En el archivo .targets compartido cree un objetivo de validación, y este debería ser uno de los primeros objetivos declarados en el archivo para que los usuarios puedan ubicarlo fácilmente.

Propiedades

Dentro del objetivo de la validación definen sus propiedades como esta:

<_RequiredProperties Include="Root"> 
    <Value>$(Root)</Value> 
</_RequiredProperties> 

que coloque el nombre de la propiedad en el incluir y su valor dentro de la metadata.The razón por qué Value Lo hago para poder detectar cuando Value está en blanco y luego uso el valor de inclusión para informar el nombre de la propiedad que falta al usuario.

Artículos

En el interior del lugar de destino los elementos necesarios dentro de un artículo como:

<_RequiredItems Include="AllConfigurations"> 
    <RequiredValue>@(AllConfigurations)</RequiredValue> 
</_RequiredItems> 

similares a las propiedades, dentro de la incluyen colocar el nombre del elemento y el valor para verificar dentro de los metadatos RequiredValue. En este ejemplo, solo comprueba para asegurarse de que el elemento AllConfiguraitons no esté vacío. Si desea asegurarse de que un valor determinado metadatos se especifica en todos los artículos a continuación, hacer algo como:

<_RequiredItems Include = "AllConfigurations.Configuration"> 
    <RequiredValue>%(AllConfigurations.Configuration </RequiredValue> 
</_RequiredItems> 

Si desea asegurarse de que existe un archivo a continuación, añadir los metadatos adicionales, RequiredFilePath.

<_RequiredItems Include ="ProjectsToBuild"> 
    <RequiredValue>%(ProjectsToBuild.Identity)</RequiredValue> 
    <RequiredFilePath>%(ProjectsToBuild.Identity)</RequiredFilePath> 
</_RequiredItems> 

Validación

Aquí es lo que necesita para llevar a cabo la validación

Ejemplo completo

Aquí está el ejemplo completo

<Target Name="ValidateBuildSettings"> 
    <ItemGroup> 
    <_RequiredProperties Include="Root"> 
     <Value>$(Root)</Value> 
    </_RequiredProperties> 

    <_RequiredProperties Include="BuildInstallRoot"> 
     <Value>$(BuildInstallRoot)</Value> 
    </_RequiredProperties> 

    <_RequiredProperties Include="SourceRoot"> 
     <Value>$(SourceRoot)</Value> 
    </_RequiredProperties> 
    <!-- 
    _RequiredItems is the item where required items should be placed. 
    The following metadata is significant: 
     REQUIRED METADATA: 
     Identity   = This will basically be used to identify the specific required item 
     RequiredValue  = This is the specific value that will be validated to exist 

     OPTIONAL METADATA 
     RequiredFilePath = Populate this with a path that should exists, if it is not empty 
          then it will be checked to exist on disk. 
    --> 

    <_RequiredItems Include="AllConfigurations"> 
     <RequiredValue>@(AllConfigurations)</RequiredValue> 
    </_RequiredItems> 
    <_RequiredItems Include = "AllConfigurations.Configuration"> 
     <RequiredValue>%(AllConfigurations.Configuration </RequiredValue> 
    </_RequiredItems> 
    <_RequiredItems Include ="ProjectsToBuild"> 
     <RequiredValue>%(ProjectsToBuild.Identity)</RequiredValue> 
     <RequiredFilePath>%(ProjectsToBuild.Identity)</RequiredFilePath> 
    </_RequiredItems> 
    </ItemGroup> 
    <!-- Raise an error if any value in _RequiredProperties is missing --> 

    <Error Condition =" '%(_RequiredProperties.Value)'=='' " 
      Text=" Missing required property [%(_RequiredProperties.Identity)]" /> 

    <!-- Raise an error if any value in _RequiredItems is empty --> 
    <Error Condition = " '%(_RequiredItems.RequiredValue)'=='' " 
      Text = " Missing required item value [%(_RequiredItems.Identity)] " /> 

    <!-- Validate any file/directory that should exist --> 
    <Error Condition = " '%(_RequiredItems.RequiredFilePath)' != '' and !Exists('%(_RequiredItems.RequiredFilePath)') " 
      Text = " Unable to find expeceted path [%(_RequiredItems.RequiredFilePath)] on item [%(_RequiredItems.Identity)] " /> 
</Target> 
+0

Excelente - esto es justo lo que estaba buscando. Parece que también necesitaré recoger una copia de tu libro :) –