仅当文件被修改时 MSBuild 上的 TextTransform? (或这样做的替代途径)

TextTransform on MSBuild only when file modified? (or an alternate route of doing this)

我有一个将 TextTransform 与 MSBuild 集成的项目,但我现在遇到的问题是文件太多,这会减慢开发时间。

我的流程是,我有一个POCO.cs;我使用 Roslyn 解析 .cs 文件以收集一些元数据;将元数据传递给 .tt 文件,然后生成 [Implementation].cs

这是与我的问题相关的 .csproj 文件的一部分:

<PropertyGroup>
  <_CommonProgramFiles>$([System.Environment]::GetEnvironmentVariable('CommonProgramFiles(x86)'))</_CommonProgramFiles>
  <_CommonProgramFiles Condition=" '$(_CommonProgramFiles)' == '' ">$(CommonProgramFiles)</_CommonProgramFiles>
  <TextTransformPath Condition="'$(TextTransformPath)' == ''">$(_CommonProgramFiles)\Microsoft Shared\TextTemplating$(VisualStudioVersion)\TextTransform.exe</TextTransformPath>
  <!-- Initial default value -->
  <_TransformExe>$(TextTransformPath)</_TransformExe>
  <_RoslynDllPath>$(ProjectDir)Lib\RoslynWrapper.dll</_RoslynDllPath>
  <!-- Cascading probing if file not found -->
  <_TransformExe Condition="!Exists('$(_TransformExe)')">$(_CommonProgramFiles)\Microsoft Shared\TextTemplating.0\TextTransform.exe"</_TransformExe>
  <_TransformExe Condition="!Exists('$(_TransformExe)')">$(_CommonProgramFiles)\Microsoft Shared\TextTemplating.0\TextTransform.exe"</_TransformExe>
  <_TransformExe Condition="!Exists('$(_TransformExe)')">$(_CommonProgramFiles)\Microsoft Shared\TextTemplating.0\TextTransform.exe"</_TransformExe>
  <!-- Future proof 'til VS2013+2 -->
  <_TransformExe Condition="!Exists('$(_TransformExe)')">$(_CommonProgramFiles)\Microsoft Shared\TextTemplating.0\TextTransform.exe"</_TransformExe>
  <_TransformExe Condition="!Exists('$(_TransformExe)')">$(_CommonProgramFiles)\Microsoft Shared\TextTemplating.0\TextTransform.exe"</_TransformExe>
</PropertyGroup>

<ItemGroup>
  <Compile Include="SomePoco.cs" />
  <Compile Include="Properties\AssemblyInfo.cs" />
  <Compile Include="SomePocoMetadata.cs">
    <AutoGen>True</AutoGen>
    <DesignTime>True</DesignTime>
    <DependentUpon>SomePocoMetadata.tt</DependentUpon>
  </Compile>
</ItemGroup>
<ItemGroup>
  <None Include="SomePocoMetadata.tt">
    <Generator>TextTemplatingFileGenerator</Generator>
    <LastGenOutput>SomePocoMetadata.cs</LastGenOutput>
  </None>
</ItemGroup>

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="TransformOnBuild" AfterTargets="BeforeBuild">
  <Error Text="Failed to find TextTransform.exe tool at '$(_TransformExe)." Condition="!Exists('$(_TransformExe)')" />
  <ItemGroup>
    <_TextTransform Include="@(None)" Condition="'%(None.Generator)' == 'TextTemplatingFileGenerator'" />
  </ItemGroup>
  <!-- Perform task batching for each file -->
  <Exec Command="&quot;$(_TransformExe)&quot; &quot;%(_TextTransform.FullPath)&quot; -r &quot;$(_RoslynDllPath)&quot;" Condition="'%(_TextTransform.Identity)' != ''" />
</Target>

有了上面的内容,.tt 文件总是在转换,编译 DLL 需要几分钟时间。有没有一种方法可以在 MSBuild 中执行此操作,以便仅在 SomePoco.cs 文件被修改时进行转换?

我是否应该研究另一种方法来实现我想要的目标?

确保为目标指定 InputsOutputs 属性。

在您的特定情况下,您似乎获得了目标内输入之一的名称,因此您不能在封闭的目标的 Input 属性中使用它。解决方法是将 _TextTransform 项目组的定义移到目标之外。

我最后做的是使用 ITaskItem[] 作为输入参数之一,我在那里使用 C# 找出文件的最后修改并确定我是否需要以这种方式生成。