Compartilhar via


Compilações incrementais

As compilações incrementais do MSBuild são compilações otimizadas para que os alvos que tenham arquivos de saída atualizados em relação aos arquivos de entrada correspondentes não sejam executados.

Um elemento de destino pode ter um atributo Inputs, que indica quais itens o destino espera como entrada e um atributo Outputs, que indica quais itens ele produz como saída. O MSBuild tenta localizar um mapeamento um-para-um entre os valores desses atributos. Se esse mapeamento existir, o MSBuild comparará o carimbo de data/hora de cada item de entrada com o carimbo de data/hora do item de saída correspondente. Os arquivos de saída que não têm um mapeamento um-para-um são comparados a todos os arquivos de entrada. Um item é considerado up-to-date se o arquivo de saída for da mesma idade ou mais recente que o arquivo de entrada ou os arquivos.

Nota

Quando o MSBuild avalia os arquivos de entrada, somente o conteúdo da lista na execução atual é considerado. As alterações na lista da última compilação não tornam automaticamente um alvo desatualizado.

Se todos os itens de saída estiverem atualizados, o MSBuild ignorará o destino. Essa compilação incremental do destino pode melhorar significativamente a velocidade da compilação. Se apenas alguns arquivos forem up-to-date, o MSBuild executará o alvo, mas ignorará os itens marcados como up-to-date e, portanto, processará todos os itens up-to-date. Esse processo é conhecido como uma compilação incremental parcial.

Os mapeamentos um para um só podem ser produzidos tornando o atributo Outputs uma transformação do atributo Inputs. Para obter mais informações, consulte Transformações do MSBuild.

Considere o seguinte alvo:

<Target Name="Backup" Inputs="@(Compile)"
    Outputs="@(Compile->'$(BackupFolder)%(Identity).bak')">
    <Copy SourceFiles="@(Compile)" DestinationFiles=
        "@(Compile->'$(BackupFolder)%(Identity).bak')" />
</Target>

O conjunto de arquivos representado pelo tipo de item Compile é copiado para um diretório de backup. Os arquivos de backup têm a extensão de arquivo .bak. Se os arquivos representados pelo tipo de item Compile ou os arquivos de backup correspondentes não forem excluídos ou modificados após a execução do destino Backup, o destino Backup será ignorado nos builds subsequentes.

Inferência de saída

O MSBuild compara os atributos Inputs e Outputs de um destino para determinar se o destino precisa ser executado. O ideal é que o conjunto de arquivos que existe após a conclusão de um build incremental permaneça o mesmo se os destinos associados forem executados ou não. Como propriedades e itens que as tarefas criam ou alteram podem afetar a compilação, o MSBuild deve inferir seus valores mesmo se o destino que as afeta seja ignorado. Esse processo é conhecido como inferência de saída.

Há três casos:

  • O destino tem um atributo Condition que é avaliado como false. Nesse caso, o destino não é executado e não possui efeitos na compilação.

  • O destino tem saídas desatualizadas e é executado para atualizá-las.

  • O destino não tem saídas desatualizadas e é ignorado. O MSBuild avalia o destino e faz alterações nos itens e propriedades como se o destino tivesse sido executado.

Para dar suporte à compilação incremental, as tarefas devem garantir que o valor do atributo TaskParameter de qualquer elemento Output seja igual a um parâmetro de entrada de tarefa. Por exemplo:

<CreateProperty Value="123">
    <Output PropertyName="Easy" TaskParameter="Value" />
</CreateProperty>

Esse código cria a propriedade Easy, que tem o valor 123 se o destino é executado ou ignorado.

A partir do MSBuild 3.5, a inferência de saída é executada automaticamente em grupos de itens e propriedades em um destino. As tarefas CreateItem não são necessárias em um destino e devem ser evitadas. Além disso, as tarefas CreateProperty devem ser usadas em um destino apenas para determinar se um destino foi executado.

Antes do MSBuild 3.5, você pode usar a tarefa CreateItem.

Determinar se um alvo foi executado

Por causa da inferência de saída, você deve examinar as propriedades e os itens de um destino para determinar se o destino foi executado. Para fazer isso, adicione a tarefa CreateProperty ao destino e atribua-lhe um elemento Output cujo TaskParameter é ValueSetByTask. Por exemplo:

<CreateProperty Value="true">
    <Output TaskParameter="ValueSetByTask" PropertyName="CompileRan" />
</CreateProperty>

Esse código cria a propriedade CompileRan e dá a ela o valor true, mas somente se o alvo for executado. Se o destino for ignorado, CompileRan não será criado.