Tutorial: usar o MSBuild

O MSBuild é a plataforma de build da Microsoft e do Visual Studio. Este tutorial apresenta os blocos de criação do MSBuild e mostra como gravar, manipular e depurar projetos do MSBuild. Você saberá mais sobre:

  • Criar e manipular um arquivo de projeto.

  • Como usar as propriedades de build.

  • Usar itens de build.

Você pode executar o MSBuild no Visual Studio ou na janela Comando. Neste tutorial, você deve criar um arquivo de projeto do MSBuild utilizando o Visual Studio. Você editará o arquivo de projeto no Visual Studio e usará a janela Comando para compilar o projeto e examinar os resultados.

Instalar o MSBuild

Se você tiver o Visual Studio, já terá o MSBuild instalado. Com o Visual Studio 2019 e posterior, ele é instalado na pasta de instalação do Visual Studio. Para uma instalação padrão típica no Windows 10, MSBuild.exe está na pasta de instalação no MSBuild\Current\Bin.

No instalador, verifique se as ferramentas do MSBuild para as cargas de trabalho que você usa estão selecionadas e escolha Instalar.

Installing MSBuild

Para instalar o MSBuild em um sistema que não tem o Visual Studio, acesse Ferramentas de Build para Visual Studio 2019 ou instale o .NET SDK.

Se você tiver o Visual Studio, já terá o MSBuild instalado. Com o Visual Studio 2022, ele é instalado na pasta de instalação do Visual Studio. Para uma instalação padrão típica no Windows 10, MSBuild.exe está na pasta de instalação no MSBuild\Current\Bin.

No instalador do Visual Studio, navegue até Componentes Individuais e localize a caixa de seleção do MSBuild. Ele é selecionada automaticamente quando você escolhe qualquer uma das outras cargas de trabalho para instalar.

Para instalar o MSBuild em um sistema que não tem o Visual Studio, acesse Ferramentas de Build para Visual Studio 2022 na página de downloads. Outra maneira de obter o MSBuild é instalar o SDK do .NET.

Criar um projeto do MSBuild

O sistema de projetos do Visual Studio é baseado no MSBuild. É fácil criar um arquivo de projeto usando o Visual Studio. Nesta seção, crie um arquivo de projeto em C#. Você também poderá escolher criar um arquivo de projeto do Visual Basic. No contexto deste tutorial, a diferença entre os dois arquivos do projeto é secundária.

Para criar um arquivo de projeto

  1. Abra o Visual Studio e crie um projeto:

    Na caixa de pesquisa, digite winforms e, em seguida, escolha Criar um novo aplicativo do Windows Forms (.NET Framework). Na caixa de diálogo que aparece, escolha Criar.

    Na caixa Nome do projeto, digite BuildApp. Insira um Local para a solução, por exemplo, D:\.

  2. Clique em OK ou Criar para criar o arquivo de projeto.

Examinar o arquivo de projeto

Na seção anterior, você usou o Visual Studio para criar um arquivo de projeto em C#. O arquivo de projeto é representado no Gerenciador de Soluções pelo nó de projeto chamado BuildApp. Você pode usar o editor de códigos do Visual Studio para examinar o arquivo de projeto.

Para examinar o arquivo de projeto

  1. No Gerenciador de Soluções, clique no nó do projeto BuildApp.

  2. No navegador Propriedades, observe que a propriedade de Arquivo de Projeto é BuildApp.csproj. Todos os arquivos de projeto são nomeados com o sufixo proj. Se você tivesse criado um projeto do Visual Basic, o nome do arquivo de projeto seria BuildApp.vbproj.

  3. Clique com o botão direito do mouse no nó de projeto novamente e clique em Editar BuildApp.csproj.

    O arquivo de projeto aparecerá no editor de códigos.

Observação

Para alguns tipos de projeto, como C++, você precisa descarregar o projeto (clique com o botão direito do mouse no arquivo de projeto e escolha Descarregar projeto) antes de abrir e editar o arquivo de projeto.

