Search code examples
c#continuous-integrationt4cakebuild

How to execute t4 template using the Cake script


What is the API / Syntax to execute the T4 template using the Cake build? Any example code will be helpful.

Whether StartProcess API should be used to call the texttransform.exe or is there any other API's available.


Solution

  • There's two built-in aliases for working with T4 templates in Cake, TransformTemplate(ICakeContext, FilePath) and TransformTemplate(ICakeContext, FilePath, TextTransformSettings)

    Example usage:

    #tool "nuget:?package=Mono.TextTransform&version=1.0.0"
    
    Task("TransformTemplate")
        .Does(() => {
        var templateFile = File("./Template.tt");
    
        TransformTemplate(templateFile);
    });
    
    
    RunTarget("TransformTemplate");
    

    Example template used

    Template generated <#=DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss")#>
    

    Example template result

    Template generated 2020-02-12 11:19:08
    

    If you have .NET Core installed it's recommended that you use the dotnet-t4 global tool as it's more well maintained.

    Example cake script using the dotnet-t4 global tool (Cake tool resolution will find use either t4.exe or texttransform.exe automatically depending on which it finds first, as with any tool you can override which tool used by ToolSettings ToolPath property in this case TextTransformSettings

    #module nuget:?package=Cake.DotNetTool.Module&version=0.4.0
    #tool "dotnet:?package=dotnet-t4&version=2.0.5"
    
    Task("TransformTemplate")
        .Does(() => {
        var templateFile = File("./HelloWorld.tt");
        var targetFile = File("./HelloWorld.txt");
        var settings = new TextTransformSettings {
                        OutputFile = targetFile,
                        Properties = {
                            ["FirstName"] = "John",
                            ["LastName"] = "Doe"
                        }
                    };
    
    
        TransformTemplate(templateFile, settings);
    });
    
    
    RunTarget("TransformTemplate");
    

    Example HelloWorld.tt

    <#@ parameter name='FirstName' #>
    <#@ parameter name='LastName' #>
    Hello <#=FirstName#> <#=LastName#>!
    

    Example result HelloWorld.txt

    Hello John Doe!
    

    To use Cake.DotNetTool.Module we atm need to bootstrap so module is fetched from NuGet (won't be needed in Cake 1.0), example execution

    dotnet cake .\t4.cake --bootstrap 
    dotnet cake .\t4.cake
    

    As asked for below an example using directive processor(Note: in mono T4 this is depreciated, so will only fully work with VisualStudio version of TextTransform.exe), directive processors aren't currently wrapped in TextTransformSettings but we can sort it like any Cake tool through ToolSettings ArgumentCustomization property.

    Example template DirectiveTemplate.tt

    <#@template language="c#" hostspecific="true"#>
    Hello <#= this.Host.ResolveParameterValue("", "", "greet") #>!
    

    Example Cake script, where we use VSWhere to locate VisualStudio version of TextTransform.exe, register path with Cake tool resolution and pass directive argument through argument customization.

    #tool "nuget:?package=vswhere&version=2.8.4"
    
    Setup(setupContext =>{
        DirectoryPath vsLatest = VSWhereLatest();
        FilePath    textTransformPath = vsLatest?.CombineWithFilePath("Common7/IDE/TextTransform.exe");
    
        if (textTransformPath == null || !FileExists(textTransformPath))
        {
            throw new Exception("Failed to resolve TextTransform.exe path.");
        }
    
        setupContext.Tools.RegisterFile(textTransformPath);
    });
    
    
    Task("T4")
        .Does(() => {
        var settings = new TextTransformSettings {
                        ArgumentCustomization = args => args.AppendSwitchQuoted("-a", " ", "!!greet!John")
                    };
        TransformTemplate("./DirectiveTemplate.tt", settings);
    });
    
    RunTarget("T4");
    

    The result in DirectiveTemplate.txt will be

    Hello John!