Dela via


Så här skapar MSBuild projekt

Hur fungerar MSBuild egentligen? I den här artikeln får du lära dig hur MSBuild bearbetar dina projektfiler, oavsett om de anropas från Visual Studio eller från en kommandorad eller ett skript. Att veta hur MSBuild fungerar kan hjälpa dig att bättre diagnostisera problem och bättre anpassa din byggprocess. Den här artikeln beskriver byggprocessen och gäller till stor del för alla projekttyper.

Den fullständiga byggprocessen består av inledande start, utvärderingoch körning av de mål och uppgifter som bygger projektet. Förutom dessa indata definierar externa importer information om byggprocessen, inklusive både standardimporter till exempel Microsoft.Common.targets och användarkonfigurerbara importer på lösnings- eller projektnivå.

Startupföretag

MSBuild kan anropas från Visual Studio via MSBuild-objektmodellen i Microsoft.Build.dlleller genom att anropa den körbara (MSBuild.exe eller dotnet build) direkt på kommandoraden eller i ett skript, till exempel i CI-system. I båda fallen omfattar indata som påverkar byggprocessen projektfilen (eller projektobjektet som är internt för Visual Studio), eventuellt en lösningsfil, miljövariabler och kommandoradsväxlar eller deras objektmodellekvivalenter. Under startfasen används kommandoradsalternativen eller objektmodellekvivalenterna för att konfigurera MSBuild-inställningar som att konfigurera loggare. Egenskaper som anges på kommandoraden med växeln -property eller -p anges som globala egenskaper, vilket åsidosätter alla värden som annars skulle ställas in i projektfilerna, även om projektfilerna läses in senare.

Nästa avsnitt handlar om indatafilerna, till exempel lösningsfiler eller projektfiler.

Lösningar och projekt

MSBuild-instanser kan bestå av ett projekt eller många projekt som en del av en lösning. Lösningsfilen är inte en MSBuild XML-fil, men MSBuild tolkar den för att känna till alla projekt som måste skapas för de angivna konfigurations- och plattformsinställningarna. När MSBuild bearbetar dessa XML-indata kallas det för lösningsversionen. Den har några utökningsbara punkter som gör att du kan köra något vid varje lösningsversion, men eftersom den här versionen är en separat körning från de enskilda projektversionerna är inga inställningar för egenskaper eller måldefinitioner från lösningsversionen relevanta för varje projektversion.

Du kan ta reda på hur du utökar lösningsversionen på Anpassa lösningsversionen.

Visual Studio-versioner jämfört med MSBuild.exe versioner

Det finns några betydande skillnader mellan när projekt byggs i Visual Studio jämfört med när du anropar MSBuild direkt, antingen via den körbara MSBuild-filen eller när du använder MSBuild-objektmodellen för att starta en version. Visual Studio hanterar projektversionsordningen för Visual Studio-versioner. det anropar bara MSBuild på den enskilda projektnivån, och när det gör det anges ett par booleska egenskaper (BuildingInsideVisualStudio, BuildProjectReferences) som avsevärt påverkar vad MSBuild gör. I varje projekt sker körningen på samma sätt som när det anropas via MSBuild, men skillnaden uppstår med referensprojekt. När refererade projekt krävs i MSBuild sker faktiskt en kompilering, det vill säga: den kör uppgifter och verktyg och genererar resultat. När en Visual Studio-version hittar ett refererat projekt returnerar MSBuild endast förväntade utdata från det refererade projektet. Det låter Visual Studio styra byggandet av dessa andra projekt. Visual Studio bestämmer byggordningen och anropar till MSBuild separat (efter behov), allt helt under Visual Studio:s kontroll.

En annan skillnad uppstår när MSBuild anropas med en lösningsfil, MSBuild parsar lösningsfilen, skapar en xml-standardindatafil, utvärderar den och kör den som ett projekt. Lösningsversionen körs före ett projekt. När du skapar från Visual Studio händer inget av detta. MSBuild ser aldrig lösningsfilen. Som en konsekvens gäller anpassning av lösningsbygget (med hjälp av före SolutionName.sln.targets och efter SolutionName.sln.targets) endast för MSBuild.exe, dotnet buildeller objektmodellbaserade byggen, inte Visual Studio-byggen.

Projekt-SDKs

SDK-funktionen för MSBuild-projektfiler är relativt ny. Före den här ändringen importerade projektfiler uttryckligen .targets och .props filer som definierade byggprocessen för en viss projekttyp.

.NET Core-projekt importerar den version av .NET SDK som är lämplig för dem. Se översikten .NET Core-projekt-SDK:eroch referensen till egenskaper.