Destinos e tarefas

Os arquivos de projeto são arquivos formatados em XML com o nó raiz Project.

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0"  xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

A maioria dos projetos do .NET tem um atributo Sdk. Esses projetos são chamados de projetos no estilo SDK.

<Project Sdk="Microsoft.NET.Sdk">

Existem muitas variações de SDKs do .NET para fins especiais; elas são descritas em SDKs do Projeto do .NET.

O trabalho de compilar um aplicativo é feito com os elementos Target e Task.

  • Uma tarefa é a menor unidade de trabalho ou, em outras palavras, é o "átomo" de um build. As tarefas são componentes executáveis independentes, que podem ter entradas e saídas. Não existem tarefas referenciadas ou definidas no arquivo de projeto no momento. Você deve adicionar tarefas ao arquivo do projeto nas seções a seguir. Para obter mais informações, consulte Tarefas.

  • Um destino é uma sequência nomeada de tarefas. Pode ser uma sequência nomeada de tarefas, mas, criticamente, representa algo a ser criado ou feito, devendo, portanto, ser definido de uma maneira orientada a metas. Para obter mais informações, consulte Destinos.

O destino padrão não está definido no arquivo de projeto. Em vez disso, ele é especificado em projetos importados. O elemento Import especifica projetos importados. Por exemplo, em um projeto C#, o destino padrão é importado do arquivo Microsoft.CSharp.targets.

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

Os arquivos importados são efetivamente inseridos no arquivo do projeto em qualquer lugar em que forem referenciados.

Em projetos no estilo SDK, você não vê esse elemento de importação, pois o atributo SDK faz com que esse arquivo seja importado implicitamente.

O MSBuild controla os destinos de um build e garante que cada destino seja compilado não mais de uma vez.

Adicionar um destino e uma tarefa

Adicione um destino ao arquivo de projeto. Adicionar uma tarefa ao destino que imprime uma mensagem.

Para adicionar um destino e uma tarefa

  1. Adicione essas linhas ao arquivo de projeto, logo após a instrução Import ou o elemento project de abertura.

    <Target Name="HelloWorld">
    </Target>
    

    Esse código cria um destino chamado HelloWorld. Observe que você tem suporte ao IntelliSense ao editar o arquivo de projeto.

  2. Adicione linhas ao destino HelloWorld de modo que a seção resultante tenha esta aparência:

    <Target Name="HelloWorld">
      <Message Text="Hello"></Message>  <Message Text="World"></Message>
    </Target>
    
  3. Salve o arquivo de projeto.

A tarefa Message é uma das muitas tarefas fornecidas com o MSBuild. Para obter uma lista completa das tarefas disponíveis e informações de uso, confira Referência de tarefas.

A tarefa Message usa o valor de cadeia de caracteres do atributo Text como entrada e o exibe no dispositivo de saída (ou grava-o em um ou mais registros, se aplicável). O destino HelloWorld executa a tarefa Mensagem duas vezes: primeiro para exibir "Olá" e depois para exibir "Mundo."

Compilar o destino

Se você tentar criar esse projeto no Visual Studio, ele não criará o destino que você definiu. Isso ocorre porque o Visual Studio escolhe o destino padrão, que ainda é aquele no arquivo .targets importado.

Execute o MSBuild no Prompt de Comando do Desenvolvedor do Visual Studio para criar o destino HelloWorld definido previamente. Use a opção de linha de comando -target ou -t para selecionar o destino.

Observação

Nas seções a seguir, vamos nos referir ao Prompt de Comando do Desenvolvedor como Janela de Comando.

