2010-10-08 6 views
6

Problem: tablica ItemGroups nie jest poprawnie budowana na podstawie wartości przekazanej w atrybucie exclude.MSBuild ItemGroup Dołącz/wyklucz numer wzoru

Jeśli uruchomisz ten plik, utworzy on plik przykładowy, a następnie spróbuje utworzyć tablicę o nazwie TheFiles na podstawie atrybutów Include/Exclude, problem występuje wtedy, gdy wykluczenie jest czymś innym niż na stałe lub bardzo prostą właściwością, która powoduje błąd.

Cel DynamicExcludeList na nieprawidłowo wybiera te pliki:
\ AKatalog \ test.cs; \ AKatalog \ test.txt

Cel HardcodedExcludeList na poprawnie wybiera te pliki..
\ AKatalog \ Test.txt.

Każda pomoc doceniona, doprowadza mnie do szału.

(uwaga jej 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> 

Jest to wyjście, należy zwrócić uwagę na różnice między 'TheFiles' i '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 

edytuje

I ve zaktualizował powyższy skrypt, aby użyć CreateItem, jednak nadal występuje problem z listą elementów t o exclude zawiera więcej niż 1 ścieżkę (tj. wartość CommonFileExclusion uległa zmianie):

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

Odpowiedz

14

OK, próbowałem trochę i myślę, że problem wynika z faktu, że używasz właściwości, która reprezentuje wartość SCALAR dla wielu wartości. Poleciłbym grupowanie i przekształcanie (zobacz http://scottlaw.knot.org/blog/?p=402 i http://msdn.microsoft.com/en-us/library/ms171476.aspx). Na przykład działa następujący kod:

<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

Dzięki za naprawę, jest to jedna z tych rzeczy, które są nieprzyjemne w MSBuild (IMO), ponieważ stają się bardziej skomplikowane, więcej wykluczeń, które chcesz dodać (np. Niektóre pliki w niektórych katalogach, ale nie w innych), może szukać innego rozwiązania . – Keith

2

W docelową DynamicExcludeList użycie CreateItem zadanie zamiast ItemGroup do dynamicznego generowania swój przedmiot:

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

Teoretycznie ItemGroup i CreateItem są równoważne ale widziałem obudowa (sytuacja dynamiczna) taka jak ta, gdy trzeba użyć CreateItem.

+1

W rzeczywistości właściwości i itemgroup są oceniane podczas analizowania skryptu, zanim każdy cel zostanie uruchomiony. Dlatego Twoje grupy produktów nie są wypełnione tym, co myślałeś, ale tym, co było przed wykonaniem twojego skryptu msbuild. Więcej informacji na ten temat można znaleźć tutaj: http://blogs.msdn.com/b/msbuild/archive/2006/01/03/508629.aspx i http://www.sedodream.com/PermaLink,guid,dd6cb1db- c0e4-47f7-ad84-6e59ff6b03d0.aspx. Dobrym sposobem na uniknięcie tego problemu jest użycie ItemGroup poza celami (dla przedmiotów statycznych) i createitem wewnątrz (dla elementów dynamicznych) –

+0

Dzięki za wyjaśnienie. Ale jeśli spojrzysz na dokumentację na temat CreateItem (http://msdn.microsoft.com/en-us/library/s2y3e43x.aspx), zobaczysz, że to zadanie jest przestarzałe, więc możesz pomyśleć, że ItemGroup wewnątrz celu zostanie oceniony dynamicznie jak w przypadku CreateItem. –

+0

Dzięki za opinię, nadal mam problem (post w sekundę), zgodnie z tym: http://stackoverflow.com/questions/937681/createitem-vs-itemgroup, CreateItem jest przestarzałe w 3.5 – Keith

Powiązane problemy