msbuild itemgroup

Problema del patrón MSBuild ItemGroup Include/Exclude



(2)

Problema: una matriz ItemGroups no se construye correctamente en función del valor pasado en el atributo de exclusión.

Si ejecuta este scrip crea un archivo de muestra y luego intenta crear un array llamado TheFiles basado en los atributos Include / Exclude, el problema es cuando el Exclude es algo diferente de hardcoded o una propiedad muy simple que lo hace mal.

El objetivo DynamicExcludeList selecciona incorrectamente estos archivos:
. / AFolder / test.cs;. / AFolder / test.txt

El objetivo HardcodedExcludeList selecciona correctamente estos archivos:
. / AFolder / test.txt

Cualquier ayuda muy apreciada, esto me está volviendo loco.

(tenga en cuenta su msbuild v4)

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Run"> <Target Name="Run" > <CallTarget Targets="CreateSampleFiles" /> <CallTarget Targets="DynamicExcludeList" /> <CallTarget Targets="HardcodedExcludeList" /> </Target> <Target Name="CreateSampleFiles" > <MakeDir Directories="AFolder" /> <WriteLinesToFile Lines="Test" File="AFolder/test.cs" Overwrite="true" /> <WriteLinesToFile Lines="Test" File="AFolder/test.txt" Overwrite="true" /> </Target> <Target Name="DynamicExcludeList" > <PropertyGroup> <CommonFileExclusion>./DIRECTORY_NAME_TOKEN/**/*.cs</CommonFileExclusion> <FinalExcludes>$(CommonFileExclusion.Replace(''DIRECTORY_NAME_TOKEN'', ''AFolder''))</FinalExcludes> </PropertyGroup> <Message Text="FinalExcludes: $(FinalExcludes)" /> <ItemGroup> <TheFiles Include="./AFolder/**/*;" Exclude="$(FinalExcludes)" /> </ItemGroup> <Message Text="TheFiles: @(TheFiles)" /> </Target> <Target Name="HardcodedExcludeList" > <PropertyGroup> <FinalExcludes>./AFolder/**/*.cs</FinalExcludes> </PropertyGroup> <Message Text="FinalExcludes: $(FinalExcludes)" /> <ItemGroup> <TheFilesWithHardcodedExcludes Include="./AFolder/**/*;" Exclude="$(FinalExcludes)" /> </ItemGroup> <Message Text="TheFilesWithHardcodedExcludes: @(TheFilesWithHardcodedExcludes)" /> </Target> </Project>

Este es el resultado, tenga en cuenta las diferencias entre ''TheFiles'' y ''TheFilesWithHardcodedExcludes''

PS C:/SVN/TrunkDeployment/TestMsBuild> msbuild ./Test.build.xml Microsoft (R) Build Engine Version 4.0.30319.1 [Microsoft .NET Framework, Version 4.0.30319.1] Copyright (C) Microsoft Corporation 2007. All rights reserved. Build started 8/10/2010 2:30:42 PM. Project "C:/SVN/TrunkDeployment/TestMsBuild/Test.build.xml" on node 1 (default targets). DynamicExcludeList: FinalExcludes: ./AFolder/**/*.cs TheFiles: ./AFolder/test.cs;./AFolder/test.txt HardcodedExcludeList: FinalExcludes: ./AFolder/**/*.cs TheFilesWithHardcodedExcludes: ./AFolder/test.txt Done Building Project "C:/SVN/TrunkDeployment/TestMsBuild/Test.build.xml" (default targets). Build succeeded. 0 Warning(s) 0 Error(s) Time Elapsed 00:00:00.06

EDITS

He actualizado el script anterior para usar CreateItem, sin embargo, todavía hay un problema cuando la lista de elementos para excluir contiene más de 1 ruta (es decir, el valor de CommonFileExclusion ha cambiado):

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Run"> <Target Name="Run" > <CallTarget Targets="CreateSampleFiles" /> <CallTarget Targets="DynamicExcludeList" /> <CallTarget Targets="HardcodedExcludeList" /> </Target> <Target Name="CreateSampleFiles" > <MakeDir Directories="AFolder" /> <WriteLinesToFile Lines="Test" File="AFolder/test.cs" Overwrite="true" /> <WriteLinesToFile Lines="Test" File="AFolder/test.txt" Overwrite="true" /> <WriteLinesToFile Lines="Test" File="AFolder/test.vb" Overwrite="true" /> </Target> <Target Name="DynamicExcludeList" > <PropertyGroup> <CommonFileExclusion>./DIRECTORY_NAME_TOKEN/**/*.cs;./DIRECTORY_NAME_TOKEN/**/*.vb;</CommonFileExclusion> <FinalExcludes>$(CommonFileExclusion.Replace(''DIRECTORY_NAME_TOKEN'', ''AFolder''))</FinalExcludes> </PropertyGroup> <Message Text="FinalExcludes: $(FinalExcludes)" /> <CreateItem Include="./AFolder/**/*;" Exclude="$(FinalExcludes)"> <Output TaskParameter="Include" ItemName="TheFiles"/> </CreateItem> <Message Text="TheFiles: @(TheFiles)" /> </Target> <Target Name="HardcodedExcludeList" > <PropertyGroup> <FinalExcludes>./AFolder/**/*.cs;./AFolder/**/*.vb</FinalExcludes> </PropertyGroup> <Message Text="FinalExcludes: $(FinalExcludes)" /> <CreateItem Include="./AFolder/**/*;" Exclude="$(FinalExcludes)"> <Output TaskParameter="Include" ItemName="TheFilesWithHardcodedExcludes"/> </CreateItem> <Message Text="TheFilesWithHardcodedExcludes: @(TheFilesWithHardcodedExcludes)" /> </Target> </Project>


En el destino DynamicExcludeList use la tarea CreateItem lugar de ItemGroup para generar dinámicamente su elemento:

<Target Name="DynamicExcludeList" > <PropertyGroup> <CommonFileExclusion>./DIRECTORY_NAME_TOKEN/**/*.cs</CommonFileExclusion> <FinalExcludes>$(CommonFileExclusion.Replace(''DIRECTORY_NAME_TOKEN'', ''AFolder''))</FinalExcludes> </PropertyGroup> <Message Text="FinalExcludes: $(FinalExcludes)" /> <CreateItem Include="./AFolder/**/*;" Exclude="$(FinalExcludes)"> <Output TaskParameter="Include" ItemName="TheFiles"/> </CreateItem> <Message Text="TheFiles: @(TheFiles)" /> </Target>

Teóricamente ItemGroup y CreateItem son equivalentes pero he visto un caso (situación dinámica) como este cuando se debe usar CreateItem .


Ok, probé un poco y creo que el problema proviene del hecho de que usas una propiedad que representa el valor SCALAR para valores múltiples. Recomendaría el procesamiento por lotes y la transformación (consulte http://scottlaw.knot.org/blog/?p=402 y http://msdn.microsoft.com/en-us/library/ms171476.aspx ). Por ejemplo, el siguiente código está funcionando:

<Target Name="DynamicExcludeList" > <ItemGroup> <ExtensionsExcluded Include="cs;vb" /> </ItemGroup> <CreateItem Include="./AFolder/**/*" Exclude="@(ExtensionsExcluded->''./AFolder/**/*.%(identity)'')"> <Output TaskParameter="Include" ItemName="TheFiles"/> </CreateItem> <Message Text="TheFiles: @(TheFiles)" /> </Target>