Utvärderingsfas

I det här avsnittet beskrivs hur dessa indatafiler bearbetas och parsas för att skapa minnesinterna objekt som avgör vad som ska skapas.

Syftet med utvärderingsfasen är att skapa objektstrukturerna i minnet baserat på XML-indatafilerna och den lokala miljön. Utvärderingsfasen består av sex pass som bearbetar indatafilerna, till exempel projekt-XML-filerna eller, och de importerade XML-filerna, vanligtvis namngivna som .props eller .targets-filer, beroende på om de främst anger egenskaper eller definierar byggmål. Varje pass skapar en del av minnesinterna objekt som senare används i körningsfasen för att skapa projekten, men inga faktiska byggåtgärder sker under utvärderingsfasen. I varje pass bearbetas elementen i den ordning de visas.

Stegen i utvärderingsfasen är följande:

  • Utvärdera miljövariabler
  • Utvärdera importer och egenskaper
  • Utvärdera objektdefinitioner
  • Utvärdera objekt
  • Utvärdera UsingTask--element
  • Utvärdera mål

Import och egenskaper utvärderas i samma pass i den ordning de förekommer, som om importerna expanderas på plats. Därför är egenskapsinställningar i tidigare importerade filer tillgängliga i senare importerade filer.

Ordningen på dessa pass har betydande konsekvenser och är viktigt att veta när du anpassar projektfilen. Se egenskaps- och objektutvärderingsordning.

Utvärdera miljövariabler

I den här fasen används miljövariabler för att ange motsvarande egenskaper. Till exempel görs PATH-miljövariabeln tillgänglig som en egenskap $(PATH). När du kör från kommandoraden eller ett skript används kommandomiljön som vanligt, och när den körs från Visual Studio används den miljö som gäller när Visual Studio startas.

Utvärdera importer och egenskaper

I den här fasen läss hela xml-indata in, inklusive projektfilerna och hela importkedjan. MSBuild skapar en minnesintern XML-struktur som representerar XML för projektet och alla importerade filer. För närvarande uppdateras och ställs in egenskaper som inte finns i målobjekt.

Som en följd av att MSBuild läser alla XML-indatafiler tidigt i processen påverkar inte eventuella ändringar av dessa indata under byggprocessen den aktuella versionen.

Egenskaper utanför ett mål hanteras på ett annat sätt än egenskaper inom mål. I den här fasen utvärderas endast de egenskaper som definierats utanför något mål.

Eftersom egenskaper bearbetas i ordning under egenskapernas bearbetning, kan en egenskap vid någon punkt i indata komma åt egenskapsvärden som visas tidigare i indata, men inte egenskaper som visas senare.

Eftersom egenskaperna bearbetas innan objekt utvärderas kan du inte komma åt värdet för något objekt under någon del av egenskaperna.

Utvärdera objektdefinitioner

I den här fasen tolkas objektdefinitioner och en minnesintern representation av dessa definitioner skapas.

Utvärdera objekt

Objekt som definieras i ett mål hanteras på ett annat sätt än objekt utanför ett mål. I den här fasen bearbetas objekt utanför alla mål och tillhörande metadata. Metadata som anges av objektdefinitioner åsidosätts av metadata som anges för objekt. Eftersom objekt bearbetas i den ordning de visas kan du referera till objekt som har definierats tidigare, men inte de som visas senare. Eftersom objektpasset sker efter egenskapspasset kan objekt komma åt alla egenskaper om de definieras utanför några målområden, oavsett om egenskapsdefinitionen visas senare.

Utvärdera UsingTask-elementet

I den här fasen läses UsingTask element och aktiviteterna deklareras för senare användning under körningsfasen.

Utvärdera mål

I den här fasen skapas alla målobjektstrukturer i minnet, i förberedelse för körning. Ingen faktisk körning sker.

Utförandefas

I körningsfasen ordnas och körs målobjekten, och alla aktiviteter utförs. Men först utvärderas egenskaper och objekt som definieras inom målen tillsammans i en enda fas i den ordning de visas. Bearbetningsordningen skiljer sig särskilt från hur egenskaper och objekt som inte finns i ett mål bearbetas: alla egenskaper först och sedan alla objekt i separata pass. Ändringar i egenskaper och objekt i ett mål kan observeras efter det mål där de ändrades.

Målversionsordning

I ett enkelt projekt körs målen seriellt. Det centrala problemet är hur du avgör vilken ordning du ska skapa allt i så att beroenden används för att skapa målen i rätt ordning.

