Partilhar via


Transformações do MSBuild

Uma transformação é uma conversão um-para-um de uma lista de itens para outra. As transformações permitem que projetos no Visual Studio convertam listas de itens. As transformações também permitem que os alvos identifiquem um mapeamento direto entre suas entradas e saídas.

Este artigo explica as transformações e como o Microsoft Build Engine (MSBuild) as usa para criar projetos com mais eficiência.

Modificadores de transformação

As transformações não são definidas arbitrariamente. Cada transformação é identificada como um modificador do formato %(\<ItemMetaDataName>). Quaisquer metadados de item podem ser usados como um modificador de transformação, incluindo os metadados de item conhecidos atribuídos a cada item no momento da criação. Para obter a lista de metadados de item conhecidos, consulte Metadados de item conhecidos do MSBuild.

O exemplo a seguir transforma uma lista de arquivos .resx em uma lista de arquivos .resources . O %(filename) modificador de transformação especifica que cada arquivo .resources tem o mesmo nome de arquivo que o arquivo .resx correspondente:

@(RESXFile->'%(filename).resources')

Se os itens na lista de @(RESXFile) itens são Form1.resx, Form2.resx e Form3.resx, a lista transformada contém as saídas Form1.resources, Form2.resources e Form3.resources.

Observação

O separador padrão para itens em uma lista transformada é o ponto-e-vírgula ;. Você pode especificar um separador personalizado da mesma forma que especifica um separador para uma lista de itens padrão. Para separar itens com uma vírgula , , use a sintaxe @(RESXFile->'Toolset\%(filename)%(extension)', ',').

Modificadores de múltiplas transformações

Uma expressão de transformação pode conter vários modificadores que podem ser combinados em qualquer ordem e podem ser repetidos. No exemplo a seguir, o nome do diretório que contém os arquivos é alterado, mas os arquivos mantêm o nome original e a extensão de nome de arquivo:

@(RESXFile->'Toolset\%(filename)%(extension)')

Se os itens na lista de RESXFile itens forem Project1\Form1.resx, Project1\Form2.resx e Project1\Form3.text, a lista transformada conterá as saídas Toolset\Form1.resx, Toolset\Form2.resx e Toolset\Form3.text.

Mapeamento de alvos e análise de dependência

As transformações garantem um mapeamento um-para-um entre a lista de itens transformados e a lista de itens original. Se um alvo cria saídas que são transformações das entradas, o MSBuild pode analisar os carimbos de data/hora das entradas e saídas. O MSBuild usa a informação para decidir se deve ignorar, compilar ou reconstruir parcialmente um alvo.

O exemplo a seguir transforma as entradas da tarefa Copy em saídas. Cada ficheiro na lista de itens de entrada BuiltAssemblies é mapeado para um ficheiro na pasta de destino da tarefa especificada ao utilizar uma transformação no atributo Outputs. Se um arquivo na lista de BuiltAssemblies itens for alterado, o Copy task arquivo será executado somente para o arquivo alterado e ignorará todos os outros arquivos.

<Target Name="CopyOutputs"
    Inputs="@(BuiltAssemblies)"
    Outputs="@(BuiltAssemblies -> '$(OutputPath)%(Filename)%(Extension)')">

    <Copy
        SourceFiles="@(BuiltAssemblies)"
        DestinationFolder="$(OutputPath)"/>

</Target>

Para obter mais informações sobre análise de dependência e como usar transformações, consulte Compilações incrementais do MSBuild para destinos novos ou obsoletos.

Arquivo de projeto com transformações

O exemplo a seguir mostra um arquivo de projeto para MSBuild que usa transformações. O exemplo pressupõe que o diretório c:\sub0\sub1\sub2\sub3 contém apenas um arquivo .xsd e o diretório de trabalho é c:\sub0.

<Project>
    <ItemGroup>
        <Schema Include="sub1\**\*.xsd"/>
    </ItemGroup>

    <Target Name="Messages">
        <Message Text="rootdir: @(Schema->'%(rootdir)')"/>
        <Message Text="fullpath: @(Schema->'%(fullpath)')"/>
        <Message Text="rootdir + directory + filename + extension: @(Schema->'%(rootdir)%(directory)%(filename)%(extension)')"/>
        <Message Text="identity: @(Schema->'%(identity)')"/>
        <Message Text="filename: @(Schema->'%(filename)')"/>
        <Message Text="directory: @(Schema->'%(directory)')"/>
        <Message Text="relativedir: @(Schema->'%(relativedir)')"/>
        <Message Text="extension: @(Schema->'%(extension)')"/>
    </Target>
</Project>

O exemplo produz a seguinte saída:

rootdir: C:\
fullpath: C:\sub0\sub1\sub2\sub3\myfile.xsd
rootdir + directory + filename + extension: C:\sub0\sub1\sub2\sub3\myfile.xsd
identity: sub1\sub2\sub3\myfile.xsd
filename: myfile
directory: sub0\sub1\sub2\sub3\
relativedir: sub1\sub2\sub3\
extension: .xsd