Compartilhar via


Invocar transformação de texto no processo de compilação

A transformação de texto pode ser invocada como parte do processo de compilação de uma solução do Visual Studio. Há tarefas de compilação que são especializadas para a transformação de texto. As tarefas de compilação T4 executam modelos de texto de tempo de design e também compilam modelos de texto de tempo de execução (pré-processados).

Há algumas diferenças em termos do que as tarefas de compilação podem fazer, dependendo do mecanismo de compilação que você usa. Quando você compila a solução no Visual Studio, um modelo de texto pode acessar a API do Visual Studio (EnvDTE) quando o atributo hostspecific="true" é definido. Mas isso não ocorre quando você compila a solução a partir da linha de comando ou ao iniciar uma compilação do servidor com o Visual Studio. Nesses casos, a compilação é executada pelo MSBuild e um host T4 diferente é usado. Isso significa que você não pode acessar itens como nomes de arquivo do projeto da mesma forma quando você cria um modelo de texto usando o MSBuild. Porém, você pode passar informações do ambiente para modelos de texto e processadores de diretriz usando parâmetros de compilação.

Configurar seus computadores

Para habilitar tarefas de compilação no seu computador de desenvolvimento, instale o SDK de Modelagem para Visual Studio.

Observação

O componente Transformação de Modelo de Texto é instalado automaticamente como parte da carga de trabalho de Desenvolvimento de extensões do Visual Studio. Você também pode instalá-lo na guia Componentes individuais do Instalador do Visual Studio, na categoria SDKs, bibliotecas e estruturas. Instale o componente SDK de Modelagem na guia Componentes individuais.

Caso seu servidor de compilação seja executado em um computador que não tenha o Visual Studio instalado, copie os seguintes arquivos para o computador de compilação a partir do computador de desenvolvimento:

  • %ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VisualStudio\v16.0\TextTemplating

    • Microsoft.VisualStudio.TextTemplating.Sdk.Host.15.0.dll
    • Microsoft.TextTemplating.Build.Tasks.dll
    • Microsoft.TextTemplating.targets
  • %ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\VSSDK\VisualStudioIntegration\Common\Assemblies\v4.0

    • Microsoft.VisualStudio.TextTemplating.15.0.dll
    • Microsoft.VisualStudio.TextTemplating.Interfaces.15.0.dll
    • Microsoft.VisualStudio.TextTemplating.VSHost.15.0.dll
  • %ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\Common7\IDE\PublicAssemblies

    • Microsoft.VisualStudio.TextTemplating.Modeling.15.0.dll

Dica

Se você receber um MissingMethodException para um método Microsoft.CodeAnalysis ao executar destinos de compilação TextTemplating em um servidor de compilação, garanta que os assemblies Roslyn estejam em um diretório chamado Roslyn que está no mesmo diretório que o executável de compilação (por exemplo, msbuild.exe).

Editar o arquivo de projeto

Edite o arquivo de projeto para configurar alguns dos recursos no MSBuild, por exemplo, importando os destinos de transformação de texto.

No Gerenciador de Soluções, escolha Descarregar no menu de clique com o botão direito do mouse do projeto. Isso permite que você edite o arquivo .csproj ou .vbproj no editor de XML. Quando você terminar de editar, escolha Recarregar.

Importar os destinos da transformação de texto

No arquivo .vbproj ou .csproj, localize a última linha Import Project.

Depois dessa linha, se existir, insira a importação de modelagem de texto:

<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v17.0\TextTemplating\Microsoft.TextTemplating.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v16.0\TextTemplating\Microsoft.TextTemplating.targets" />

Transformar modelos em uma compilação

