Vraag Visual Studio om een ​​T4-sjabloon uit te voeren op elke build

Hoe zorg ik ervoor dat een T4-sjabloon de uitvoer ervan genereert bij elke build? Zoals het nu is, wordt het alleen opnieuw gegenereerd wanneer ik een wijziging aanbreng in de sjabloon.

Ik heb andere soortgelijke vragen gevonden:

T4-transformatie en bouwvolgorde in Visual Studio( onbeantwoord)

Hoe t4-bestanden visueel in te bouwen studio?(antwoorden zijn niet gedetailleerd genoeg [terwijl ze nog steeds erg ingewikkeld zijn] en zijn zelfs niet helemaal logisch)

Er moet een eenvoudigere manier zijn om dit te doen!


Antwoord 1, autoriteit 100%

Ik ben het eens met GarethJ – in VS2010 is het veel gemakkelijker om tt-sjablonen bij elke build opnieuw te genereren.
De blog van Oleg Sych beschrijft hoe je het moet doen. In het kort:

  1. Installeer Visual Studio SDK
  2. Installeer Visual Studio 2010 Modellering
    en visualisatie SDK
  3. Open in teksteditor projectbestand en
    toevoegen aan het einde van het bestand maar vóór </Project>

Dat is het. Open uw project. Bij elke build worden alle *.tt-sjablonen opnieuw verwerkt

<!-- 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" />

Antwoord 2, autoriteit 96%

Ik heb het antwoord van JoelFan gebruikt om dit te bedenken. Ik vind het leuker omdat je niet hoeft te onthouden om de pre-build-gebeurtenis te wijzigen telkens wanneer je een nieuw .tt-bestand aan het project toevoegt.

  • Voeg TextTransform.exe toe aan uw %PATH%
  • een batchbestand gemaakt met de naam transform_all.bat (zie hieronder)
  • maak een pre-build evenement “transform_all ..\..

transform_all.bat

@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
:: set the working dir (default to current dir)
set wdir=%cd%
if not (%1)==() set wdir=%1
:: set the file extension (default to vb)
set extension=vb
if not (%2)==() set extension=%2
echo executing transform_all from %wdir%
:: create a list of all the T4 templates in the working dir
dir %wdir%\*.tt /b /s > t4list.txt
echo the following T4 templates will be transformed:
type t4list.txt
:: transform all the templates
for /f %%d in (t4list.txt) do (
set file_name=%%d
set file_name=!file_name:~0,-3!.%extension%
echo:  \--^> !file_name!    
TextTransform.exe -out !file_name! %%d
)
echo transformation complete

Antwoord 3, autoriteit 45%

Er is een geweldig NuGet-pakketdat precies dit doet:

PM> Install-Package Clarius.TransformOnBuild

Details over het pakket zijn te vinden op hier te vindenen de GitHub-repo is hier.


Antwoord 4, autoriteit 27%

Ik heb het antwoord van MarkGr gebruikt en deze oplossing ontwikkeld. Maak eerst een batchbestand met de naam RunTemplate.batin een aparte map toolsboven de hoofdoplossingsmap. Het batchbestand heeft alleen de regel:

"%CommonProgramFiles%\Microsoft Shared\TextTemplating\1.2\texttransform.exe" -out %1.cs -P %2 -P "%ProgramFiles%\Reference Assemblies\Microsoft\Framework\v3.5" %1.tt

Dit batchbestand heeft 2 parameters… %1is het pad naar het .tt-bestand zonder de .tt-extensie. %2is het pad naar alle DLL’s waarnaar wordt verwezen door Assembly-richtlijnen in de sjabloon.

Ga vervolgens naar de projecteigenschappen van het project dat de T4-sjabloon bevat. Ga naar Build Eventsen voeg de volgende Pre-build event-opdrachtregeltoe:

$(SolutionDir)..\..\tools\RunTemplate.bat $(ProjectDir)MyTemplate $(OutDir)

MijnTemplatevervangen door de bestandsnaam van uw .tt-bestand (d.w.z. MijnTemplate.tt) zonder de .tt-extensie. Dit heeft als resultaat dat de sjabloon wordt uitgebreid om MyTemplate.cs te produceren voordat het project wordt gebouwd. Vervolgens compileert de daadwerkelijke build MyTemplate.cs


Antwoord 5, autoriteit 19%

Onlangs deze geweldige VS-plug-in gevonden, Chirpy.

Het genereert niet alleen uw T4 op een build, maar het maakt ook een T4-gebaseerde benadering mogelijk voor minificatie van javascript, CSS en laat u zelfs MINDER syntaxis gebruiken voor uw CSS!


Antwoord 6, autoriteit 18%

De eenvoudigste manier is waarschijnlijk om een ​​Visual Studio-extensie te installeren met de naam AutoT4.

