2009-08-18 10 views
16

Mam następujący fragment kodu MSBuild:Jak wywołać ten sam cel msbuild dwa razy z różnymi parametrami od wewnątrz msbuild samego pliku projektu

<PropertyGroup> 
    <DirA>C:\DirA\</DirA> 
    <DirB>C:\DirB\</DirB> 
    </PropertyGroup> 

    <Target Name="CopyToDirA" 
      Condition="Exists('$(DirA)') AND '@(FilesToCopy)' != ''" 
      Inputs="@(FilesToCopy)" 
      Outputs="@(FilesToCopy -> '$(DirA)%(Filename)%(Extension)')"> 
    <Copy SourceFiles="@(FilesToCopy)" DestinationFolder="$(DirA)" /> 
    </Target> 

    <Target Name="CopyToDirB" 
      Condition="Exists('$(DirB)') AND '@(FilesToCopy)' != ''" 
      Inputs="@(FilesToCopy)" 
      Outputs="@(FilesToCopy -> '$(DirB)%(Filename)%(Extension)')"> 
    <Copy SourceFiles="@(FilesToCopy)" DestinationFolder="$(DirB)" /> 
    </Target> 

    <Target Name="CopyFiles" DependsOnTargets="CopyToDirA;CopyToDirB"/> 

Więc powołując się celem CopyFiles kopie odpowiednich dokumentów do $(DirA) i $(DirB), pod warunkiem, że nie są już dostępne i aktualne.

Ale cele CopyToDirA i CopyToDirB wyglądają identycznie, z wyjątkiem jednej kopii na $(DirA), a drugą - na $(DirB). Czy możliwe jest zunifikowanie ich do jednego celu po raz pierwszy wywołanego przez $(DirA), a następnie z $(DirB)?

Dzięki.

Odpowiedz

14

Powinieneś być w stanie wygenerować ItemGroup zawierający Dirs, a następnie% na tym.

<ItemGroup> 
    <Dirs Include="C:\DirA\;C:\DirB\"> 
</ItemGroup> 
<Target Name="CopyFiles" 
    Condition="Exists('%(Dirs)') AND '@(FilesToCopy)' != ''" 
    Inputs="@(FilesToCopy)" 
    Outputs="@(FilesToCopy -> '%(Dirs)%(Filename)%(Extension)')"> 
    <Copy SourceFiles="@(FilesToCopy)" DestinationFolder="%(Dirs)" /> 
</Target> 

Albo można zrobić 2 wyraźnych połączeń:

<Target Name="CopyFiles"> 
    <MsBuild Projects="$(MSBuildProjectFullPath)" Targets="CopyASetOfFiles" Properties="[email protected](FilesToCopy);DestDir=$(DirA)" /> 
    <MsBuild Projects="$(MSBuildProjectFullPath)" Targets="CopyASetOfFiles" Properties="[email protected](FilesToCopy);DestDir=$(DirB)" /> 
</Target> 

<Target Name="CopyASetOfFiles" 
    Condition="Exists('$(DestDir)') AND '@(FilesToCopy)' != ''" 
    Inputs="@(FilesToCopy)" 
    Outputs="@(FilesToCopy -> '$(DestDir)%(Filename)%(Extension)')"> 
    <Copy SourceFiles="@(FilesToCopy)" DestinationFolder="$(DestDir)" /> 
</Target> 

nie testowałem zarówno składni, ale jestem stosunkowo bardziej pewni drugiego.

(odpowiedź, jeśli istnieje, jest w mojej książce Sayed Hashimi na moim biurku - trzeba będzie poczekać, aż pierwsze:

  1. Pobierz książkę
  2. znudzę
  3. Sayed znajdzie ten post i wymyśla genialny badanej odpowiedzi)
+0

Hi Ruben. Czy mógłbyś rozwinąć ... w swojej odpowiedzi? Nie jestem zaznajomiony z sparametryzowanymi celami, aby zrozumieć, co masz na myśli. Dzięki. – mark

+0

@mark: done.Powód, dla którego nie robiłem tego wcześniej, jest dwojaki 1. Nie miałem miłego edytora do ręki. 2. nie wiem na temat składni pierwszej próbki. Mam nadzieję że to pomoże. Bardzo polecam książkę Inside MSBuild –

+0

@ruben: LOL @ # 3 –

4

Tak, co chcesz, jest nazywany dozowania w MSBuild. Parametry zdefiniowane w wynikach spowodują, że to zadanie zostanie wykonane dla każdego elementu w grupie pozycji produktu Dirs.

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

<ItemGroup> 
    <Dirs Include="C:\DirA" /> 
    <Dirs Include="C:\DirB" /> 
</ItemGroup> 

<Target Name="CopyFiles" 
    Inputs="@(FilesToCopy);@(Dirs)" 
    Outputs="@(FilesToCopy -> '%(Dirs.Identity)%(Filename)%(Extension)');%(Dirs.Identity)" > 
    <Message Text="%(Dirs.Identity)" /> 
</Target> 

</Project> 

Wyjścia:

Build started 8/19/2009 10:11:57 PM. 
Project "D:\temp\test.proj" on node 0 (default targets). 
    C:\DirA 
CopyFiles: 
    C:\DirB 
Done Building Project "D:\temp\test.proj" (default targets). 

Zmiany zadanie Wiadomość Kopiowanie zadanie z następującego warunku i gotowe:

Condition="Exists('%(Dirs.Identity)') AND '@(FilesToCopy)' != ''"