Para compilar o destino:

  1. Abra a janela Comando.

    Na caixa de pesquisa na barra de tarefas, comece a digitar o nome da ferramenta, como dev ou developer command prompt. Isso abre uma lista de aplicativos instalados que correspondem ao seu padrão de pesquisa.

    Se você precisar encontrá-lo manualmente, o arquivo é LaunchDevCmd.bat na pasta {pasta de instalação do Visual Studio}\Common7\Tools.

  2. Na janela Comando, acesse a pasta que contém o arquivo de projeto, a qual, neste caso, é D:\BuildApp\BuildApp.

  3. Execute msbuild com a opção de comando -t:HelloWorld. Esse comando seleciona e cria o destino HelloWorld:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Examine a saída na janela Comando. Você deverá ver as duas linhas "Hello" e "World":

    Hello
    World
    

Observação

Se em vez disso aparecer The target "HelloWorld" does not exist in the project, será porque você provavelmente se esqueceu de salvar o arquivo de projeto no editor de códigos. Salve o arquivo e tente novamente.

Ao alternar entre o editor de códigos e a janela Comando, você poderá alterar o arquivo de projeto e ver os resultados rapidamente.

Compilar propriedades

As propriedades de build são pares nome-valor que guiam o build. Várias propriedades de build já estão definidas na parte superior do arquivo de projeto:

<PropertyGroup>
...
  <ProductVersion>10.0.11107</ProductVersion>
  <SchemaVersion>2.0</SchemaVersion>
  <ProjectGuid>{30E3C9D5-FD86-4691-A331-80EA5BA7E571}</ProjectGuid>
  <OutputType>WinExe</OutputType>
...
</PropertyGroup>

Todas as propriedades são elementos filho dos elementos PropertyGroup. O nome da propriedade é o nome do elemento filho e o valor da propriedade é o elemento de texto do elemento filho. Por exemplo,

<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>

define a propriedade denominada TargetFrameworkVersion, dando a ela o valor de cadeia de caracteres "v4.5."

As propriedades de criação podem ser redefinidas a qualquer momento. Se

<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>

aparece posteriormente no arquivo do projeto ou em um arquivo importado posteriormente no arquivo do projeto, então TargetFrameworkVersion assume o novo valor "v3.5."

Examinar um valor da propriedade

Para obter o valor de uma propriedade, use a seguinte sintaxe, em que PropertyName é o nome da propriedade:

$(PropertyName)

Use essa sintaxe para examinar algumas das propriedades no arquivo de projeto.

Para examinar um valor da propriedade

  1. No editor de códigos, substitua o destino HelloWorld por este código:

    <Target Name="HelloWorld">
      <Message Text="Configuration is $(Configuration)" />
      <Message Text="MSBuildToolsPath is $(MSBuildToolsPath)" />
    </Target>
    
  2. Salve o arquivo de projeto.

  3. Na janela Comando, digite e execute esta linha:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Examine a saída. Você deve ver essas duas linhas (sua saída pode ser diferente):

    Configuration is Debug
    MSBuildToolsPath is C:\Program Files\Microsoft Visual Studio\2022\MSBuild\Current\Bin\amd64
    
    Configuration is Debug
    MSBuildToolsPath is C:\Program Files (x86)\Microsoft Visual Studio\2019\MSBuild\16.0\Bin
    

Propriedades condicionais

Muitas propriedades, como Configuration, são definidas condicionalmente, ou seja, o atributo Condition aparece no elemento da propriedade. As propriedades condicionais são definidas ou redefinidas somente se a condição for avaliada como "verdadeira." As propriedades não definidas recebem o valor padrão de uma cadeia de caracteres vazia. Por exemplo,

<Configuration   Condition=" '$(Configuration)' == '' ">Debug</Configuration>

significa "Se a propriedade Configuration ainda não tiver sido definida, defina-a e dê a ela o valor 'Depuração'."

Quase todos os elementos do MSBuild podem ter um atributo Condition. Para mais discussões sobre como usar o atributo Condition, consulte Condições.

Propriedades reservadas

O MSBuild reserva alguns nomes de propriedade para armazenar informações sobre o arquivo de projeto e os binários do MSBuild. MSBuildToolsPath é um exemplo de uma propriedade reservada. As propriedades reservadas são referenciadas com a notação $ como qualquer outra propriedade. Para saber mais, confira Como referenciar o nome ou o local do arquivo de projeto e Propriedades reservadas e conhecidas do MSBuild.