Alle T4-sjablonen worden automatisch op build uitgevoerd.


Antwoord 7, autoriteit 16%

De pre-build kan worden teruggebracht tot een enkele regel:

forfiles /p "$(ProjectDir)." /m "*.tt" /s /c "cmd /c echo Transforming @path && \"%CommonProgramFiles(x86)%\Microsoft Shared\TextTemplating\1.2\TextTransform.exe\" @file"

Dit transformeert alle .TT-bestanden in het project en vermeldt ze in de build-uitvoer.

Als je de build-output niet wilt, moet je wat “interessant gedrag”omzeilen:

forfiles /p "$(ProjectDir)." /m "*.tt" /s /c "cmd /c @\"%CommonProgramFiles(x86)%\Microsoft Shared\TextTemplating\1.2\TextTransform.exe\" @file"

Natuurlijk kunt u dit in een batchbestand opnemen waaraan u desgewenst het pad van de projectdirectory doorgeeft.

NBHet pad kan enige aanpassing vereisen. Het bovenstaande pad is waar VS 2008 het op mijn computer heeft geïnstalleerd; maar het kan zijn dat het versienummer tussen TextTemplatingen TextTransform.exeanders is.


Antwoord 8, autoriteit 12%

Bekijk
C:\Program Files (x86)\Common Files\Microsoft Shared\TextTemplating
daar zit een command line transformation exe in. U kunt ook een MSBuild-taak schrijven met een aangepaste host en de transformatie zelf uitvoeren.


Antwoord 9, autoriteit 11%

Dankzij GitHub.com/Mono/T4kun je het momenteel voor beide doen. NET Core- en Visual Studio-builds door dit toe te voegen aan uw .csproj-bestand:

 <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>

Als u uw sjablonen omzet in verschillende programmeertalen, moet u iets toevoegen als <Compile Remove="**\*.vb" />en <Compile Include="**\*.vb" />om deze bestanden gecompileerd te krijgen, zelfs als u nog geen gegenereerde bestanden heeft.

De truc

Removeen Includeis alleen nodig voor de eerste generatie, of je kunt de XML als volgt korter maken:

 <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>

en voer build twee keer uit (voor de eerste keer). Als je al bestanden hebt gegenereerd die zijn vastgelegd in de repository, zullen er geen problemen zijn bij het opnieuw opbouwen met beide voorbeelden.

In de Visual Studio wil je misschien zoiets zien:

in plaats van dit:

Dus voeg zoiets als dit toe aan je projectbestand:

 <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>

Compleet voorbeeld hier: GitHub.com/Konard/T4GenericsExample(inclusief het genereren van meerdere bestanden van één sjabloon ).


Antwoord 10, autoriteit 10%

Uitbreiden op Seth Renoen JoelFan’santwoorden, ik heb dit bedacht. Met deze oplossing hoeft u er niet aan te denken om de pre-build-gebeurtenis aan te passen telkens wanneer u een nieuw .tt-bestand aan het project toevoegt.

Implementatieprocedure

  • Maak een batchbestand met de naam transform_all.bat (zie hieronder)
  • Maak een pre-build evenement transform_all.bat "$(ProjectDir)" $(ProjectExt)voor elk project met een .tt die je wilt bouwen

transform_all.bat

@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
:: set the correct path to the the app
if not defined ProgramFiles(x86). (
  echo 32-bit OS detected
  set ttPath=%CommonProgramFiles%\Microsoft Shared\TextTemplating\1.2\
) else (
  echo 64-bit OS detected
  set ttPath=%CommonProgramFiles(x86)%\Microsoft Shared\TextTemplating\1.2\
)
:: set the working dir (default to current dir)
if not (%1)==() pushd %~dp1
:: set the file extension (default to vb)
set ext=%2
if /i %ext:~1%==vbproj (
  set ext=vb
) else if /i %ext:~1%==csproj (
  set ext=cs
) else if /i [%ext%]==[] (
  set ext=vb
)
:: create a list of all the T4 templates in the working dir
echo Running TextTransform from %cd%
dir *.tt /b /s | findstr /vi obj > t4list.txt
:: transform all the templates
set blank=.
for /f "delims=" %%d in (t4list.txt) do (
  set file_name=%%d
  set file_name=!file_name:~0,-3!.%ext%
  echo:  \--^> !!file_name:%cd%=%blank%!
  "%ttPath%TextTransform.exe" -out "!file_name!" "%%d"
)
:: delete T4 list and return to previous directory
del t4list.txt
popd
echo T4 transformation complete

