How do I get a T4 template to generate its output on every build? As it is now, it only regenerates it when I make a change to the template.
I have found other ques
I agree with GarethJ - in VS2010 it is much easier to regenerate tt templates on each build. Oleg Sych's blog describes how to do it. In short:
</Project>
That's it. Open your project. On each build all *.tt templates will be reprocessed
<!-- This line could already present in file. If it is so just skip it -->
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- process *.tt templates on each build -->
<PropertyGroup>
<TransformOnBuild>true</TransformOnBuild>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TextTemplating\v10.0\Microsoft.TextTemplating.targets" />
Here is how I tacked it. Link. Basically building on top of a great blog( blogs.clariusconsulting.net/kzu/how-to-transform-t4-templates-on-build-without-installing-a-visual-studio-sdk/ can't post more that 2 links :( ) I came up with This .targets file for use with visual studio proj files.
It's useful when you are using other dll-s inside of your .tt and you want the result to change as the dll-s are changing.
How it works:
Remove the assembly references from .tt
Inside the proj file use this code to set up transform on build:
<PropertyGroup>
<!-- Initial default value -->
<_TransformExe>$(CommonProgramFiles)\Microsoft Shared\TextTemplating\10.0\TextTransform.exe</_TransformExe>
<!-- If explicit VS version, override default -->
<_TransformExe Condition="'$(VisualStudioVersion)' != ''">$(CommonProgramFiles)\Microsoft Shared\TextTemplating\$(VisualStudioVersion)\TextTransform.exe</_TransformExe>
<!-- Cascading probing if file not found -->
<_TransformExe Condition="!Exists('$(_TransformExe)')">$(CommonProgramFiles)\Microsoft Shared\TextTemplating\10.0\TextTransform.exe</_TransformExe>
<_TransformExe Condition="!Exists('$(_TransformExe)')">$(CommonProgramFiles)\Microsoft Shared\TextTemplating\11.0\TextTransform.exe</_TransformExe>
<_TransformExe Condition="!Exists('$(_TransformExe)')">$(CommonProgramFiles)\Microsoft Shared\TextTemplating\12.0\TextTransform.exe</_TransformExe>
<!-- Future proof 'til VS2013+2 -->
<_TransformExe Condition="!Exists('$(_TransformExe)')">$(CommonProgramFiles)\Microsoft Shared\TextTemplating\13.0\TextTransform.exe</_TransformExe>
<_TransformExe Condition="!Exists('$(_TransformExe)')">$(CommonProgramFiles)\Microsoft Shared\TextTemplating\14.0\TextTransform.exe</_TransformExe>
<_TransformExe Condition="!Exists('$(_TransformExe)')">$(CommonProgramFiles)\Microsoft Shared\TextTemplating\15.0\TextTransform.exe</_TransformExe>
<IncludeForTransform>@(DllsToInclude, '&quot; -r &quot;')</IncludeForTransform>
</PropertyGroup>
First part Locates TextTransform.exe
$(IncludeForTransform)
will be equal to c:\path\to\dll\foo.dll' -r c:\path\to\dll\bar.dll
because that's the way to add references for the TextTransform on the command line
<Target Name="TransformOnBuild" BeforeTargets="BeforeBuild">
<!--<Message Text="$(IncludeForTransform)" />-->
<Error Text="Failed to find TextTransform.exe tool at '$(_TransformExe)." Condition="!Exists('$(_TransformExe)')" />
<ItemGroup>
<_TextTransform Include="$(ProjectDir)**\*.tt" />
</ItemGroup>
<!-- Perform task batching for each file -->
<Exec Command=""$(_TransformExe)" "@(_TextTransform)" -r "$(IncludeForTransform)"" Condition="'%(Identity)' != ''" />
</Target>
<_TextTransform Include="$(ProjectDir)**\*.tt" />
this creates a list of all tt files inside the project and subdirectories
<Exec Command="...
produces a line for each of the found .tt files that looks like "C:\path\to\Transform.exe" "c:\path\to\my\proj\TransformFile.tt" -r"c:\path\to\foo.dll" -r "c:\path\to\bar.dll"
The only thing left to do is add the paths to the dlls inside of:
<ItemGroup>
<DllsToInclude Include="$(ProjectDir)path\to\foo.dll">
<InProject>False</InProject>
</DllsToInclude>
<DllsToInclude Include="$(ProjectDir)path\to\bar.dll">
<InProject>False</InProject>
</DllsToInclude>
</ItemGroup>
Here <InProject>False</InProject>
hides these items from the Solution View
So now you should be able to generate your code on build and on change of dll-s.
You can remove the custom tool (from properties inside of Visual Studio) so the VS does not try to transform and fail miserably every time. Because we removed the assembly references in step 2
You just install NuGet Package: Clarius.TransformOnBuild
Then, every time you click Rebuild project (or Solution), your .tt files will run
In visual studio 2013, right click the T4 template and set the transform on build property to true.
There is a great NuGet package that does just this:
PM> Install-Package Clarius.TransformOnBuild
Details about the package can be found here
The pre-build can be reduced to a single line:
forfiles /p "$(ProjectDir)." /m "*.tt" /s /c "cmd /c echo Transforming @path && \"%CommonProgramFiles(x86)%\Microsoft Shared\TextTemplating\1.2\TextTransform.exe\" @file"
This transforms all .tt
files in the project and lists them to the build output.
If you don't want the build output then you have to work around some "interesting behaviour":
forfiles /p "$(ProjectDir)." /m "*.tt" /s /c "cmd /c @\"%CommonProgramFiles(x86)%\Microsoft Shared\TextTemplating\1.2\TextTransform.exe\" @file"
Of course, you can pull this out into a batch file to which you pass the project directory path if you wish.
NB The path may require some tweaking. The path above is where VS 2008 installed it on my machine; but you might find that the version number between TextTemplating
and TextTransform.exe
is different.