Noções básicas sobre o arquivo de projeto

por Jason Lee

os arquivos de projeto do Microsoft Build Engine (MSBuild) estão no centro do processo de compilação e implantação. Este tópico começa com uma visão geral conceitual do MSBuild e do arquivo de projeto. Ele descreve os principais componentes que você encontrará ao trabalhar com arquivos de projeto e funciona por meio de um exemplo de como você pode usar arquivos de projeto para implantar aplicativos do mundo real.

O que você aprenderá:

  • Como o MSBuild usa arquivos de projeto do MSBuild para criar projetos.
  • Como o MSBuild se integra às tecnologias de implantação, como a Ferramenta de Implantação da Web (Implantação da Web) dos Serviços de Informações da Internet (IIS).
  • Como entender os principais componentes de um arquivo de projeto.
  • Como você pode usar arquivos de projeto para criar e implantar aplicativos complexos.

MSBuild e o arquivo de projeto

Quando você cria e cria soluções no Visual Studio, o Visual Studio usa o MSBuild para criar cada projeto em sua solução. Cada projeto do Visual Studio inclui um arquivo de projeto do MSBuild, com uma extensão de arquivo que reflete o tipo de projeto , por exemplo, um projeto C# (.csproj), um projeto do Visual Basic.NET (.vbproj) ou um projeto de banco de dados (.dbproj). Para criar um projeto, o MSBuild deve processar o arquivo de projeto associado ao projeto. O arquivo de projeto é um documento XML que contém todas as informações e instruções de que o MSBuild precisa para criar seu projeto, como o conteúdo a ser incluído, os requisitos da plataforma, as informações de controle de versão, as configurações do servidor Web ou do servidor de banco de dados e as tarefas que devem ser executadas.

Os arquivos de projeto do MSBuild são baseados no esquema XML do MSBuild e, como resultado, o processo de build é totalmente aberto e transparente. Além disso, você não precisa instalar o Visual Studio para usar o mecanismo do MSBuild– o executável do MSBuild.exe faz parte do .NET Framework e pode executá-lo em um prompt de comando. Como desenvolvedor, você pode criar seus próprios arquivos de projeto do MSBuild, usando o esquema XML do MSBuild, para impor um controle sofisticado e refinado sobre como seus projetos são criados e implantados. Esses arquivos de projeto personalizados funcionam exatamente da mesma maneira que os arquivos de projeto que o Visual Studio gera automaticamente.

Observação

Você também pode usar arquivos de projeto do MSBuild com o serviço team build no TFS (Team Foundation Server). Por exemplo, você pode usar arquivos de projeto em cenários de CI (integração contínua) para automatizar a implantação em um ambiente de teste quando o novo código é verificado. Para obter mais informações, consulte Configurando o Team Foundation Server para implantação automatizada da Web.

Convenções de nomenclatura de arquivo de projeto

Ao criar seus próprios arquivos de projeto, você pode usar qualquer extensão de arquivo desejada. No entanto, para facilitar a compreensão de suas soluções para outras pessoas, você deve usar estas convenções comuns:

  • Use a extensão .proj ao criar um arquivo de projeto que compila projetos.
  • Use a extensão .targets ao criar um arquivo de projeto reutilizável para importar para outros arquivos de projeto. Arquivos com uma extensão .targets normalmente não criam nada sozinhos, eles simplesmente contêm instruções que você pode importar para seus arquivos .proj.

Integração com tecnologias de implantação

Se você trabalhou com projetos de aplicativo Web no Visual Studio 2010, como ASP.NET aplicativos Web e aplicativos Web ASP.NET MVC, saberá que esses projetos incluem suporte interno para empacotamento e implantação do aplicativo Web em um ambiente de destino. As páginas Propriedades desses projetos incluem as guias Pacote/Publicar Web e Pacote/Publicar SQL que você pode usar para configurar como os componentes do aplicativo são empacotados e implantados. Isso mostra a guia Pacote/Publicar Web :

A guia Pacote/Publicar Web

A tecnologia subjacente por trás desses recursos é conhecida como WPP (Pipeline de Publicação na Web). Essencialmente, o WPP reúne o MSBuild e a Implantação da Web para fornecer um processo completo de compilação, pacote e implantação para seus aplicativos Web.