OPMERKINGEN

  1. De teksttransformatie gaat ervan uit dat de code in de T4-sjabloon dezelfde taal is als uw projecttype. Als dit geval niet op u van toepassing is, moet u het argument $(ProjectExt)vervangen door de extensie van de bestanden die u door de code wilt laten genereren.

  2. .TT-bestanden moeten in de projectdirectory staan, anders worden ze niet gebouwd. U kunt TT-bestanden buiten de projectdirectory bouwen door een ander pad als eerste argument op te geven (dwzvervang "$(ProjectDir)"door het pad dat de TT-bestanden bevat.)

  3. Vergeet niet om het juiste pad naar het batchbestand transform_all.batin te stellen.
    Ik plaatste het bijvoorbeeld in mijn oplossingsmap, zodat de pre-build-gebeurtenis als volgt was "$(SolutionDir)transform_all.bat" "$(ProjectDir)" $(ProjectExt)


Antwoord 11, autoriteit 8%

Als u Visual Studio 2010 gebruikt, kunt u de Visual Studio Modeling and Visualization SDK gebruiken:
http://code.msdn.microsoft.com/vsvmsdk

Dit bevat msbuild-taken voor het uitvoeren van T4-sjablonen tijdens het bouwen.

Bekijk de blog van Oleg voor meer uitleg:
http://www.olegsych.com/2010/04/understanding-t4 -msbuild-integratie


Antwoord 12, autoriteit 5%

Hé,
mijn script kan ook de uitvoerextensie ontleden

for /r %1 %%f in (*.tt) do (
 for /f "tokens=3,4 delims==, " %%a in (%%f) do (
  if %%~a==extension "%CommonProgramFiles%\Microsoft Shared\TextTemplating\1.2\texttransform.exe" -out %%~pnf.%%~b -P %%~pf -P "%ProgramFiles%\Reference Assemblies\Microsoft\Framework\v3.5" %%f
 )
)
echo Exit Code = %ERRORLEVEL%

Maak gewoon transform_all.bat $(SolutionDir)pre-build-gebeurtenis, en alle *.tt-bestanden in uw oplossing worden automatisch getransformeerd.


Antwoord 13, autoriteit 4%

Dynamo.AutoTT doet wat je nodig hebt. Je kunt het configureren om bestanden te bekijken via een regex of te genereren bij het bouwen. Je kunt er ook mee aangeven welke T4-sjablonen je wilt activeren.

Je kunt het hier downloaden: https://github.com/MartinF/Dynamo.AutoTT

Bouw het gewoon, kopieer de dll- en AddIn-bestanden naar

C:\Users\Documents\Visual Studio 2012\Addins\

en daar ga je.

Als u het in VS2012 wilt laten werken, moet u het Dynamo.AutoTT.AddIn-bestand wijzigen en de versie instellen op 11.0 in het AddIn-bestand;


Antwoord 14, autoriteit 3%

Je hoeft alleen dit commando toe te voegen aan de pre-build gebeurtenis van het project:

if $(ConfigurationName) == Debug $(MSBuildToolsPath)\Msbuild.exe  /p:CustomBeforeMicrosoftCSharpTargets="$(ProgramFiles)\MSBuild\Microsoft\VisualStudio\v11.0\TextTemplating\Microsoft.TextTemplating.targets"  $(ProjectPath) /t:TransformAll 

De controle op configuratie = debug, zorgt ervoor dat u de code niet opnieuw genereert in de release-modus, bijvoorbeeld wanneer u de build op de TFS-buildserver doet.


Antwoord 15, autoriteit 3%

In Visual Studio 2017 (waarschijnlijk ook volgende versies), moet u dit toevoegen in Pre-build-gebeurtenis:

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

ps. Wijzig het pad naar uw sjabloon als deze zich niet in de hoofdmap van het project bevindt.


Antwoord 16

Hier is mijn oplossing – vergelijkbaar met het geaccepteerde antwoord.
We hadden een probleem met ons bronbeheer. De doel-.cs-bestanden zijn alleen-lezen en de T4 werkte niet.
Hier is de code die T4 in de tijdelijke map uitvoert, doelbestanden vergelijkt en deze alleen kopieert in het geval van dezelfde wijziging. Het lost het probleem met alleen-lezen bestanden niet op, maar het komt in ieder geval niet vaak voor:

Transform.bat

ECHO Transforming T4 templates
SET CurrentDirBackup=%CD%
CD %1
ECHO %1
FOR /r %%f IN (*.tt) DO call :Transform %%f
CD %CurrentDirBackup%
ECHO T4 templates transformed
goto End
:Transform
set ttFile=%1
set csFile=%1
ECHO Transforming %ttFile%:
SET csFile=%ttFile:~0,-2%cs
For %%A in ("%ttFile%") do Set tempTT=%TEMP%\%%~nxA
For %%A in ("%csFile%") do Set tempCS=%TEMP%\%%~nxA
copy "%ttFile%" "%tempTT%
"%COMMONPROGRAMFILES(x86)%\microsoft shared\TextTemplating\11.0\TextTransform.exe"  "%tempTT%"
fc %tempCS% %csFile% > nul
if errorlevel 1 (
 :: You can try to insert you check-out command here.
 "%COMMONPROGRAMFILES(x86)%\microsoft shared\TextTemplating\11.0\TextTransform.exe"  "%ttFile%"
) ELSE (
 ECHO  no change in %csFile%
)
del %tempTT%
del %tempCS%
goto :eof
:End

