MSBuild的动态生成的文件复制为项目依赖的一部分(MSBuild to copy dynamic

2019-07-18 04:37发布

我有一个是产生一些文件输出到项目A的输出目录($(TARGETDIR))的自定义MSBuild任务。 当前的代码是这样的:

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

一个项目B的参考项目A,但问题是,建设项目B时,产生由MyCustomTask文件不会被复制到项目B的输出目录。

我们怎样才能动态生成的额外文件复制与MSBuild项目依赖的一部分吗?

Answer 1:

我终于设法无需修改,它会自动执行从B项目的副本。 IIya不是从溶液中,到目前为止,但事实是,我不能静态地生成的文件列表,以从项目A与MyCustomTask是动态的。 挖掘更多的进入后Microsoft.Common.targets ,我发现项目B将通过调用目标得到项目A输出的列表GetCopyToOutputDirectoryItems 。 这个目标是依赖从AssignTargetPaths这本身就是依赖于目标列表属性AssignTargetPathsDependsOn

因此,为了生成动态内容,并获得该内容被通过标准的项目依赖自动复制,我们需要在两个不同的地方挂钩A计划

  • AssignTargetPathsDependsOn ,因为它是通过GetCopyToOutputDirectoryItems间接项目B项目A调用。 并且还间接地项目A调用时PrepareResource被调用。 在这里,我们只是outputing将生成(按项目A)项目B消耗的文件列表。 AssignTargetPathsDependsOn将调用自定义任务MyCustomTaskList其只负责输出文件的列表(而不是生成它们),文件将创建动态的“内容”与此列表CopyOutputDirectory
  • BuildDependsOn实际上为了生成项目A的内容。 这将调用MyCustomTask将生成的内容。

所有这一切都是建立像这样的项目A:

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

这种方法正在与anykind正在使用Common.Targets C#项目(所以它正在与纯桌面的WinRT XAML应用程序或Windows Phone 8个项目)。



Answer 2:

像这样的东西似乎工作,手动包含到项目A的.csproj的(记住VS有偶尔解决通配符成绝对路径和覆盖.csproj的一个坏习惯),或者通过自定义任务本身的动态注入。 此外,VS开放缓存itemgroups,因此可能无法复制文件或失败,如果他们在那里,但删除的构建。 在这种情况下,项目需要重新加载或VS重新启动重新评估itemgroups。 MSBuild的,TFS等应始终工作。

<ItemGroup>
  <Content Include="$(TargetDir)\*.txt">
    <Link>%(Filename)%(Extension)</Link>
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </Content>
</ItemGroup>


Answer 3:

如果你已经这样做了自己构建与MSBuild的,你可以添加一个复制任务 ,以推动自己周围的文件吗?



Answer 4:

据我了解,你想通过写ProjectB.msbuild仅此行添加额外的步骤:

<Import Project="ProjectA.msbuild" />

为了实现它,你可以写类似的项目A:

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

这增加了你的任务就是建设任务的依赖性列表。

请参阅有关详细信息,这个问题: 了StyleCop MS建立的魔力? 谁是调用了StyleCop目标是什么?



文章来源: MSBuild to copy dynamically generated files as part of project dependency