2010-10-08 38 views
6

Vấn đề: mảng ItemGroups không được xây dựng chính xác dựa trên giá trị được chuyển trong thuộc tính loại trừ.MSBuild ItemGroup Bao gồm/Loại trừ vấn đề mẫu

Nếu bạn chạy tập lệnh này, nó sẽ tạo một số tệp mẫu rồi cố gắng tạo một mảng có tên TheFiles dựa trên thuộc tính Bao gồm/Loại trừ, sự cố là khi Loại trừ là bất kỳ điều gì khác ngoài mã cứng hoặc thuộc tính rất đơn giản.

Mục tiêu DynamicExcludeList của sai lựa chọn những tập tin này:
\ AFolder \ Test.cs; \ AFolder \ test.txt

Mục tiêu HardcodedExcludeList của lựa chọn một cách chính xác những tập tin này:..
\ AFolder \ test.txt.

Bất kỳ trợ giúp nào được nhiều người đánh giá cao, điều này khiến tôi cảm thấy phiền muộn.

(lưu ý v4 msbuild của nó)

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

Đây là đầu ra, lưu ý sự khác nhau giữa 'TheFiles' và '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 

CHỈNH SỬA

tôi đã cập nhật kịch bản trên để sử dụng CreateItem, tuy nhiên vẫn còn một vấn đề khi danh sách các mục t o loại trừ chứa nhiều hơn 1 đường dẫn (tức là giá trị của CommonFileExclusion đã thay đổi):

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

Trả lời

14

Ok, tôi đã thử một chút và tôi nghĩ rằng vấn đề xuất phát từ thực tế là bạn sử dụng thuộc tính đại diện cho giá trị SCALAR cho nhiều giá trị. Tôi sẽ khuyên bạn nên định lượng và chuyển đổi (xem http://scottlaw.knot.org/blog/?p=402http://msdn.microsoft.com/en-us/library/ms171476.aspx). Ví dụ: mã sau đang hoạt động:

<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

Cảm ơn bạn đã sửa chữa, nó chỉ là một trong những điều khó chịu trong MSBuild (IMO) vì nó phức tạp hơn, bạn không muốn thêm (ví dụ một số tệp trong một số thư mục, nhưng không phải khác). . – Keith

2

Trong mục tiêu DynamicExcludeList sử dụng CreateItem nhiệm vụ thay vì ItemGroup để tự động tạo ra sản phẩm của bạn:

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

Về mặt lý thuyết ItemGroupCreateItem là tương đương nhưng tôi đã nhìn thấy trường hợp (tình huống động) như thế này khi CreateItem phải được sử dụng.

+1

Thực tế, các thuộc tính và nhóm mặt hàng đều được đánh giá khi tập lệnh của bạn được phân tích cú pháp, trước khi mọi mục tiêu được chạy. Đây là lý do tại sao các nhóm item của bạn không được điền vào với những gì bạn nghĩ nhưng với những gì đã có trước khi kịch bản lệnh msbuild của bạn được thực thi. Bạn có thể đọc thêm về nó tại đây: http://blogs.msdn.com/b/msbuild/archive/2006/01/03/508629.aspx và http://www.sedodream.com/PermaLink,guid,dd6cb1db- c0e4-47f7-ad84-6e59ff6b03d0.aspx. Một cách tốt để tránh vấn đề này là sử dụng ItemGroup bên ngoài các mục tiêu (đối với các mục tĩnh) và createitem bên trong (đối với các mục động) –

+0

Cảm ơn lời giải thích. Nhưng nếu bạn xem tài liệu trên CreateItem (http://msdn.microsoft.com/en-us/library/s2y3e43x.aspx), bạn thấy rằng tác vụ này không được chấp nhận, vì vậy bạn có thể nghĩ rằng ItemGroup bên trong một mục tiêu sẽ được đánh giá động như CreateItem. –

+0

Cảm ơn phản hồi, tôi vẫn gặp sự cố (sau một giây), theo như sau: http://stackoverflow.com/questions/937681/createitem-vs-itemgroup, CreateItem đã lỗi thời trong 3.5 – Keith

Các vấn đề liên quan