Målordningen bestäms av användningen av attributen BeforeTargets, DependsOnTargetsoch AfterTargets på varje mål. Ordningen på senare mål kan påverkas under utförandet av ett tidigare mål om det tidigare målet ändrar en egenskap som refereras av dessa attribut.

Reglerna för beställning beskrivs i Fastställa målversionsordningen. Processen bestäms av en stackstruktur som innehåller mål som ska skapas. Målet längst upp i den här uppgiften startar körningen, och om det beror på något annat, så push-överförs dessa mål till toppen av stacken och de börjar köras. När det finns ett mål utan beroenden körs det till fullbordande och dess överordnade mål återupptas.

Projektreferenser

Det finns två kodsökvägar som MSBuild kan använda, den normala, som beskrivs här, och grafalternativet som beskrivs i nästa avsnitt.

Enskilda projekt anger sitt beroende av andra projekt genom ProjectReference objekt. När ett projekt överst i stacken börjar byggas når det den punkt där det ResolveProjectReferences målet körs, ett standardmål som definierats i de gemensamma målfilerna.

ResolveProjectReferences anropar MSBuild-aktiviteten med indata från ProjectReference objekt för att hämta utdata. De ProjectReference objekten omvandlas till lokala objekt som Reference. MSBuild-körningsfasen för det aktuella projektet pausar medan körningsfasen börjar bearbeta det refererade projektet (utvärderingsfasen görs först efter behov). Det refererade projektet kompileras bara när du har börjat skapa det beroende projektet, och detta skapar ett träd av projekt som kompileras.

Med Visual Studio kan du skapa projektberoenden i lösningsfiler (.sln). Beroendena anges i lösningsfilen och respekteras endast när du skapar en lösning eller när du skapar i Visual Studio. Om du skapar ett enskilt projekt ignoreras den här typen av beroende. Lösningsreferenser omvandlas av MSBuild till ProjectReference objekt och behandlas därefter på samma sätt.

Alternativ för diagram

Om du anger graph build-växeln (-graphBuild eller -graph) blir ProjectReference ett förstklassigt begrepp som används av MSBuild. MSBuild parsar alla projekt och skapar byggordningsdiagrammet, ett faktiskt beroendediagram över projekt, som sedan bläddras för att fastställa byggordningen. Precis som med mål i enskilda projekt ser MSBuild till att refererade projekt skapas efter de projekt som de är beroende av.

Parallell körning

Om du använder stöd för flera processorer (-maxCpuCount eller -m växeln) skapar MSBuild noder, som är MSBuild-processer som använder tillgängliga CPU-kärnor. Varje projekt skickas till en tillgänglig nod. I en nod körs enskilda projektversioner seriellt.

Uppgifter kan aktiveras för parallell körning genom att ange den booleska variabeln BuildInParallel, som anges enligt värdet för egenskapen $(BuildInParallel) i MSBuild. För uppgifter som är aktiverade för parallell körning hanterar en arbetsschemaläggare noder och tilldelar arbete till noder.

Se Skapa flera projekt parallellt med MSBuild

Standardimporter

Microsoft.Common.props och Microsoft.Common.targets både importeras av .NET-projektfiler (explicit eller implicit i SDK-liknande projekt) och finns i mappen MSBuild\Current\bin i en Visual Studio-installation. C++-projekt har en egen importhierarki. Se MSBuild Internals for C++ projects.

Microsoft.Common.props filen ställer in standardvärden som du kan åsidosätta. Den importeras (explicit eller implicit) i början av en projektfil. På så sätt visas projektets inställningar efter standardvärdena, så att de åsidosätter dem.

Microsoft.Common.targets-filen och målfilerna som importeras definierar standardprocessen för .NET-projekt. Den innehåller även tilläggspunkter som du kan använda för att anpassa versionen.

I implementeringen är Microsoft.Common.targets en tunn omslutning som importerar Microsoft.Common.CurrentVersion.targets. Den här filen innehåller inställningar för standardegenskaper och definierar de faktiska mål som definierar byggprocessen. Build-målet är definierat här, men är faktiskt tomt. Det Build målet innehåller dock attributet DependsOnTargets som anger de enskilda mål som utgör de faktiska byggstegen, som BeforeBuild, CoreBuildoch AfterBuild. Målet Build definieras på följande sätt:

  <PropertyGroup>
    <BuildDependsOn>
      BeforeBuild;
      CoreBuild;
      AfterBuild
    </BuildDependsOn>
  </PropertyGroup>

  <Target
      Name="Build"
      Condition=" '$(_InvalidConfigurationWarning)' != 'true' "
      DependsOnTargets="$(BuildDependsOn)"
      Returns="@(TargetPathWithTargetPlatformMoniker)" />