Há algumas propriedades que podem ser inseridas em seu arquivo de projeto para controlar a tarefa de transformação:

  • Execute a tarefa Transform no início de cada compilação:

    <PropertyGroup>
        <TransformOnBuild>true</TransformOnBuild>
    </PropertyGroup>
    
  • Substitua os arquivos que são somente leitura, por exemplo, porque eles não passam por check-out:

    <PropertyGroup>
        <OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles>
    </PropertyGroup>
    
  • Transforme cada modelo toda vez:

    <PropertyGroup>
        <TransformOutOfDateOnly>false</TransformOutOfDateOnly>
    </PropertyGroup>
    

    Por padrão, a tarefa T4 MSBuild regenerará um arquivo de saída se ele for mais antigo que:

    • o arquivo de modelo
    • qualquer arquivo incluído
    • qualquer arquivo que foram lidos anteriormente pelo modelo ou por um processador de diretiva que ele usa

    Esse é um teste de dependência mais avançado do que é usado pelo comando Transformar Todos os Modelos no Visual Studio, que compara apenas as datas do modelo e do arquivo de saída.

Para executar apenas as transformações de texto em seu projeto, invoque a tarefa TransformAll:

msbuild myProject.csproj /t:TransformAll

Para transformar um modelo específico de texto:

msbuild myProject.csproj /t:Transform /p:TransformFile="Template1.tt"

Você pode usar curingas em TransformFile:

msbuild dsl.csproj /t:Transform /p:TransformFile="GeneratedCode\**\*.tt"

Controle do código-fonte

Não há integração interna específica com um sistema de controle do código-fonte. No entanto, você pode adicionar suas próprias extensões, por exemplo, para fazer check-out e check-in de um arquivo gerado. Por padrão, a tarefa de transformação de texto evita substituir um arquivo marcado como somente leitura. Quando esse arquivo é encontrado, um erro é registrado na Lista de Erros do Visual Studio e a tarefa falha.

Para especificar que os arquivos somente leitura devem ser substituídos, insira esta propriedade:

<OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles>

A menos que você personalize a etapa de pós-processamento, um aviso será registrado na Lista de Erros quando um arquivo for substituído.

Personalizar o processo de compilação

A transformação de texto ocorre antes de outras tarefas no processo de compilação. Você pode definir as tarefas que são invocadas antes e depois da transformação, definindo as propriedades $(BeforeTransform) e $(AfterTransform):

<PropertyGroup>
    <BeforeTransform>CustomPreTransform</BeforeTransform>
    <AfterTransform>CustomPostTransform</AfterTransform>
</PropertyGroup>
<Target Name="CustomPreTransform">
    <Message Text="In CustomPreTransform..." Importance="High" />
</Target>
<Target Name="CustomPostTransform">
    <Message Text="In CustomPostTransform..." Importance="High" />
</Target>

Em AfterTransform, você pode referenciar listas de arquivos:

  • GeneratedFiles – uma lista de arquivos gravados pelo processo. Para os arquivos que substituem os arquivos somente leitura existentes, %(GeneratedFiles.ReadOnlyFileOverwritten) será verdadeiro. Esses arquivos podem passar por check-out do controle do código-fonte.

  • NonGeneratedFiles – uma lista de arquivos somente leitura que não foram substituídos.

Por exemplo, você definirá uma tarefa fazer check-out de GeneratedFiles.

OutputFilePath e OutputFileName

Essas propriedades são usadas somente pelo MSBuild. Elas não afetam a geração de código no Visual Studio. Elas redirecionam o arquivo de saída gerado para uma pasta ou um arquivo diferente. A pasta de destino já deve existir.

<ItemGroup>
  <None Include="MyTemplate.tt">
    <Generator>TextTemplatingFileGenerator</Generator>
    <OutputFilePath>MyFolder</OutputFilePath>
    <LastGenOutput>MyTemplate.cs</LastGenOutput>
  </None>
</ItemGroup>

Uma pasta útil para redirecionar é $(IntermediateOutputPath).

Se você especificar um nome de arquivo de saída, ele terá precedência sobre a extensão especificada na diretiva de saída nos modelos.

<ItemGroup>
  <None Include="MyTemplate.tt">
    <Generator>TextTemplatingFileGenerator</Generator>
    <OutputFileName>MyOutputFileName.cs</OutputFileName>
    <LastGenOutput>MyTemplate.cs</LastGenOutput>
  </None>
</ItemGroup>

