Get Visual Studio to run a T4 Template on every build

Viewed 71145
22 Answers

Thanks to GitHub.com/Mono/T4, at the moment you can do it for both .NET Core and Visual Studio builds by adding this to your .csproj file:

  <ItemGroup>
    <DotNetCliToolReference Include="dotnet-t4-project-tool" Version="2.0.5" />
    <TextTemplate Include="**\*.tt" />
  </ItemGroup>

  <Target Name="TextTemplateTransform" BeforeTargets="BeforeBuild">
    <ItemGroup>
      <Compile Remove="**\*.cs" />
    </ItemGroup>
    <Exec WorkingDirectory="$(ProjectDir)" Command="dotnet t4 %(TextTemplate.Identity)" />
    <ItemGroup>
      <Compile Include="**\*.cs" />
    </ItemGroup>
  </Target>

If you transform your templates to different programming languages you should add something like <Compile Remove="**\*.vb" /> and <Compile Include="**\*.vb" /> in order to get these files compiled even if you don't have generated files yet.

Remove and Include trick only needed for first time generation, or you can make the XML-shorter like this:

  <ItemGroup>
    <DotNetCliToolReference Include="dotnet-t4-project-tool" Version="2.0.5" />
    <TextTemplate Include="**\*.tt" />
  </ItemGroup>

  <Target Name="TextTemplateTransform" BeforeTargets="BeforeBuild">
    <Exec WorkingDirectory="$(ProjectDir)" Command="dotnet t4 %(TextTemplate.Identity)" />
  </Target>

and just run build twice (for the first time). If you already have generated files committed to the repository there will be no problems on rebuilds with both examples.

In the Visual Studio you might want to see something like this:

enter image description here

instead of this:

enter image description here

So add something like this to your project file:

  <ItemGroup>
    <Compile Update="UInt16Class.cs">
      <DependentUpon>UInt16Class.tt</DependentUpon>
    </Compile>
    <Compile Update="UInt32Class.cs">
      <DependentUpon>UInt32Class.tt</DependentUpon>
    </Compile>
    <Compile Update="UInt64Class.cs">
      <DependentUpon>UInt64Class.tt</DependentUpon>
    </Compile>
    <Compile Update="UInt8Class.cs">
      <DependentUpon>UInt8Class.tt</DependentUpon>
    </Compile>
  </ItemGroup>

Complete example here: GitHub.com/Konard/T4GenericsExample (includes generation of multiple files from single template).

In Visual Studio 2017 (probably next versions too), you should add this in Pre-build event:

"$(DevEnvDir)TextTransform.exe" -out "$(ProjectDir)YourTemplate.cs" "$(ProjectDir)YourTemplate.tt"

p.s. Change path to your template if it's located not in root project directory.

T4Executer does this for VS2019. You can specify templates to ignore on build, and there is a execute after build option.

You just install NuGet Package: Clarius.TransformOnBuild

Then, every time you click Rebuild project (or Solution), your .tt files will run

Here's a pre-build event using only Microsoft Tooling and standard paths. It's tested in vs2019/netcore3.1.

Replace "AppDbContext.tt" with your project-relative file path:

"$(MSBuildBinPath)\msbuild" "$(SolutionPath)" /t:$(ProjectName):Transform /p:TransformFile="AppDbContext.tt" /p:CustomAfterMicrosoftCommonTargets="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TextTemplating\Microsoft.TextTemplating.targets"

Microsoft also has a guide to make macros like "$(SolutionDirectory)" available in the template by using T4ParameterValues in your project file.

Related