Variáveis de ambiente

Você pode referenciar variáveis de ambiente em arquivos de projeto da mesma maneira que as propriedades de build. Por exemplo, para usar a variável de ambiente PATH em seu arquivo de projeto, use $(Path). Se o projeto contiver uma definição de propriedade que tem o mesmo nome que uma variável de ambiente, a propriedade no projeto substituirá o valor da variável de ambiente. Para saber mais, confira Como usar variáveis de ambiente em um build.

Definir propriedades na linha de comando

As propriedades podem ser definidas na linha de comando utilizando a alternância de linha de comando -property ou -p. Os valores das propriedades recebidos da linha de comando substituem os valores das propriedades definidos no arquivo de projeto e nas variáveis de ambiente.

Para definir um valor da propriedade da linha de comando:

  1. Na janela Comando, digite e execute esta linha:

    msbuild buildapp.csproj -t:HelloWorld -p:Configuration=Release
    
  2. Examine a saída. Você deverá ver esta linha:

    Configuration is Release.
    

O MSBuild cria a propriedade Configuração e dá a ela o valor "Versão."

Caracteres especiais

Determinados caracteres têm significado especial em arquivos de projeto do MSBuild. O ponto e vírgula (;) e o asterisco (*) são exemplos desses caracteres. Para usar esses caracteres especiais como literais em um arquivo de projeto, eles devem ser especificados usando a sintaxe %<xx>, em que <xx> representa o valor hexadecimal ASCII do caractere.

Altere a tarefa Message para mostrar o valor da propriedade Configuration com caracteres especiais para torná-la mais legível.

Para usar caracteres especiais na tarefa Message:

  1. No editor de códigos, substitua ambas as tarefas Message por esta linha:

    <Message Text="%24(Configuration) is %22$(Configuration)%22" />
    
  2. Salve o arquivo de projeto.

  3. Na janela Comando, digite e execute esta linha:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Examine a saída. Você deverá ver esta linha:

    $(Configuration) is "Debug"
    

Para saber mais, confira Caracteres especiais no MSBuild.

Compilar itens

Um item é uma informação, normalmente um nome de arquivo, que é usado como entrada no sistema de build. Por exemplo, uma coleção de itens que representam os arquivos de origem pode ser passada para uma tarefa chamada Compile para compilá-los em um assembly.

Todos os itens são elementos filho dos elementos ItemGroup. O nome do item é o nome do elemento filho e o valor do item é o valor do atributo Include do elemento filho. Os valores dos itens com o mesmo nome são coletados em tipos de item do nome. Por exemplo,

<ItemGroup>
    <Compile Include="Program.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>

define um grupo de itens que contém dois itens. O tipo de item Compile tem dois valores: Program.cs e Properties\AssemblyInfo.cs.

O código a seguir cria o mesmo tipo de item declarando os dois arquivos em um atributo Include, separados por ponto e vírgula.

<ItemGroup>
    <Compile Include="Program.cs;Properties\AssemblyInfo.cs" />
</ItemGroup>

Para obter mais informações, consulte Itens.

Observação

Os caminhos de arquivo são relativos à pasta que contém o arquivo de projeto do MSBuild, mesmo que o arquivo de projeto seja um arquivo de projeto importado. Há algumas exceções a isso, como ao usar elementos Import e UsingTask.

Examinar os valores de tipo de item

Para obter os valores de um tipo de item, use a seguinte sintaxe, em que ItemType é o nome do tipo de item:

@(ItemType)

Use essa sintaxe para examinar o tipo de item Compile no arquivo de projeto.

