In the section "Import the text transformation targets", it is said that we should put an Import markup after the Microsoft.CSharp.targets or the Microsoft.VisualBasic.targets.
But when using the new .Net Core csproj format, there are no more such lines.
Can you add a little explanation on what to do in this case?
I tested by importing the targets file at the end of the csproj (.Net Core format) and it does not seem to work.
⚠Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.
This is a bit related to #856 . @bijuvenugopal, do you know how to import the text transformation targets
in a .NET Core project, or can you point us to someone who can help with this? Thanks!
@loicmorvan : My apologies for the delayed response.
We have removed support for text transformation for .NET Core projects from Visual Studio 2017. While removing support for this feature has been a hard decision, we want to ensure that our resources are invested in features that deliver the most customer value. If you are a significant user of the text transformation, you can continue to use Visual Studio 2015 or earlier versions, whilst you decide on an alternative tool for your needs. Thanks for writing to us
@gewarren I don't think this issue is related to #856. #856 is just an IDE issue - if you manually make the changes to the project file then everything works correctly at the MSBuild level.
This issue looks more like it's at the MSBuild level.
@subsri could you clarify what is meant by "removed support for text transformation in Visual Studio 2017" please? The blog post referred to in the current documentation states that the T4 runtime and T4 SDK shipped in VS2017 (_"In VS2017, the T4 SDK is installed with the T4 runtime as part of the Text Template Transformation optional component, which is itself installed by default with many Visual Studio workloads"_). Also, If I click _Add new item_, and search for "text template" I see the expected _Text Template_ and _Runtime Text Template" item templates (as well as the Entity Framework templates), for both old-style and new-style projects. Thanks!
Fixing the targets file so that it also works with .NET Core projects is trivial.
Change the _Microsoft.TextTemplating.targets.targets_ file as follows:
Change the line
<Target Name="TransformDuringBuild" Condition=" $(TransformOnBuild)==true">
to
<Target Name="TransformDuringBuild" Condition=" $(TransformOnBuild)==true" BeforeTargets="BeforeBuild">
(Optional) Delete the following lines:
```
The modified version will work equally well for old-style MSBuild projects, and has the added benefit that it no longer matters where in the project file the import of the _Microsoft.TextTemplating.targets_ file is placed.
### Workaround (1)
Just edit the _Microsoft.TextTemplating.targets_ file in _%ProgramFiles(x86)%\Microsoft Visual Studio\2017\[VS EDITION]\MSBuild\Microsoft\VisualStudio\v15.0\TextTemplating_ as described in the "Fix" section above, and import the targets into your project as described in the docs.
Note that this will required admin permissions on the machine.
### Workaround (2)
The first workaround might not be suitable in some circumstances (e.g. for build agent machine) as it requires admin permissions and the ability to edit a file on the machine.
The alternative is to import the targets as described in the docs, then tweak your project file to ensure the _TransformDuringBuild_ target is called.
One way of doing this would be to add the following snippet to your project:
```
There are two ways that targets can be hooked in to the execution flow in MSBuild (see Target Build Order). The old way (pre-MSBuild v4) was to use _DependsOnTargets_: the convention was that the target author would define a variable that contained the list of targets their target depended on, and extenders could update the variable to add their target to the list. The new way is to _BeforeTargets_ and _AfterTargets_.
The _Microsoft.TextTemplating.targets_ file uses the old method, and hook the _TransformDuringBuild_ target into the build by updating the _$(BuildDependsOn)_ variable. Unfortunately, the new standard Microsoft targets for .NET Core no longer use the _$(BuildDependsOn)_ variable, so the T4 targets are not linked in to the build.
@duncanp-sonar : I am sorry for the confusion in my message. What I meant was there is no official support for T4 in .Net Core projects. Also, thanks for sharing a solution.
Where is this Microsoft.TextTemplating.targets.targets file? I can't find it anywhere in the solution or in Program Files.
As @duncanp-sonar said, it is located here: %ProgramFiles(x86)%\Microsoft Visual Studio\2017[VS EDITION]\MSBuild\Microsoft\VisualStudio\v15.0\TextTemplating.
D'oh, I was looking in MSBuild. Thanks!
@duncanp-sonar Thanks for your workaround (2), it works a treat.
One annoying side-effect is that the TransformOutOfDateOnly property seems to be ignored-- every template in the project is transformed always. Do you have an idea of a workaround for that?
For background, I'm trying to migrate some older projects to the new .Net format, and this project in particular is a dependency of many other projects, so only transforming when the output was out of date is critical to ensuring that incremental builds are fast. When the transform happens always, essentially my entire solution needs to be rebuilt. It's not a great situation to be in.
I'd appreciate your thoughts. Thanks!
@dammejed I've updated workaround (2) above slightly.
To make incremental transformations work, you also need to set the build property TrackerLogDirectory. I've given an example in the workaround above, but I haven't tested it on a multi-framework. You might need to tweak the location slightly.
The incremental transformation behaviour depends on a feature of MSBuild calling "tracking logs". The transformation task tells MSBuild to track and store a list of all of the files read during the task execution in .tlog files. The next time the task runs, MSBuild can use the information in the .tlog files to work out if any of the task inputs have changed.
One consequence of this is that incremental transformations can only work on the second and subsequent builds since the .tlog files won't exist for the first build. This means that incremental transformations will never work in an Azure DevOps CI builds that use a hosted build agent since a new VM is used for each build and then destroyed. However, if you are hosting your own build agents then incremental transformations will work.
By default, the $(TrackerLogDirectory) property is set to the value of $(IntermediateOutputPath) in the main TextTemplating targets file. However, because the execution order is different for SDK-style MSBuild projects, $(IntermediateOutputPath) hasn't been set yet -> $(TrackerLogDirectory) is blank -> no .tlog files -> no incremental transforms.
There might be a more elegant workaround that avoids the need to set $(TrackerLogDirectory) explicitly e.g. by changing when the T4DotNetCoreWorkaround target is hooked into the standard SDK targets, but I haven't looked.
Brilliant, thank you for the updated workaround and the thorough explanation of both the problem and solution.
Your updated workaround worked great for me-- When doing subsequent solution builds, the project is now correctly detected as "up to date" on my development machine.
Closing this issue now since workarounds have been proposed. If something new comes up, please open a new issue.
@duncanp-sonar thanks a lot for workarounds, I'd like to add one thing to your instruction: it's necessary to disable "EnableDefaultCompileItems" and add your future generated .cs files as \
Most helpful comment
Fixing the targets file so that it also works with .NET Core projects is trivial.
Fix
Change the _Microsoft.TextTemplating.targets.targets_ file as follows:
Change the line
<Target Name="TransformDuringBuild" Condition=" $(TransformOnBuild)==true">to
<Target Name="TransformDuringBuild" Condition=" $(TransformOnBuild)==true" BeforeTargets="BeforeBuild">(Optional) Delete the following lines:
```
TransformDuringBuild;$(BuildDependsOn)
```
Background
There are two ways that targets can be hooked in to the execution flow in MSBuild (see Target Build Order). The old way (pre-MSBuild v4) was to use _DependsOnTargets_: the convention was that the target author would define a variable that contained the list of targets their target depended on, and extenders could update the variable to add their target to the list. The new way is to _BeforeTargets_ and _AfterTargets_.
The _Microsoft.TextTemplating.targets_ file uses the old method, and hook the _TransformDuringBuild_ target into the build by updating the _$(BuildDependsOn)_ variable. Unfortunately, the new standard Microsoft targets for .NET Core no longer use the _$(BuildDependsOn)_ variable, so the T4 targets are not linked in to the build.