U kunt proberen uw uitcheckopdracht op een regel toe te voegen (:: U kunt proberen ….)

Stel dit in uw project in als een vooraf gemaakte actie:

Path-To-Transform.bat "$(ProjectDir)"

Antwoord 17

Klik in Visual Studio 2013 met de rechtermuisknop op de T4-sjabloon en stel de eigenschap Transform on build in op true.


Antwoord 18

Hier is hoe ik het heb aangepakt. Link. In feite voortbouwen op een geweldige blog (blogs.clariusconsulting.net/kzu/how-to-transform-t4-templates-on-build-without-installing-a-visual-studio-sdk/ kan niet meer dan 2 plaatsen links 🙁 ) Ik heb dit .targets-bestand bedacht voor gebruik met visual studio proj-bestanden.

Het is handig wanneer u andere dll-s binnen uw .tt gebruikt en u wilt dat het resultaat verandert als de dll-s veranderen.

Hoe het werkt:

  1. Maak de tt, voeg de assembly name=”$(SolutionDir)path\to\other\project\output\foo.dll toe en stel de transformatie en het resultaat in zoals verwacht
  2. Verwijder de assembly-referenties uit .tt

  3. Gebruik deze code in het proj-bestand om transformatie bij build in te stellen:

    <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, '&amp;quot; -r &amp;quot;')</IncludeForTransform>
    </PropertyGroup>
    
    • Eerste deel lokaliseert TextTransform.exe

    • $(IncludeForTransform)is gelijk aan c:\path\to\dll\foo.dll' -r c:\path\to\dll\bar.dllwant dat is de manier om referenties toe te voegen voor de TextTransform op de commandoregel

      <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="&quot;$(_TransformExe)&quot; &quot;@(_TextTransform)&quot; -r &quot;$(IncludeForTransform)&quot;" Condition="'%(Identity)' != ''" />
       </Target>
      
    • <_TextTransform Include="$(ProjectDir)**\*.tt" />dit creëert een lijst van alle tt-bestanden in het project en submappen

    • <Exec Command="...produceert een regel voor elk van de gevonden .tt-bestanden die eruitziet als "C:\path\to\Transform.exe" "c:\path\to\my\proj\TransformFile.tt" -r"c:\path\to\foo.dll" -r "c:\path\to\bar.dll"

  4. Het enige dat u nog hoeft te doen, is de paden toevoegen aan de dll’s in:

       <ItemGroup>
          <DllsToInclude Include="$(ProjectDir)path\to\foo.dll">
            <InProject>False</InProject>
          </DllsToInclude>
          <DllsToInclude Include="$(ProjectDir)path\to\bar.dll">
            <InProject>False</InProject>
          </DllsToInclude>
        </ItemGroup>
    

    Hier <InProject>False</InProject>verbergt deze items in de oplossingsweergave

Dus nu zou je je code moeten kunnen genereren bij het bouwen en bij het wijzigen van dll-s.

U kunt de aangepaste tool verwijderen (van de eigenschappen in Visual Studio), zodat de VS niet elke keer proberen te transformeren en jammerlijk mislukken. Omdat we de assembly-referenties in stap 2 hebben verwijderd


Antwoord 19

T4Executerdoet dit voor VS2019. U kunt sjablonen specificeren die tijdens het bouwen moeten worden genegeerd, en er is een optie voor uitvoeren na bouwen.


Antwoord 20

Je installeert gewoon NuGet Package: Clarius.TransformOnBuild

Telkens wanneer u op Rebuildproject (of Solution) klikt, worden uw .tt-bestanden uitgevoerd


Antwoord 21

Een of andere kerelheeft hiervoor een nuget-pakketgebouwd.

Kanttekening: ik krijg compileerfouten van zowel TextTemplate.exe als dat pakket (omdat dat pakket TextTemplate.exe aanroept), maar niet van Visual Studio. Dus blijkbaar is het gedrag niet hetzelfde; heads-up.

EDIT: Ditwerd uiteindelijk mijn probleem.


Antwoord 22

Hier is een pre-build-gebeurtenis waarbij alleen Microsoft Tooling en standaardpaden worden gebruikt. Het is getest in vs2019/netcore3.1.

Vervang “AppDbContext.tt” door uw project-relatieve bestandspad:

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

Microsoft heeft ook een handleiding om macro’s zoals “$(SolutionDirectory)” beschikbaar te maken in de sjabloon met behulp van T4ParameterValuesin uw projectbestand.

Other episodes