Para examinar os valores de tipo de item:

  1. No editor de códigos, substitua a tarefa do destino HelloWorld por este código:

    <Target Name="HelloWorld">
      <Message Text="Compile item type contains @(Compile)" />
    </Target>
    
  2. Salve o arquivo de projeto.

  3. Na janela Comando, digite e execute esta linha:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Examine a saída. Você deverá ver esta linha longa:

    Compile item type contains Form1.cs;Form1.Designer.cs;Program.cs;Properties\AssemblyInfo.cs;Properties\Resources.Designer.cs;Properties\Settings.Designer.cs
    

Por padrão, os valores de um tipo de item são separados por ponto e vírgula.

Para alterar o separador de um tipo de item, use a seguinte sintaxe, em que ItemType é o tipo de item e Separator é uma cadeia de caracteres de um ou mais caracteres de separação:

@(ItemType, Separator)

Altere a tarefa Message para usar retornos de carro e alimentações de linha (%0A%0D) para exibir os itens Compile em linhas individuais.

Para exibir os valores de tipo de item em linhas individuais

  1. No editor de códigos, substitua a tarefa Message por esta linha:

    <Message Text="Compile item type contains @(Compile, '%0A%0D')" />
    
  2. Salve o arquivo de projeto.

  3. Na janela Comando, digite e execute esta linha:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Examine a saída. Você deverá ver estas linhas:

    Compile item type contains Form1.cs
    Form1.Designer.cs
    Program.cs
    Properties\AssemblyInfo.cs
    Properties\Resources.Designer.cs
    Properties\Settings.Designer.cs
    

Incluir, excluir e curingas

Você pode usar os curingas "*", "**" e "?" com o atributo Include para adicionar itens a um tipo de item. Por exemplo,

<Photos Include="images\*.jpeg" />

adiciona todos os arquivos com a extensão de arquivo .jpeg na pasta de imagens ao tipo de item Photos, enquanto

<Photos Include="images\**\*.jpeg" />

adiciona todos os arquivos com a extensão de arquivo .jpeg na pasta de imagens, juntamente com todas as subpastas, ao tipo de item Photos. Para obter mais exemplos, confira Como selecionar os arquivos para compilação.

Observe que, à medida que os itens são declarados, eles são adicionados ao tipo de item. Por exemplo,

<Photos Include="images\*.jpeg" />
<Photos Include="images\*.gif" />

cria um tipo de item chamado Foto que contém todos os arquivos na pasta imagens com uma extensão de arquivo .jpeg ou .gif. Essas linhas são equivalentes à linha a seguir:

<Photos Include="images\*.jpeg;images\*.gif" />

Você pode excluir um item de um tipo de item com o atributo Exclude. Por exemplo,

<Compile Include="*.cs" Exclude="*Designer*">

adiciona todos os arquivos com a extensão de arquivo .cs ao tipo de item Compile, exceto os arquivos cujos nomes contêm a cadeia de caracteres Designer. Para obter mais exemplos, confira Como excluir arquivos do build.

O atributo Exclude afeta apenas os itens adicionados pelo atributo Include no elemento item que contém ambos. Por exemplo,

<Compile Include="*.cs" />
<Compile Include="*.res" Exclude="Form1.cs">

não excluiria o arquivo Form1.cs, que foi adicionado no elemento de item anterior.

Para incluir e excluir itens

  1. No editor de códigos, substitua a tarefa Message por esta linha:

    <Message Text="XFiles item type contains @(XFiles)" />
    
  2. Adicione esse grupo de itens logo após o elemento Import:

    <ItemGroup>
       <XFiles Include="*.cs;properties/*.resx" Exclude="*Designer*" />
    </ItemGroup>
    
  3. Salve o arquivo de projeto.

  4. Na janela Comando, digite e execute esta linha:

    msbuild buildapp.csproj -t:HelloWorld
    
  5. Examine a saída. Você deverá ver esta linha:

    XFiles item type contains Form1.cs;Program.cs;Properties/Resources.resx
    

Metadados do item

Os itens podem conter metadados além das informações coletadas dos atributos Include e Exclude. As tarefas que exigem mais informações sobre os itens ao invés de apenas o valor do item, podem utilizar esses metadados.

