Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
O MSBuild é o mecanismo de build da Microsoft usado para criar a maioria dos projetos do Visual Studio. O MSBuild invoca compiladores e outras ferramentas para criar seu código, mas também inclui opções flexíveis de configuração e personalização e infraestrutura para criar não apenas binários compilados, mas também uma ampla gama de outros artefatos de saída. O MSBuild é muito configurável e personalizável, mas para aproveitar ao máximo essa personalização, é importante entender como o MSBuild funciona. Neste artigo, você aprenderá como o MSBuild processa seus arquivos de projeto, sejam invocados do Visual Studio ou de uma linha de comando ou script. Saber como o MSBuild funciona pode ajudá-lo a diagnosticar melhor os problemas e personalizar melhor o processo de build. Este artigo descreve o processo de build e é amplamente aplicável a todos os tipos de projeto.
O processo de build completo consiste em
- inicialização – o processamento de opções de linha de comando.
- avaliação – a interpretação e o processamento do texto do arquivo de projeto do MSBuild.
- execução – executa os destinos e as tarefas que criam o projeto.
Além dos arquivos de origem e outros artefatos de entrada, as importações externas definem os detalhes do processo de build, incluindo importações padrão , como Microsoft.Common.targets e importações configuráveis pelo usuário no nível da solução ou do projeto.
Inicialização
O MSBuild pode ser invocado do Visual Studio por meio do modelo de objeto MSBuild em Microsoft.Build.dllou invocando o executável (MSBuild.exe ou dotnet build) diretamente na linha de comando ou em um script, como em sistemas de CI. Em ambos os casos, as entradas que afetam o processo de build incluem o arquivo de projeto (ou objeto de projeto interno para o Visual Studio), possivelmente um arquivo de solução, variáveis de ambiente e comutadores de linha de comando ou seus equivalentes de modelo de objeto. Durante a fase de inicialização, as opções de linha de comando ou equivalentes do modelo de objeto são usadas para definir configurações do MSBuild, como configurar agentes. As propriedades definidas na linha de comando usando a opção -property são -p definidas como propriedades globais, que substituem todos os valores que seriam definidos nos arquivos de projeto, mesmo que os arquivos de projeto sejam lidos posteriormente.
As próximas seções são sobre os arquivos de entrada, como arquivos de solução ou arquivos de projeto.
Soluções e projetos
As instâncias do MSBuild podem consistir em um projeto ou muitos projetos como parte de uma solução. Há suporte para arquivos de solução no .slnx formato ou no .sln formato (no MSBuild 17.12 e posterior). O arquivo de solução (.sln) não é um arquivo XML do MSBuild, mas o MSBuild o interpreta para conhecer todos os projetos necessários para serem criados para as configurações e as configurações de plataforma fornecidas. Quando o MSBuild processa essa entrada, ela é conhecida como a compilação da solução. Ele tem alguns pontos extensíveis que permitem executar algo em cada build de solução, mas como esse build é uma execução separada das compilações individuais do projeto, nenhuma configuração de propriedades ou definições de destino do build da solução é relevante para cada build de projeto.
Você pode descobrir como estender o build da solução em Personalizar o build da solução.
Builds do Visual Studio versus builds de MSBuild.exe
Há algumas diferenças significativas entre quando os projetos são compilados no Visual Studio versus quando você invoca o MSBuild diretamente, por meio do executável do MSBuild ou quando usa o modelo de objeto MSBuild para iniciar um build. O Visual Studio gerencia a ordem de build do projeto para builds do Visual Studio; ele só chama o MSBuild no nível de projeto individual e, quando isso acontece, algumas propriedades boolianas (BuildingInsideVisualStudio, BuildProjectReferences) são definidas que afetam significativamente o que o MSBuild faz. Dentro de cada projeto, a execução ocorre da mesma forma que quando invocada por meio do MSBuild, mas a diferença surge com projetos referenciados. No MSBuild, quando os projetos referenciados são necessários, um build realmente ocorre; ou seja, ele executa tarefas e ferramentas e gera a saída. Quando um build do Visual Studio encontra um projeto referenciado, o MSBuild retorna apenas as saídas esperadas do projeto referenciado; ele permite que o Visual Studio controle a construção desses outros projetos. O Visual Studio determina a ordem de build e as chamadas para o MSBuild separadamente (conforme necessário), tudo completamente sob o controle do Visual Studio.
Outra diferença surge quando o MSBuild é invocado com um arquivo de solução, o MSBuild analisa o arquivo de solução, cria um arquivo de entrada XML padrão, o avalia e o executa como um projeto. O build da solução é executado antes de qualquer projeto. Ao compilar a partir do Visual Studio, nada disso acontece; O MSBuild nunca vê o arquivo de solução. Como consequência, a personalização do build da solução (usando antes. SolutionName.sln.targets e posteriores. SolutionName.sln.targets) aplica-se apenas a builds baseados em MSBuild.exe, dotnet buildou de modelo de objeto, não de builds do Visual Studio.
SDKs do projeto
O recurso SDK para arquivos de projeto do MSBuild é relativamente novo. Antes dessa alteração, os arquivos de projeto importavam explicitamente os arquivos .targets e .props que definiam o processo de build para um tipo de projeto específico.
Os projetos do .NET Core importam a versão do SDK do .NET apropriada para eles. Confira a visão geral, os SDKs de projeto do .NET Core e a referência às propriedades.
Fase de avaliação
Esta seção discute como esses arquivos de entrada são processados e analisados para produzir objetos na memória que determinam o que será criado.
A finalidade da fase de avaliação é criar as estruturas de objeto na memória com base nos arquivos XML de entrada e no ambiente local. A fase de avaliação consiste em seis passes que processam os arquivos de entrada, como os arquivos XML do projeto ou, e os arquivos XML importados, geralmente nomeados como arquivos .props ou .targets , dependendo se eles definem principalmente propriedades ou definem destinos de build. Cada passagem cria uma parte dos objetos na memória que são usados posteriormente na fase de execução para criar os projetos, mas nenhuma ação de build real ocorre durante a fase de avaliação. Em cada passagem, os elementos são processados na ordem em que aparecem.
As passagens na fase de avaliação são as seguintes:
- Avaliar variáveis de ambiente
- Avaliar importações e propriedades
- Avaliar definições de item
- Avaliar itens
- Avaliar elementos UsingTask
- Avaliar destinos
Importações e propriedades são avaliadas na mesma sequência de aparência de passagem, como se as importações forem expandidas em vigor. Portanto, as configurações de propriedade em arquivos importados anteriormente estão disponíveis em arquivos importados posteriormente.
A ordem dessas passagens tem implicações significativas e é importante saber ao personalizar o arquivo de projeto. Consulte a ordem de avaliação de propriedade e item.
Avaliar variáveis de ambiente
Nesta fase, as variáveis de ambiente são usadas para definir propriedades equivalentes. Por exemplo, a variável de ambiente PATH é disponibilizada como uma propriedade $(PATH). Quando executado a partir da linha de comando ou de um script, o ambiente de comando é usado como normal e, quando executado no Visual Studio, o ambiente em vigor quando o Visual Studio é iniciado é usado.
Avaliar importações e propriedades
Nesta fase, todo o XML de entrada é lido, incluindo os arquivos de projeto e toda a cadeia de importações. O MSBuild cria uma estrutura XML na memória que representa o XML do projeto e todos os arquivos importados. No momento, as propriedades que não estão nos destinos são avaliadas e definidas.
Como consequência da leitura de todos os arquivos de entrada XML no início do processo, as alterações nessas entradas durante o processo de build não afetam o build atual.
As propriedades fora de qualquer destino são tratadas de forma diferente das propriedades dentro dos destinos. Nesta fase, somente as propriedades definidas fora de qualquer destino são avaliadas.
Como as propriedades são processadas em ordem na passagem de propriedades, uma propriedade a qualquer momento na entrada pode acessar valores de propriedade que aparecem anteriormente na entrada, mas não propriedades que aparecem posteriormente.
Como as propriedades são processadas antes que os itens sejam avaliados, você não pode acessar o valor de qualquer item durante qualquer parte da passagem de propriedades.
Avaliar definições de item
Nesta fase, as definições de item são interpretadas e uma representação na memória dessas definições é criada.
Avaliar itens
Os itens definidos dentro de um destino são tratados de forma diferente dos itens fora de qualquer destino. Nesta fase, os itens fora de qualquer destino e seus metadados associados são processados. Metadados definidos por definições de item são substituídos por metadados definidos em itens. Como os itens são processados na ordem em que aparecem, você pode referenciar itens que foram definidos anteriormente, mas não os que aparecem posteriormente. Como os itens são passados após a passagem das propriedades, os itens podem acessar qualquer propriedade se definidos fora de qualquer destino, independentemente de a definição da propriedade ser exibida posteriormente.
Avaliar UsingTask elementos
Nesta fase, os elementos UsingTask são lidos e as tarefas são declaradas para uso posterior durante a fase de execução.
Avaliar destinos
Nesta fase, todas as estruturas de objeto de destino são criadas na memória, em preparação para execução. Nenhuma execução real ocorre.
Fase de execução
Na fase de execução, os destinos são ordenados e executados e todas as tarefas são executadas. Mas, primeiro, as propriedades e os itens definidos dentro dos destinos são avaliados juntos em uma única fase na ordem em que aparecem. A ordem de processamento é notavelmente diferente de como as propriedades e itens que não estão em um destino são processados: todas as propriedades primeiro e, em seguida, todos os itens, em passagens separadas. As alterações em propriedades e itens dentro de um destino podem ser observadas após o destino em que foram alteradas.
Ordem de build de destino
Em um único projeto, os destinos são executados serialmente. O problema central é como determinar em que ordem criar tudo para que as dependências sejam usadas para criar os destinos na ordem certa.
A ordem de build de destino é determinada pelo uso do BeforeTargets, DependsOnTargetse AfterTargets atributos em cada destino. A ordem dos destinos posteriores poderá ser influenciada durante a execução de um destino anterior se o destino anterior modificar uma propriedade referenciada nesses atributos.
As regras para ordenação são descritas em Determinar a ordem de build de destino. O processo é determinado por uma estrutura de pilha que contém destinos a serem compilados. O destino na parte superior dessa tarefa inicia a execução e, se depender de qualquer outra coisa, esses destinos são enviados para a parte superior da pilha e começam a ser executados. Quando há um destino sem dependências, ele é executado até a conclusão e seu destino pai é retomado.
Referências de projeto
Há dois caminhos de código que o MSBuild pode usar, o normal, descrito aqui e a opção de grafo descrita na próxima seção.
Projetos individuais especificam sua dependência de outros projetos por meio ProjectReference de itens. Quando um projeto na parte superior da pilha começa a ser criado, ele atinge o ponto em que o ResolveProjectReferences destino é executado, um destino padrão definido nos arquivos de destino comuns.
ResolveProjectReferences invoca a tarefa MSBuild com entradas dos ProjectReference itens para obter as saídas. Os ProjectReference itens são transformados em itens locais, como Reference. A fase de execução do MSBuild para o projeto atual pausa enquanto a fase de execução começa a processar o projeto referenciado (a fase de avaliação é feita primeiro conforme necessário). O projeto referenciado só é compilado depois que você começa a compilar o projeto dependente e, portanto, cria uma árvore de construção de projetos.
O Visual Studio permite a criação de dependências de projeto em arquivos de solução (.sln). As dependências são especificadas no arquivo de solução e só são respeitadas ao criar uma solução ou ao criar dentro do Visual Studio. Se você criar um único projeto, esse tipo de dependência será ignorado. As referências de solução são transformadas pelo MSBuild em ProjectReference itens e, posteriormente, são tratadas da mesma maneira.
Opção de grafo
Se você especificar o comutador de build de grafo (-graphBuild ou -graph), ele ProjectReference se tornará um conceito de primeira classe usado pelo MSBuild. O MSBuild analisará todos os projetos e construirá o grafo de ordem de build, um grafo de dependência real de projetos, que é então percorrido para determinar a ordem de build. Assim como acontece com os destinos em projetos individuais, o MSBuild garante que os projetos referenciados sejam criados após os projetos dos quais dependem.
Execução paralela
Se estiver usando suporte a vários processadores (-maxCpuCount ou -m comutador), o MSBuild criará nós, que são processos do MSBuild que usam os núcleos de CPU disponíveis. Cada projeto é enviado para um nó disponível. Dentro de um nó, os builds de projeto individuais são executados serialmente.
As tarefas podem ser habilitadas para execução paralela definindo uma variável booliana BuildInParallel, que é definida de acordo com o valor da $(BuildInParallel) propriedade no MSBuild. Para tarefas habilitadas para execução paralela, um agendador de trabalho gerencia nós e atribui trabalho a nós.
Consulte Como criar vários projetos em paralelo com o MSBuild
Importações padrão
Microsoft.Common.props e Microsoft.Common.targets são importados por arquivos de projeto do .NET (explicitamente ou implicitamente em projetos no estilo SDK) e estão localizados na pasta MSBuild\Current\bin em uma instalação do Visual Studio. Os projetos do C++ têm sua própria hierarquia de importações; consulte Os Internos do MSBuild para projetos C++.
Os conjuntos de arquivos Microsoft.Common.props padrão que você pode substituir. Ele é importado (explicitamente ou implicitamente) no início de um arquivo de projeto. Dessa forma, as configurações do projeto aparecem após os padrões, para que elas as substituam.
O arquivo Microsoft.Common.targets e os arquivos de destino importados definem o processo de build padrão para projetos .NET. Ele também fornece pontos de extensão que você pode usar para personalizar o build.
Na implementação, Microsoft.Common.targets é um wrapper fino que importa Microsoft.Common.CurrentVersion.targets. Esse arquivo contém configurações para propriedades padrão e define os destinos reais que definem o processo de build. O Build destino é definido aqui, mas na verdade está vazio. No entanto, o Build destino contém o DependsOnTargets atributo que especifica os destinos individuais que compõem as etapas de build reais, que são BeforeBuild, CoreBuilde AfterBuild. O Build destino é definido da seguinte maneira:
<PropertyGroup>
<BuildDependsOn>
BeforeBuild;
CoreBuild;
AfterBuild
</BuildDependsOn>
</PropertyGroup>
<Target
Name="Build"
Condition=" '$(_InvalidConfigurationWarning)' != 'true' "
DependsOnTargets="$(BuildDependsOn)"
Returns="@(TargetPathWithTargetPlatformMoniker)" />
BeforeBuild e AfterBuild são pontos de extensão. Eles estão vazios no arquivo Microsoft.Common.CurrentVersion.targets , mas os projetos podem fornecer seus próprios BeforeBuild destinos e AfterBuild tarefas que precisam ser executadas antes ou depois do processo de build principal.
AfterBuildé executado antes do destino no-op, Buildporque aparece no DependsOnTargets atributo no Build destino, mas ocorre após CoreBuildAfterBuild .
O CoreBuild destino contém as chamadas para as ferramentas de build, da seguinte maneira:
<PropertyGroup>
<CoreBuildDependsOn>
BuildOnlySettings;
PrepareForBuild;
PreBuildEvent;
ResolveReferences;
PrepareResources;
ResolveKeySource;
Compile;
ExportWindowsMDFile;
UnmanagedUnregistration;
GenerateSerializationAssemblies;
CreateSatelliteAssemblies;
GenerateManifests;
GetTargetPath;
PrepareForRun;
UnmanagedRegistration;
IncrementalClean;
PostBuildEvent
</CoreBuildDependsOn>
</PropertyGroup>
<Target
Name="CoreBuild"
DependsOnTargets="$(CoreBuildDependsOn)">
<OnError ExecuteTargets="_TimeStampAfterCompile;PostBuildEvent" Condition="'$(RunPostBuildEvent)'=='Always' or '$(RunPostBuildEvent)'=='OnOutputUpdated'"/>
<OnError ExecuteTargets="_CleanRecordFileWrites"/>
</Target>
A tabela a seguir descreve esses destinos; alguns destinos são aplicáveis somente a determinados tipos de projeto.
| Meta | Description |
|---|---|
| BuildOnlySettings | Configurações somente para builds reais, não para quando o MSBuild é invocado na carga do projeto pelo Visual Studio. |
| PrepareForBuild | Preparar os pré-requisitos para a criação |
| PreBuildEvent | Ponto de extensão para projetos definirem tarefas a serem executadas antes do build |
| ResolveProjectReferences | Analisar dependências de projeto e criar projetos referenciados |
| ResolveAssemblyReferences | Localize assemblies referenciados. |
| ResolveReferences |
ResolveProjectReferences Consiste em e ResolveAssemblyReferences localizar todas as dependências |
| PrepareResources | Processar arquivos de recursos |
| ResolveKeySource | Resolva a chave de nome forte usada para assinar o assembly e o certificado usado para assinar os manifestos do ClickOnce . |
| Compilar | Invoca o compilador |
| ExportWindowsMDFile | Gere um arquivo WinMD dos arquivos WinMDModule gerados pelo compilador. |
| UnmanagedUnregistration | Remover/limpar as entradas do Registro de Interoperabilidade COM de um build anterior |
| GenerateSerializationAssemblies | Gerar um assembly de serialização XML usando sgen.exe. |
| CreateSatelliteAssemblies | Crie um assembly satélite para cada cultura exclusiva nos recursos. |
| Gerar manifestos | Gera manifestos de aplicativo e implantação clickOnce ou um manifesto nativo. |
| GetTargetPath | Retorne um item que contém o produto de build (executável ou assembly) para este projeto, com metadados. |
| PrepareForRun | Copie as saídas de build para o diretório final se elas tiverem sido alteradas. |
| UnmanagedRegistration | Definir entradas do Registro para Interoperabilidade COM |
| IncrementalClean | Remova arquivos que foram produzidos em um build anterior, mas não foram produzidos no build atual. Isso é necessário para trabalhar Clean em builds incrementais. |
| PostBuildEvent | Ponto de extensão para projetos definirem tarefas a serem executadas após o build |
Muitos dos destinos na tabela anterior são encontrados em importações específicas do idioma, como Microsoft.CSharp.targets. Esse arquivo define as etapas no processo de build padrão específicas para projetos .NET em C#. Por exemplo, ele contém o Compile destino que realmente chama o compilador C#.
Importações configuráveis pelo usuário
Além das importações padrão, há várias importações que você pode adicionar para personalizar o processo de build.
- Directory.Build.props
- Directory.Build.targets
Esses arquivos são lidos pelas importações padrão para quaisquer projetos em qualquer subpasta sob eles. Isso geralmente está no nível da solução para que as configurações controlem todos os projetos na solução, mas também podem ser mais altas no sistema de arquivos, até a raiz da unidade.
O arquivo Directory.Build.props é importado por Microsoft.Common.props, portanto, as propriedades definidas nela estão disponíveis no arquivo de projeto. Eles podem ser redefinidos no arquivo de projeto para personalizar os valores por projeto. O arquivo Directory.Build.targets é lido após o arquivo de projeto. Normalmente, ele contém destinos, mas aqui você também pode definir propriedades que você não deseja que projetos individuais redefinam.
Personalizações em um arquivo de projeto
O Visual Studio atualiza seus arquivos de projeto à medida que você faz alterações no Gerenciador de Soluções, na janela Propriedades ou nas Propriedades do Projeto, mas também pode fazer suas próprias alterações editando diretamente o arquivo de projeto.
Muitos comportamentos de build podem ser configurados definindo as propriedades do MSBuild, seja no arquivo de projeto para configurações locais de um projeto ou conforme mencionado na seção anterior, criando um arquivo Directory.Build.props para definir propriedades globalmente para pastas inteiras de projetos e soluções. Para compilações ad hoc na linha de comando ou scripts, você também pode usar a opção /p na linha de comando para definir propriedades para uma invocação específica do MSBuild. Consulte as propriedades comuns do projeto DO MSBuild para obter informações sobre as propriedades que você pode definir.