22

ProjectA の出力ディレクトリ ($(TargetDir)) にいくつかの出力ファイルを生成するカスタム msbuild タスクがあります。現在のコードは次のようなものです。

<MyCustomTask ...>
   <Output TaskParameter="OutputFiles" ItemName="FileWrites"/>
</MyCustomTask>

ProjectB はProjectAを参照していますが、問題は、ProjectB をビルドするときに、MyCustomTask によって生成されたファイルが ProjectB の出力ディレクトリにコピーされないことです。

MSBuild でプロジェクトの依存関係の一部としてコピーされる動的に生成された追加ファイルを取得するにはどうすればよいですか?

4

5 に答える 5

15

最終的に、プロジェクト Bを変更せずに自動的にコピーを実行することができました。IIya は解決にはほど遠いのですが、MyCustomTask でプロジェクト Aから生成するファイルのリストが動的であるため、静的に生成することはできないのが実情です。をさらに掘り下げた後Microsoft.Common.targets、 ProjectB はtarget を呼び出すことによってプロジェクト AGetCopyToOutputDirectoryItemsからの出力のリストを取得することがわかりました。このターゲットは、AssignTargetPathsそれ自体がターゲット リスト プロパティに依存している依存先AssignTargetPathsDependsOnです。

したがって、コンテンツを動的に生成し、このコンテンツを標準のプロジェクトの依存関係を通じて自動的にコピーするには、プロジェクト Aを 2 つの異なる場所でフックする必要があります。

  • GetCopyToOutputDirectoryItemsを介してプロジェクト A のプロジェクト BAssignTargetPathsDependsOnによって間接的に呼び出されるためです。また、呼び出されたときにプロジェクト Aによって間接的に呼び出されます。ここでは、( Project Aによって) 生成されるか、 Project Bによって消費されるファイルのリストを出力しています。AssignTargetPathsDependsOn は、ファイルのリストの出力のみを担当するカスタム タスクを呼び出します (ただし、ファイルのリストは生成しません)。このファイルのリストは、.PrepareResourceMyCustomTaskListCopyOutputDirectory
  • プロジェクト Aで実際にBuildDependsOnコンテンツを生成するため。これは、コンテンツを生成する呼び出しを行います。MyCustomTask

これはすべて、ProjectA で次のようにセットアップされました。

<!-- In Project A -->

<!-- Task to generate the files -->
<UsingTask TaskName="MyCustomTask" AssemblyFile="$(PathToMyCustomTaskAssembly)"/>

<!-- Task to output the list of generated of files - It doesn't generate the file -->
<UsingTask TaskName="MyCustomTaskList" AssemblyFile="$(PathToMyCustomTaskAssembly)"/>

<!-- 1st PART : When Project A is built, It will generate effectively the files -->
<PropertyGroup>
  <BuildDependsOn>
    MyCustomTaskTarget;
    $(BuildDependsOn);
  </BuildDependsOn>
</PropertyGroup>

<Target Name="MyCustomTaskTarget">
  <!-- Call MyCustomTask generate the files files that will be generated by MyCustomTask -->
  <MyCustomTask
      ProjectDirectory="$(ProjectDir)"
      IntermediateDirectory="$(IntermediateOutputPath)"
      Files="@(MyCustomFiles)"
      RootNamespace="$(RootNamespace)"
      >
  </MyCustomTask>
</Target>

<!-- 2nd PART : When Project B is built, It will call GetCopyToOutputDirectoryItems on ProjectA so we need to generate this list when it is called  -->
<!-- For this we need to override AssignTargetPathsDependsOn in order to generate the list of files -->
<!-- as GetCopyToOutputDirectoryItems  ultimately depends on AssignTargetPathsDependsOn -->
<!-- Content need to be generated before AssignTargets, because AssignTargets will prepare all files to be copied later by GetCopyToOutputDirectoryItems -->
<!-- This part is also called from ProjectA when target 'PrepareResources' is called -->
<PropertyGroup>
  <AssignTargetPathsDependsOn>
    $(AssignTargetPathsDependsOn);
    MyCustomTaskListTarget;
  </AssignTargetPathsDependsOn>
</PropertyGroup>

<Target Name="MyCustomTaskListTarget">

  <!-- Call MyCustomTaskList generating the list of files that will be generated by MyCustomTask -->
  <MyCustomTaskList
      ProjectDirectory="$(ProjectDir)"
      IntermediateDirectory="$(IntermediateOutputPath)"
      Files="@(MyCustomFiles)"
      RootNamespace="$(RootNamespace)"
      >
      <Output TaskParameter="ContentFiles" ItemName="MyCustomContent"/>
  </MyCustomTaskList>

  <ItemGroup>
    <!--Generate the lsit of content generated by MyCustomTask -->
    <Content Include="@(MyCustomContent)" KeepMetadata="Link;CopyToOutputDirectory"/>
  </ItemGroup>
</Target>

このメソッドは、Common.Targets を使用しているあらゆる種類の C# プロジェクトで機能します (したがって、純粋なデスクトップ、WinRT XAML アプリ、または Windows Phone 8 プロジェクトで機能します)。

于 2013-01-25T13:45:28.867 に答える
4

ProjectA の .csproj に手動で含めるか (VS にはワイルドカードを絶対パスに解決して .csproj を上書きするという悪い習慣があることに注意してください)、カスタム タスク自体によって動的に挿入します。また、VS はアイテムグループを開いたときにキャッシュするため、ファイルが存在していても削除された場合、ファイルがコピーされなかったり、ビルドに失敗したりする可能性があります。その場合、アイテムグループを再評価するには、プロジェクトをリロードするか、VS を再起動する必要があります。MSBuild、TFS などは常に動作するはずです。

<ItemGroup>
  <Content Include="$(TargetDir)\*.txt">
    <Link>%(Filename)%(Extension)</Link>
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </Content>
</ItemGroup>
于 2013-01-21T00:45:22.517 に答える
1

既に MSBuild を使用してこのビルドを自分で行っている場合は、コピー タスクを追加してファイルを自分の周りにプッシュできますか?

于 2013-01-14T16:30:10.497 に答える
0

私が理解しているように、ProjectB.msbuild に次の行のみを記述して、追加のステップを追加したいと考えています。

<Import Project="ProjectA.msbuild" />

それを達成するには、ProjectA のように書くことができます:

<PropertyGroup>
  <BuildDependsOn>$(BuildDependsOn);MyCustomTask</BuildDependsOn>
</PropertyGroup>

これにより、ビルド タスクの依存関係のリストにタスクが追加されます。

詳細については、この質問を参照してください: StyleCop MS Build magic? StyleCop ターゲットを呼び出しているのは誰ですか?

于 2013-01-25T07:10:58.560 に答える