A boa notícia é que você pode aproveitar os pontos de integração que o WPP fornece ao criar arquivos de projeto personalizados para projetos Web. Você pode incluir instruções de implantação no arquivo de projeto, o que permite criar seus projetos, criar pacotes de implantação da Web e instalar esses pacotes em servidores remotos por meio de um único arquivo de projeto e uma única chamada para o MSBuild. Você também pode chamar outros executáveis como parte do processo de build. Por exemplo, você pode executar a ferramenta de linha de comando VSDBCMD.exe para implantar um banco de dados de um arquivo de esquema. Ao longo deste tópico, você verá como aproveitar esses recursos para atender aos requisitos de seus cenários de implantação empresarial.

Observação

Para obter mais informações sobre como o processo de implantação de aplicativo Web funciona, consulte Visão geral ASP.NET implantação de projeto de aplicativo Web.

A anatomia de um arquivo de projeto

Antes de examinar o processo de build com mais detalhes, vale a pena levar alguns instantes para se familiarizar com a estrutura básica de um arquivo de projeto do MSBuild. Esta seção fornece uma visão geral dos elementos mais comuns que você encontrará ao examinar, editar ou criar um arquivo de projeto. Em particular, você aprenderá:

  • Como usar propriedades para gerenciar variáveis para o processo de build.
  • Como usar itens para identificar as entradas para o processo de build, como arquivos de código.
  • Como usar destinos e tarefas para fornecer instruções de execução ao MSBuild, usando propriedades e itens definidos em outro lugar no arquivo de projeto.

Isso mostra a relação entre os principais elementos em um arquivo de projeto do MSBuild:

A relação entre os principais elementos em um arquivo de projeto do MSBuild.

O elemento Project

O elemento Project é o elemento raiz de cada arquivo de projeto. Além de identificar o esquema XML para o arquivo de projeto, o elemento Project pode incluir atributos para especificar os pontos de entrada para o processo de build. Por exemplo, na solução de exemplo do Contact Manager, o arquivo Publish.proj especifica que o build deve começar chamando o destino chamado FullPublish.

<Project ToolsVersion="4.0" DefaultTargets="FullPublish" 
         xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  
</Project>

Propriedades e condições

Um arquivo de projeto normalmente precisa fornecer muitas informações diferentes para compilar e implantar seus projetos com êxito. Essas informações podem incluir nomes de servidor, cadeias de conexão, credenciais, configurações de build, caminhos de arquivo de origem e destino e quaisquer outras informações que você deseja incluir para dar suporte à personalização. Em um arquivo de projeto, as propriedades devem ser definidas dentro de um elemento PropertyGroup . As propriedades do MSBuild consistem em pares chave-valor. Dentro do elemento PropertyGroup , o nome do elemento define a chave de propriedade e o conteúdo do elemento define o valor da propriedade. Por exemplo, você pode definir propriedades chamadas ServerName e ConnectionString para armazenar um nome de servidor estático e cadeia de conexão.

<PropertyGroup>    
   <ServerName>FABRIKAM\TEST1</ServerName>
   <ConnectionString>
     Data Source=FABRIKAM\TESTDB;InitialCatalog=ContactManager,...
   </ConnectionString>
</PropertyGroup>

Para recuperar um valor de propriedade, use o formato $(PropertyName). Por exemplo, para recuperar o valor da propriedade ServerName , você digitaria:

$(ServerName)

Observação

Você verá exemplos de como e quando usar valores de propriedade posteriormente neste tópico.

Inserir informações como propriedades estáticas em um arquivo de projeto nem sempre é a abordagem ideal para gerenciar o processo de build. Em muitos cenários, você desejará obter as informações de outras fontes ou capacitar o usuário a fornecer as informações do prompt de comando. O MSBuild permite que você especifique qualquer valor de propriedade como um parâmetro de linha de comando. Por exemplo, o usuário pode fornecer um valor para ServerName quando ele executar MSBuild.exe na linha de comando.

msbuild.exe Publish.proj /p:ServerName=FABRIKAM\TESTWEB1

Observação

Para obter mais informações sobre os argumentos e opções que você pode usar com MSBuild.exe, consulte Referência de linha de comando do MSBuild.

