2

我有一个类库,它有几个依赖的文件,并且必须将这些文件打包以便与任何依赖该库的项目一起部署。现在这意味着除了将库添加为 MSBuild PrjectReference 之外,我还必须自定义每个依赖项目以确保它们复制文件。添加更多文件时,必须更新所有项目。

我一直在通过 Microsoft.Common.targets 寻找一种将这些文件包含在库自己的项目文件的输出中的方法,因此任何对库有 ProjectReference 的项目都会在构建时自动获取这些文件。我还没有任何工作,但如果这可能的话,我会更普遍地好奇。看起来应该是这样,_CopyFilesMarkedCopyLocal 目标甚至尊重其他未使用的 %(DestinationSubDirectory) 元数据项,该元数据项将允许自定义放置这些文件,这将是完美的。

我相信我缺少的是,对于构建依赖于项目 B 的项目 A,将项目 B 的项目输出添加到项目 A 的构建项目中的部分。

编辑:Leo 的评论,我没有注意到标有 CopyToOutputDirectory 的文件也被复制到依赖的项目输出目录,因为我们使用的 ItemGroups 的名称不是 Content、EmbeddedResource、None 等。深入挖掘,使用这些的目标是 GetCopyToOutputDirectoryItems 和它似乎递归调用 MSBuild 任务来确定项目输出,所以我应该能够定义一些可以导入到我们的项目中的自定义目标,在 GetCopyToOutputDirectoryItems 目标中添加我们的自定义 ItemGroups,这样我们就不必使用内容/无等

但是,执行复制的目标是 _CopyOutOfDateSourceItemsToOutputDirectoryAlways,不幸的是它不尊重 %(DestinationSubDirectory),因此所有这些文件都直接复制到 $(OutDir)。

我的新目标是查看是否有某种方法可以将自定义文件添加到依赖项目的 ReferenceCopyLocalPaths ItemGroup 中,以便它们被 _CopyFilesMarkedCopyLocal 目标复制,该目标确实利用了 %(DestinationSubDirectory)。

4

1 回答 1

1

在 _CopyOutOfDateSourceItemsToOutputDirectoryAlways 目标中为 ItemGroups 添加自定义构建操作

上面的标题应该更接近 bwerks 的目标。作为测试,我们可以知道 ItemGroups 的自定义构建操作不会复制到输出目录,因此我们需要将自定义构建操作复制到目标_CopyOutOfDateSourceItemsToOutputDirectoryAlways

为此,请打开Microsoft.Common.CurrentVersion.targetsMSBuild 15.0 文件夹中的文件C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets(确保您有足够的权限并备份它),找到目标_CopyOutOfDateSourceItemsToOutputDirectoryAlways

<Copy
    SourceFiles = "@(_SourceItemsToCopyToOutputDirectoryAlways)"
    DestinationFiles = "@(_SourceItemsToCopyToOutputDirectoryAlways->'$(OutDir)%(TargetPath)')"
    ...
        >

  <Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>

</Copy>

然后我们可以知道复制的源文件是@(_SourceItemsToCopyToOutputDirectoryAlways),在目标中搜索_SourceItemsToCopyToOutputDirectoryAlways这个,你会发现:

<ItemGroup>
  <_SourceItemsToCopyToOutputDirectoryAlways KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(ContentWithTargetPath->'%(FullPath)')" Condition="'%(ContentWithTargetPath.CopyToOutputDirectory)'=='Always'"/>
  <_SourceItemsToCopyToOutputDirectory       KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(ContentWithTargetPath->'%(FullPath)')" Condition="'%(ContentWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"/>
</ItemGroup>

可以知道源文件是@(ContentWithTargetPath),在目标中不断搜索ContentWithTargetPath,最后得到如下:

<AssignTargetPath Files="@(Content)" RootFolder="$(MSBuildProjectDirectory)">
  <Output TaskParameter="AssignedFiles" ItemName="ContentWithTargetPath" />
</AssignTargetPath>

因此,我们可以知道目标是如何将默认构建操作文件复制到输出目录的。

现在,转到我们的自定义构建操作,我们只需将我们的自定义构建操作添加到ItemName="ContentWithTargetPath",因此在文件中添加以下内容Microsoft.Common.CurrentVersion.targets

<AssignTargetPath Files="@(MyBuildAction)" RootFolder="$(MSBuildProjectDirectory)">
  <Output TaskParameter="AssignedFiles" ItemName="ContentWithTargetPath" />
</AssignTargetPath>

保存。

对于项目文件中的文件.csproj

  <ItemGroup>
    <MyBuildAction Include="TextFile1.txt">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </MyBuildAction>
  </ItemGroup>

在此处输入图像描述

希望这可以帮助。

于 2018-08-28T04:15:10.587 回答