Os metadados de item são declarados no arquivo de projeto criando um elemento com o nome dos metadados como um elemento filho do item. Um item pode ter zero ou mais valores de metadados. Por exemplo, o seguinte item CSFile tem metadados Culture com um valor de "Fr":

<ItemGroup>
    <CSFile Include="main.cs">
        <Culture>Fr</Culture>
    </CSFile>
</ItemGroup>

Para obter o valor dos metadados de um tipo de item, use a seguinte sintaxe, em que ItemType é o nome do tipo de item e MetaDataName é o nome dos metadados:

%(ItemType.MetaDataName)

Para examinar metadados de item:

  1. No editor de códigos, substitua a tarefa Message por esta linha:

    <Message Text="Compile.DependentUpon: %(Compile.DependentUpon)" />
    
  2. Salve o arquivo de projeto.

  3. Na janela Comando, digite e execute esta linha:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Examine a saída. Você deverá ver estas linhas:

    Compile.DependentUpon:
    Compile.DependentUpon: Form1.cs
    Compile.DependentUpon: Resources.resx
    Compile.DependentUpon: Settings.settings
    

Observe que "Compile.DependentUpon" aparece várias vezes. O uso de metadados com essa sintaxe em um destino causa o "envio em lote." Envio em lote significa que as tarefas no destino são executadas uma vez para cada valor exclusivo dos metadados. O envio em lote é o equivalente do script do MSBuild do constructo de programação comum "foreach loop". Para obter mais informações, consulte Envio em lote.

Metadados conhecidos

Sempre que um item é adicionado a uma lista de itens, esse item recebe alguns metadados conhecidos. Por exemplo, %(Filename) retorna o nome de arquivo de qualquer item. Para obter uma lista completa dos metadados conhecidos, consulte Metadados de itens conhecidos.

Para examinar os metadados conhecidos:

  1. No editor de códigos, substitua a tarefa Message por esta linha:

    <Message Text="Compile Filename: %(Compile.Filename)" />
    
  2. Salve o arquivo de projeto.

  3. Na janela Comando, digite e execute esta linha:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Examine a saída. Você deverá ver estas linhas:

    Compile Filename: Form1
    Compile Filename: Form1.Designer
    Compile Filename: Program
    Compile Filename: AssemblyInfo
    Compile Filename: Resources.Designer
    Compile Filename: Settings.Designer
    

Ao comparar os dois exemplos anteriores, você pode ver que, embora nem todos os itens do tipo de item Compilar tenham metadados DependentUpon, todos os itens têm os conhecidos metadados Filename.

Transformações de metadados

As listas de itens podem ser transformadas em novas listas de itens. Para transformar uma lista de itens, use a seguinte sintaxe, em que <ItemType> é o nome do tipo de item e <MetadataName> é o nome dos metadados:

@(ItemType -> '%(MetadataName)')

Por exemplo, uma lista de itens dos arquivos de origem pode ser transformada em uma coleção de arquivos-objeto usando uma expressão como @(SourceFiles -> '%(Filename).obj'). Para obter mais informações, consulte Transformações.

Para transformar itens que usam metadados:

  1. No editor de códigos, substitua a tarefa Message por esta linha:

    <Message Text="Backup files: @(Compile->'%(filename).bak')" />
    
  2. Salve o arquivo de projeto.

  3. Na janela Comando, digite e execute esta linha:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Examine a saída. Você deverá ver esta linha:

    Backup files: Form1.bak;Form1.Designer.bak;Program.bak;AssemblyInfo.bak;Resources.Designer.bak;Settings.Designer.bak
    

Observe que os metadados expressos nessa sintaxe não são causam o envio em lote.

Próximas etapas

Para saber como criar um arquivo de projeto simples, uma etapa de cada vez, no Windows, experimente Criar um arquivo de projeto no MSBuild do zero.

Se estiver usando principalmente o SDK do .NET, continue lendo em Referência do MSBuild para projetos do SDK do .NET.