Você pode usar a mesma sintaxe de propriedade para obter os valores de variáveis de ambiente e propriedades internas do projeto. Muitas propriedades comumente usadas são definidas para você e você pode usá-las em seus arquivos de projeto incluindo o nome do parâmetro relevante. Por exemplo, para recuperar a plataforma de projeto atual, por exemplo, x86 ou AnyCpu, você pode incluir a referência de propriedade $(Platform) no arquivo de projeto. Para obter mais informações, consulte Macros para comandos e propriedades de build, Propriedades comuns do projeto do MSBuild e Propriedades Reservadas.

As propriedades geralmente são usadas em conjunto com as condições. A maioria dos elementos do MSBuild dá suporte ao atributo Condition , que permite especificar os critérios sobre os quais o MSBuild deve avaliar o elemento. Por exemplo, considere esta definição de propriedade:

<PropertyGroup>
   <OutputRoot Condition=" '$(OutputRoot)'=='' ">..\Publish\Out\</OutputRoot>
   ...
</PropertyGroup>

Quando o MSBuild processa essa definição de propriedade, ele primeiro verifica se um valor de propriedade $(OutputRoot) está disponível. Se o valor da propriedade estiver em branco, em outras palavras, o usuário não forneceu um valor para essa propriedade, a condição será avaliada como true e o valor da propriedade será definido como .. \Publish\Out. Se o usuário tiver fornecido um valor para essa propriedade, a condição será avaliada como false e o valor da propriedade estática não será usado.

Para obter mais informações sobre as diferentes maneiras pelas quais você pode especificar condições, consulte Condições do MSBuild.

Itens e Grupos de Itens

Uma das funções importantes do arquivo de projeto é definir as entradas para o processo de build. Normalmente, essas entradas são arquivos , arquivos de código, arquivos de configuração, arquivos de comando e quaisquer outros arquivos que você precisa processar ou copiar como parte do processo de build. No esquema de projeto do MSBuild, essas entradas são representadas pelos elementos Item . Em um arquivo de projeto, os itens devem ser definidos dentro de um elemento ItemGroup . Assim como os elementos Property , você pode nomear um elemento Item como desejar. No entanto, você deve especificar um atributo Include para identificar o arquivo ou curinga que o item representa.

<ItemGroup>
   <ProjectsToBuild Include="$(SourceRoot)ContactManager-WCF.sln"/>
</ItemGroup>

Ao especificar vários elementos Item com o mesmo nome, você está efetivamente criando uma lista nomeada de recursos. Uma boa maneira de ver isso em ação é dar uma olhada em um dos arquivos de projeto que o Visual Studio cria. Por exemplo, o arquivo ContactManager.Mvc.csproj na solução de exemplo inclui muitos grupos de itens, cada um com vários elementos item de nome idêntico.

<ItemGroup>
   <Reference Include="Microsoft.CSharp" />
   <Reference Include="System.Runtime.Serialization" />
   <Reference Include="System.ServiceModel" />
   ...
</ItemGroup>
<ItemGroup>
   <Compile Include="Controllers\AccountController.cs" />
   <Compile Include="Controllers\ContactsController.cs" />
   <Compile Include="Controllers\HomeController.cs" />
   ...
</ItemGroup>
<ItemGroup>
   <Content Include="Content\Custom.css" />
   <Content Include="CreateDatabase.sql" />
   <Content Include="DropDatabase.sql" />
   ...
</ItemGroup>

Dessa forma, o arquivo de projeto está instruindo o MSBuild a construir listas de arquivos que precisam ser processados da mesma maneira: a lista de referências inclui assemblies que devem estar em vigor para um build bem-sucedido, a lista Compilar inclui arquivos de código que devem ser compilados e a lista Conteúdo inclui recursos que devem ser copiados sem alterações. Examinaremos como o processo de build faz referência e usaremos esses itens mais adiante neste tópico.

Os elementos de item também podem incluir elementos filho ItemMetadata . Esses são pares chave-valor definidos pelo usuário e, essencialmente, representam propriedades específicas para esse item. Por exemplo, muitos dos elementos Compile item no arquivo de projeto incluem elementos filho DependentUpon .

<Compile Include="Global.asax.cs">
   <DependentUpon>Global.asax</DependentUpon>
</Compile>

Observação

Além dos metadados de item criados pelo usuário, todos os itens recebem vários metadados comuns na criação. Para obter mais informações, consulte Metadados de item conhecidos.

