2010-10-08 74 views
6

问题:根据exclude属性中传递的值,ItemGroups数组未正确构建。MSBuild ItemGroup包含/排除模式问题

如果您运行此脚本创建了一些示例文件,然后尝试基于Include/Exclude属性创建一个名为TheFiles的数组,则问题是排除是硬编码以外的任何内容或非常简单的属性时,它会导致错误。

目标DynamicExcludeList的不正确选择这些文件:
\ AFolder \ test.cs中; \ AFolder \ test.txt的

目标HardcodedExcludeList的正确选择这些文件:。
\ AFolder \ test.txt的。

任何帮助非常感谢,这是让我疯了。

(注意其的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> 

这是输出,请注意 'TheFiles' 和 '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之间的差异

I”已经更新了上面的脚本以使用CreateItem,但是当项目列表t仍然存在问题时排除包含多于一个路径(即, CommonFileExclusion的值更改):

<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> 

回答

14

好的,我试了一下,我认为问题来自于你使用一个属性代表多个值的SCALAR值。我会建议配料和改造(见http://scottlaw.knot.org/blog/?p=402http://msdn.microsoft.com/en-us/library/ms171476.aspx)。例如,下面的代码正在工作:

<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> 
+0

感谢您的修复,它只是MSBuild(IMO)中令人讨厌的那些东西之一,因为它变得越复杂,您要添加的排除越多(例如某些目录中的某些文件,而不是其他等),可能会寻找另一种解决方案。 – Keith 2010-10-11 07:54:42

2

在目标DynamicExcludeList使用CreateItem任务,而不是ItemGroup动态生成您的项目:

<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> 

理论上ItemGroupCreateItem是等价的,但我已经看到了像这样的情况(动态情况)CreateItem必须使用。

+1

事实上,在每个目标运行之前,脚本解析时都会评估属性和项目组。这就是为什么你的项目组没有填充你的想法,而是你的msbuild脚本执行之前的内容。您可以在这里阅读更多信息:http://blogs.msdn.com/b/msbuild/archive/2006/01/03/508629.aspx和http://www.sedodream.com/PermaLink,guid,dd6cb1db- c0e4-47f7-ad84-6e59ff6b03d0.aspx。避免此问题的一个好方法是在目标外部使用ItemGroup(用于静态项目)和createitem(用于动态项目) – 2010-10-08 14:17:48

+0

感谢您的解释。但是,如果您查看CreateItem(http://msdn.microsoft.com/en-us/library/s2y3e43x.aspx)上的文档,您会看到此任务已被弃用,因此您可以认为目标中的ItemGroup将被评估动态地像CreateItem一样。 – 2010-10-08 14:20:58

+0

感谢您的反馈,我仍然有一个问题(在一秒内发布),根据这个:http://stackoverflow.com/questions/937681/createitem-vs-itemgroup,CreateItem在3中已经过时。5 – Keith 2010-10-08 14:23:18