Especificar OutputFileName ou OutputFilePath não é recomendado se você também estiver transformando modelos no Visual Studio usando Transformar Tudo ou executando o gerador de único arquivo. Você acabará com caminhos de arquivos diferentes dependendo de como tiver desencadeado a transformação. Isso pode ser confuso.

Adicionar referência e incluir caminhos

O host tem um conjunto padrão de caminhos em que procura assemblies referenciados em modelos. Para adicionar a este conjunto:

<ItemGroup>
    <T4ReferencePath Include="$(VsIdePath)PublicAssemblies\" />
    <!-- Add more T4ReferencePath items here -->
</ItemGroup>

Para definir as pastas em que arquivos de inclusão serão procurados, forneça uma lista separada por ponto-e-vírgula. Normalmente, você adiciona à lista de pastas existente.

<PropertyGroup>
    <IncludeFolders>
$(IncludeFolders);$(MSBuildProjectDirectory)\Include;AnotherFolder;And\Another</IncludeFolders>
</PropertyGroup>

Passar dados de contexto da compilação para os modelos

Você pode definir valores de parâmetros no arquivo do projeto. Por exemplo, você pode passar propriedades da compilação e variáveis do ambiente:

<ItemGroup>
  <T4ParameterValues Include="ProjectFolder">
    <Value>$(ProjectDir)</Value>
    <Visible>false</Visible>
  </T4ParameterValues>
</ItemGroup>

Em um modelo de texto, defina hostspecific na diretiva do modelo. Use a diretiva parameter para obter os valores:

<#@template language="c#" hostspecific="true"#>
<#@ parameter type="System.String" name="ProjectFolder" #>
The project folder is: <#= ProjectFolder #>

Em um processador de diretiva, você pode chamar ITextTemplatingEngineHost.ResolveParameterValue:

string value = Host.ResolveParameterValue("-", "-", "parameterName");

Observação

ResolveParameterValue obtém dados de T4ParameterValues somente quando você usa o MSBuild. Quando você transformar o modelo usando o Visual Studio, os parâmetros terão valores padrão.

Usar propriedades do projeto no assembly e diretivas de inclusão

Macros do Visual Studio como $(SolutionDir) não funcionam no MSBuild. Você pode usar as propriedades do projeto como alternativa.

Edite seu arquivo .csproj ou .vbproj para definir uma propriedade do projeto. Este exemplo define uma propriedade chamada myLibFolder:

<!-- Define a project property, myLibFolder: -->
<PropertyGroup>
    <myLibFolder>$(MSBuildProjectDirectory)\..\libs</myLibFolder>
</PropertyGroup>

<!-- Tell the MSBuild T4 task to make the property available: -->
<ItemGroup>
    <T4ParameterValues Include="myLibFolder">
      <Value>$(myLibFolder)</Value>
    </T4ParameterValues>
  </ItemGroup>

Agora você pode usar sua propriedade de projeto no assembly e diretivas de inclusão:

<#@ assembly name="$(myLibFolder)\MyLib.dll" #>
<#@ include file="$(myLibFolder)\MyIncludeFile.t4" #>

Essas diretivas obtêm valores de T4parameterValues nos hosts do MSBuild e do Visual Studio.

Perguntas e respostas

Por que convém transformar modelos no servidor de compilação? Eu já transformei modelos no Visual Studio antes de fazer check-in do código.

Se você atualizar um arquivo incluído ou outro arquivo lido pelo modelo, o Visual Studio não transformará o arquivo automaticamente. Transformar modelos como parte da compilação assegura que tudo seja atualizado.

Quais são as outras opções disponíveis para transformar modelos de texto?

  • Há boas diretrizes no modelo T4 MSbuild em %ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\VisualStudio\v17.0\TextTemplating\Microsoft.TextTemplating.targets
  • Há boas diretrizes no modelo T4 MSbuild em %ProgramFiles(x86)%\Microsoft Visual Studio\2019\Enterprise\msbuild\Microsoft\VisualStudio\v16.0\TextTemplating\Microsoft.TextTemplating.targets