Você pode criar elementos ItemGroup dentro do elemento Project de nível raiz ou dentro de elementos Target específicos. Os elementos ItemGroup também dão suporte a atributos Condition, o que permite adaptar as entradas ao processo de build de acordo com condições como a configuração ou a plataforma do projeto.

Destinos e tarefas

No esquema do MSBuild, um elemento Task representa uma instrução de build individual (ou tarefa). O MSBuild inclui uma infinidade de tarefas predefinidas. Por exemplo:

  • A tarefa Copiar copia arquivos para um novo local.
  • A tarefa Csc invoca o compilador do Visual C#.
  • A tarefa VBC invoca o compilador do Visual Basic.
  • A tarefa Exec executa um programa especificado.
  • A tarefa Mensagem grava uma mensagem em um agente.

Observação

Para obter detalhes completos das tarefas que estão disponíveis prontas para uso, consulte Referência de tarefa do MSBuild. Para obter mais informações sobre tarefas, incluindo como criar suas próprias tarefas personalizadas, consulte Tarefas do MSBuild.

As tarefas sempre devem estar contidas nos elementos Target . Um elemento Target é um conjunto de uma ou mais tarefas executadas sequencialmente e um arquivo de projeto pode conter vários destinos. Quando você quiser executar uma tarefa ou um conjunto de tarefas, invoque o destino que as contém. Por exemplo, suponha que você tenha um arquivo de projeto simples que registra uma mensagem.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <Target Name="LogMessage">
      <Message Text="Hello world!" />
   </Target>
</Project>

Você pode invocar o destino da linha de comando usando a opção /t para especificar o destino.

msbuild.exe Publish.proj /t:LogMessage

Como alternativa, você pode adicionar um atributo DefaultTargets ao elemento Project para especificar os destinos que deseja invocar.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 
         DefaultTargets="FullPublish">
   <Target Name="LogMessage">
      <Message Text="Hello world!" />
   </Target>
</Project>

Nesse caso, você não precisa especificar o destino da linha de comando. Você pode simplesmente especificar o arquivo de projeto e o MSBuild invocará o destino FullPublish para você.

msbuild.exe Publish.proj

Os destinos e as tarefas podem incluir atributos condition . Dessa forma, você pode optar por omitir destinos inteiros ou tarefas individuais se determinadas condições forem atendidas.

Em geral, ao criar tarefas e destinos úteis, você precisará se referir às propriedades e itens que definiu em outro lugar no arquivo de projeto:

  • Para usar um valor de propriedade, digite $(PropertyName), em que PropertyName é o nome do elemento Property ou o nome do parâmetro.
  • Para usar um item, digite @(ItemName), em que ItemName é o nome do elemento Item .

Observação

Lembre-se de que, se você criar vários itens com o mesmo nome, estará criando uma lista. Por outro lado, se você criar várias propriedades com o mesmo nome, o último valor de propriedade fornecido substituirá todas as propriedades anteriores com o mesmo nome— uma propriedade só pode conter um único valor.

Por exemplo, no arquivo Publish.proj na solução de exemplo, dê uma olhada no destino BuildProjects .

<Target Name="BuildProjects" Condition=" '$(BuildingInTeamBuild)'!='true' ">
   <MSBuild Projects="@(ProjectsToBuild)"           
            Properties="OutDir=$(OutputRoot);
                        Configuration=$(Configuration);
                        DeployOnBuild=true;
                        DeployTarget=Package"
            Targets="Build" />
</Target>

Neste exemplo, você pode observar estes pontos-chave:

  • Se o parâmetro BuildingInTeamBuild for especificado e tiver um valor true, nenhuma das tarefas dentro desse destino será executada.

  • O destino contém uma única instância da tarefa do MSBuild . Essa tarefa permite que você crie outros projetos do MSBuild.

  • O item ProjectsToBuild é passado para a tarefa. Esse item pode representar uma lista de arquivos de projeto ou solução, tudo definido pelos elementos de item ProjectsToBuild dentro de um grupo de itens. Nesse caso, o item ProjectsToBuild refere-se a um único arquivo de solução.

    <ItemGroup>
       <ProjectsToBuild Include="$(SourceRoot)ContactManager-WCF.sln"/>
    </ItemGroup>
    
  • Os valores de propriedade passados para a tarefa do MSBuild incluem parâmetros chamados OutputRoot e Configuration. Eles serão definidos como valores de parâmetro se forem fornecidos ou valores de propriedade estáticos, se não forem.

    <PropertyGroup>
       ... 
       <Configuration Condition=" '$(Configuration)'=='' ">Release
       </Configuration>
       <OutputRoot Condition=" '$(OutputRoot)'=='' ">..\Publish\Out\
       </OutputRoot>
       ...
    </PropertyGroup>
    

