MSBuild 将动态生成的文件复制为项目依赖项的一部分 [英] MSBuild to copy dynamically generated files as part of project dependency

查看:14
本文介绍了MSBuild 将动态生成的文件复制为项目依赖项的一部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个自定义 msbuild 任务,它生成一些输出文件到 ProjectA 的输出目录 ($(TargetDir)).当前代码是这样的:

I have a custom msbuild task that is generating some output files to the output directory ($(TargetDir)) of a ProjectA. Current code is something like this:

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

A ProjectB 正在引用 ProjectA 但问题是在构建 ProjectB 时,MyCustomTask 生成的文件没有复制到 ProjectB 的输出目录中.

A ProjectB is referencing ProjectA but the problem is that when building ProjectB, generated files by MyCustomTask are not copied to the output directory of the ProjectB.

我们如何获取动态生成的附加文件以作为 MSBuild 项目依赖项的一部分进行复制?

How can we get dynamically generated additional files to be copied as part of project dependency with MSBuild?

推荐答案

我终于成功地自动执行了 Project B 的复制,而无需修改它.IIya 离解决方案不远了,但事实是我无法静态生成,因为要从带有 MyCustomTask 的 Project A 生成的文件列表是动态的.在深入研究 Microsoft.Common.targets 后,我发现 ProjectB 将通过调用目标 GetCopyToOutputDirectoryItemsProject A 获取输出列表.此目标依赖于 AssignTargetPaths,而 AssignTargetPaths 本身又依赖于目标列表属性 AssignTargetPathsDependsOn.

I have finally managed to perform automatically the copy from Project B without having to modify it. IIya was not so far from the solution, but the fact is that I cannot generate statically as the list of files to generate from Project A with MyCustomTask is dynamic. After digging more into Microsoft.Common.targets, I have found that ProjectB will get the list of output from Project A by calling the target GetCopyToOutputDirectoryItems. This target is dependent from AssignTargetPaths which itself is dependent on the target list property AssignTargetPathsDependsOn.

因此,为了动态生成内容并通过标准项目依赖项自动复制这些内容,我们需要在两个不同的位置挂钩项目 A:

So in order to generate dynamically content and to get this content being copied automatically through standard project dependency, we need to hook Project A at two different places:

  • AssignTargetPathsDependsOn 中,因为 Project BProject A 上通过 GetCopyToOutputDirectoryItems 间接调用它.当 PrepareResource 被调用时,它也会被 Project A 间接调用.在这里,我们只是输出将生成(由项目 A)或由 项目 B 使用的文件列表.AssignTargetPathsDependsOn 将调用一个自定义任务 MyCustomTaskList,它只负责输出文件列表(但不生成它们),该文件列表将使用 CopyOutputDirectory.
  • BuildDependsOn 中,以便在Project A 中实际生成内容.这将调用将生成内容的 MyCustomTask.
  • In AssignTargetPathsDependsOn as it is called indirectly by Project B on Project A through GetCopyToOutputDirectoryItems. And also it is indirectly called by Project A when PrepareResource is called. Here, we are just outputing the list of files that will be generated (by Project A) or consumed by Project B. AssignTargetPathsDependsOn will call a custom task MyCustomTaskList which is only responsible to output the list of files (but not to generate them), this list of files will create dynamic "Content" with CopyOutputDirectory.
  • In BuildDependsOn in order to actually generate the content in Project A. This will call MyCustomTask that will generate the content.

所有这些在 ProjectA 中都是这样设置的:

All of this was setup like this in 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 项目).

This method is working with anykind of C# projects that is using Common.Targets (so It is working with pure Desktop, WinRT XAML App or Windows Phone 8 projects).

这篇关于MSBuild 将动态生成的文件复制为项目依赖项的一部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