BeforeBuild och AfterBuild är tilläggspunkter. De är tomma i Microsoft.Common.CurrentVersion.targets-filen, men projekt kan tillhandahålla sina egna BeforeBuild och AfterBuild mål med uppgifter som måste utföras före eller efter huvudgenereringsprocessen. AfterBuild körs innan no-op-mål Buildeftersom AfterBuild visas i attributet DependsOnTargets på målet Build, men det inträffar efter CoreBuild.

Mål CoreBuild innehåller anrop till byggverktygen enligt följande:

  <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>

I följande tabell beskrivs dessa mål. vissa mål gäller endast för vissa projekttyper.

Mål Beskrivning
BuildOnlySettings Inställningar endast för verkliga versioner, inte för när MSBuild anropas vid projektinläsning av Visual Studio.
PrepareForBuild Förbered förutsättningarna för att bygga
PreBuildEvent Tilläggspunkt för projekt för att definiera uppgifter som ska köras före byggprocessen
ResolveProjectReferences Analysera projektberoenden och skapa refererade projekt
ResolveAssemblyReferences Leta upp refererade sammansättningar.
ResolveReferences Består av ResolveProjectReferences och ResolveAssemblyReferences för att hitta alla beroenden
PrepareResources Bearbeta resursfiler
ResolveKeySource Lös den starka namnnyckel som används för att signera sammansättningen och certifikatet som används för att signera ClickOnce- manifest.
Kompilera Anropar kompilatorn
ExporteraWindowsMDFil Generera en WinMD- fil från WinMDModule-filerna som genereras av kompilatorn.
HanteringsfriAvregistrering Ta bort/rensa COM Interop- registerposter från en tidigare version
GenerateSerializationAssemblies Generera en XML-serialiseringssammansättning med hjälp av sgen.exe.
CreateSatelliteAssemblies Skapa en satellitsammansättning för varje unik kultur i resurserna.
Generera manifesten Genererar ClickOnce program- och distributionsmanifest eller ett inbyggt manifest.
GetTargetPath Returnera ett objekt som innehåller byggprodukten (körbar eller sammansättning) för det här projektet med metadata.
PrepareForRun Kopiera byggutdata till den slutliga katalogen om de har ändrats.
Ohanterad registrering Ange registerposter för COM Interop
IncrementalClean Ta bort filer som skapades i en tidigare version men som inte producerades i den aktuella versionen. Detta är nödvändigt för att Clean ska fungera i inkrementella versioner.
PostBuildEvent Tilläggspunkt för projekt för att definiera aktiviteter som ska köras efter bygget

Många av målen i föregående tabell finns i språkspecifika importer, till exempel Microsoft.CSharp.targets. Den här filen definierar stegen i den standardversionsprocess som är specifik för C# .NET-projekt. Den innehåller till exempel det Compile mål som faktiskt anropar C#-kompilatorn.

Användarkonfigurerbar import

Förutom standardimporterna finns det flera importer som du kan lägga till för att anpassa byggprocessen.

  • Directory.Build.props
  • Directory.Build.targets

Dessa filer läses in av standardimporterna för alla projekt i alla undermappar under dem. Det är vanligtvis på lösningsnivå för inställningar för att styra alla projekt i lösningen, men kan också ligga högre upp i filsystemet, ända upp till roten av hårddisken.

Filen Directory.Build.props importeras av Microsoft.Common.props, så de egenskaper som definieras däri är tillgängliga i projektfilen. De kan omdefinieras i projektfilen för att anpassa värdena per projekt. Filen Directory.Build.targets läses in efter projektfilen. Den innehåller vanligtvis mål, men här kan du också definiera egenskaper som du inte vill att enskilda projekt ska omdefiniera.

Anpassningar i en projektfil

Visual Studio uppdaterar dina projektfiler när du gör ändringar i Solution Explorer, fönstret Egenskaper eller i Projektegenskaper, men du kan också göra dina egna ändringar genom att redigera projektfilen direkt.

Många byggbeteenden kan konfigureras genom att ange MSBuild-egenskaper, antingen i projektfilen för inställningar som är lokala för ett projekt eller som nämns i föregående avsnitt, genom att skapa en Directory.Build.props fil för att ange egenskaper globalt för hela mappar med projekt och lösningar. För ad hoc-versioner på kommandoraden eller skript kan du också använda alternativet /p på kommandoraden för att ange egenskaper för ett visst anrop av MSBuild. Mer information om egenskaper som du kan ange finns i Vanliga MSBuild-projektegenskaper.