Você também pode ver que a tarefa do MSBuild invoca um destino chamado Build. Esse é um dos vários destinos internos que são amplamente usados em arquivos de projeto do Visual Studio e estão disponíveis para você em seus arquivos de projeto personalizados, como Compilar, Limpar, Recompilar e Publicar. Você aprenderá mais sobre como usar destinos e tarefas para controlar o processo de build e sobre a tarefa do MSBuild em particular, mais adiante neste tópico.

Observação

Para obter mais informações sobre destinos, consulte Destinos do MSBuild.

Dividir arquivos de projeto para dar suporte a vários ambientes

Suponha que você queira implantar uma solução em vários ambientes, como servidores de teste, plataformas de preparo e ambientes de produção. A configuração pode variar substancialmente entre esses ambientes, não apenas em termos de nomes de servidor, cadeias de conexão e assim por diante, mas também potencialmente em termos de credenciais, configurações de segurança e muitos outros fatores. Se você precisar fazer isso regularmente, não é realmente conveniente editar várias propriedades no arquivo de projeto sempre que você alternar o ambiente de destino. Também não é uma solução ideal para exigir que uma lista infinita de valores de propriedade seja fornecida ao processo de build.

Felizmente há uma alternativa. O MSBuild permite dividir a configuração de build em vários arquivos de projeto. Para ver como isso funciona, na solução de exemplo, observe que há dois arquivos de projeto personalizados:

  • Publish.proj, que contém propriedades, itens e destinos comuns a todos os ambientes.
  • Env-Dev.proj, que contém propriedades específicas de um ambiente de desenvolvedor.

Agora observe que o arquivo Publish.proj inclui um elemento Import , imediatamente abaixo da marca project de abertura.

<Import Project="$(TargetEnvPropsFile)"/>

O elemento Import é usado para importar o conteúdo de outro arquivo de projeto do MSBuild para o arquivo de projeto do MSBuild atual. Nesse caso, o parâmetro TargetEnvPropsFile fornece o nome de arquivo do arquivo de projeto que você deseja importar. Você pode fornecer um valor para esse parâmetro ao executar o MSBuild.

msbuild.exe Publish.proj /p:TargetEnvPropsFile=EnvConfig\Env-Dev.proj

Isso mescla efetivamente o conteúdo dos dois arquivos em um único arquivo de projeto. Usando essa abordagem, você pode criar um arquivo de projeto que contém a configuração de build universal e vários arquivos de projeto suplementares que contêm propriedades específicas do ambiente. Como resultado, simplesmente executar um comando com um valor de parâmetro diferente permite implantar sua solução em um ambiente diferente.

Executar um comando com um valor de parâmetro diferente permite implantar sua solução em um ambiente diferente.

Dividir os arquivos de projeto dessa maneira é uma boa prática a ser seguida. Ele permite que os desenvolvedores implantem em vários ambientes executando um único comando, evitando a duplicação de propriedades de build universais em vários arquivos de projeto.

Observação

Para obter diretrizes sobre como personalizar os arquivos de projeto específicos do ambiente para seus próprios ambientes de servidor, consulte Configurando propriedades de implantação para um ambiente de destino.

Conclusão

Este tópico forneceu uma introdução geral aos arquivos de projeto do MSBuild e explicou como você pode criar seus próprios arquivos de projeto personalizados para controlar o processo de build. Ele também introduziu o conceito de dividir arquivos de projeto em instruções de build universais e propriedades de build específicas do ambiente, para facilitar a criação e a implantação de projetos em vários destinos.

O próximo tópico, Noções básicas sobre o processo de build, fornece mais informações sobre como você pode usar arquivos de projeto para controlar a compilação e a implantação percorrendo a implantação de uma solução com um nível realista de complexidade.

Leitura Adicional

Para obter uma introdução mais detalhada aos arquivos de projeto e ao WPP, consulte Inside the Microsoft Build Engine: Using MSBuild and Team Foundation Build by Sayed Ibrahim Hashimi and William Bartholomew, ISBN: 978-0-7356-4524-0.