Megosztás a következőn keresztül:


Hogyan fejleszti az MSBuild a projekteket?

Az MSBuild a Microsoft buildmotorja, amely a legtöbb Visual Studio-projekt létrehozásához használható. Az MSBuild meghívja a fordítókat és más eszközöket a kód létrehozásához, de rugalmas konfigurációs és testreszabási lehetőségeket, valamint olyan infrastruktúrát is tartalmaz, amellyel nem csak lefordított bináris fájlokat hozhat létre, hanem számos egyéb kimeneti összetevőt is. Az MSBuild nagyon konfigurálható és testreszabható, de ahhoz, hogy a lehető legtöbbet hozhassa ki ebből a testreszabhatóságból, fontos tisztában lenni az MSBuild működésével. Ebben a cikkben megtudhatja, hogyan dolgozza fel az MSBuild a projektfájlokat, akár a Visual Studióból, akár parancssorból vagy szkriptből. Az MSBuild működésének ismerete segíthet a problémák jobb diagnosztizálásában és a buildelési folyamat jobb testreszabásában. Ez a cikk ismerteti a buildelési folyamatot, és nagyrészt minden projekttípusra alkalmazható.

A teljes összeállítási folyamat a következőkből áll:

  • kezdeti indítás – a parancssori beállítások feldolgozása.
  • értékelés – az MSBuild projektfájl szövegének értelmezése és feldolgozása.
  • végrehajtás – futtatja a projektet összeállító célokat és feladatokat.

A forrásfájlok és egyéb bemeneti összetevők mellett a külső importálások határozzák meg a buildelési folyamat részleteit, beleértve a standard importálásokat is, például a Microsoft.Common.targets és a felhasználó által konfigurálható importálást a megoldás vagy a projekt szintjén.

Indítás

Az MSBuild meghívható a Visual Studióból a Microsoft.Build.dllMSBuild objektummodelljén keresztül, vagy a végrehajtható (MSBuild.exe vagy dotnet build) meghívásával közvetlenül a parancssorban vagy egy szkriptben, például CI-rendszerekben. Mindkét esetben a buildelési folyamatot befolyásoló bemenetek közé tartozik a projektfájl (vagy a Visual Studio belső projektobjektuma), esetleg a megoldásfájl, a környezeti változók és a parancssori kapcsolók vagy az objektummodell megfelelői. Az indítási fázis során a parancssori beállítások vagy az objektummodell megfelelői az MSBuild-beállítások konfigurálására, például a naplózók konfigurálására szolgálnak. A parancssorban a -property vagy -p kapcsolóval beállított tulajdonságok globális tulajdonságokként vannak beállítva, amelyek felülbírálják a projektfájlokban beállított értékeket, annak ellenére, hogy a projektfájlokat később beolvassa a rendszer.

A következő szakaszok a bemeneti fájlokról szólnak, például a megoldásfájlokról vagy a projektfájlokról.

Megoldások és projektek

Az MSBuild-példányok egy projektből vagy egy megoldás részeként számos projektből állhatnak. A `.slnx` vagy `.sln` formátumban lévő megoldásfájlok egyaránt támogatottak (az MSBuild 17.12-ben és azután). A megoldásfájl (.sln) nem MSBuild XML-fájl, de az MSBuild úgy értelmezi, hogy megismerje azokat a projekteket, amelyek a megadott konfigurációhoz és platformbeállításokhoz szükségesek. Amikor az MSBuild feldolgozza ezt a bemenetet, azt a megoldás buildjének nevezzük. Van néhány bővíthető pontja, amely lehetővé teszi, hogy minden megoldás buildjén futtathasson valamit, de mivel ez a build külön futtatás az egyes projekt buildektől, a megoldás buildjének egyik tulajdonság- vagy céldefiníciója sem releváns az egyes projekt buildekhez.

A megoldás buildjének kiterjesztését a A megoldás buildjének testreszabásacímű témakörben találja.

Visual Studio-buildek és MSBuild.exe buildek

Jelentős különbségek vannak a projektek Visual Studióban történő buildelése és az MSBuild közvetlen meghívása között, akár az MSBuild végrehajtható fájlon keresztül, akár ha az MSBuild objektummodellt használja a build elindításához. A Visual Studio kezeli a Visual Studio-buildek projekt-összeállítási sorrendjét; csak az egyes projekt szintjén hívja meg az MSBuildet, és ha igen, néhány logikai tulajdonság (BuildingInsideVisualStudio, BuildProjectReferences) van beállítva, amelyek jelentősen befolyásolják az MSBuild működését. Az egyes projekteken belül a végrehajtás ugyanúgy történik, mint az MSBuild használatával történő meghíváskor, de a különbség a hivatkozott projekteknél jelentkezik. Az MSBuildben, ha hivatkozott projektekre van szükség, valójában buildelés történik; vagyis feladatokat és eszközöket futtat, és létrehozza a kimenetet. Amikor egy Visual Studio-build talál egy hivatkozott projektet, az MSBuild csak a hivatkozott projekt várt kimeneteit adja vissza; lehetővé teszi, hogy a Visual Studio vezérelje a többi projekt felépítését. A Visual Studio külön határozza meg a buildelési sorrendet és az MSBuildbe irányuló hívásokat (szükség szerint), mindezt teljes egészében a Visual Studio felügyelete alatt.

Egy másik különbség akkor fordul elő, ha az MSBuild meghívása megoldásfájllal történik, az MSBuild elemzi a megoldásfájlt, létrehoz egy szabványos XML-bemeneti fájlt, kiértékeli és projektként végrehajtja. A megoldás buildelése minden projekt előtt végrehajtva. Amikor a Visual Studióból építkeznek, ez nem történik meg; Az MSBuild soha nem látja a megoldásfájlt. Ennek következtében a megoldási buildek testreszabása (használata a SolutionName.sln.targets előtt és használata a SolutionName.sln.targetsután) csak MSBuild.exe, dotnet buildvagy objektummodell-alapú buildekre vonatkozik, a Visual Studio-buildekre nem.

Projekt SDK-k

Az MSBuild projektfájlok SDK-funkciója viszonylag új. A módosítás előtt a projektfájlok explicit módon importálták a .targets és .props fájlokat, amelyek meghatározták az adott projekttípus buildelési folyamatát.

A .NET Core-projektek a számukra megfelelő .NET SDK-verziót importálják. Tekintse meg a .NET Core-projekt SDK-k áttekintését, valamint a tulajdonságokramutató hivatkozást.

Kiértékelési fázis

Ez a szakasz bemutatja, hogyan dolgozzák fel és elemzik ezeket a bemeneti fájlokat a memóriában lévő objektumok létrehozásához, amelyek meghatározzák, hogy mit fognak létrehozni.

A kiértékelési fázis célja az objektumstruktúrák létrehozása a memóriában a bemeneti XML-fájlok és a helyi környezet alapján. A kiértékelési fázis hat lépésből áll, amelyek feldolgozzák a bemeneti fájlokat, például a projekt XML-fájljait vagy az importált XML-fájlokat, amelyek általában .props vagy .targets fájlokat, attól függően, hogy elsősorban tulajdonságokat vagy buildcélokat határoznak meg. Minden egyes átadás létrehozza a memóriában lévő objektumok egy részét, amelyeket később a végrehajtási fázisban használnak a projektek létrehozásához, de a kiértékelési fázisban nem történik tényleges buildelési művelet. Minden egyes lépésen belül az elemek a megjelenésük sorrendjében lesznek feldolgozva.

A kiértékelési fázisban a következő passzok jelennek meg:

  • Környezeti változók kiértékelése
  • Importok és tulajdonságok értékelése
  • Elemdefiníciók kiértékelése
  • Elemek kiértékelése
  • UsingTask-elemek kiértékelése
  • Célok kiértékelése

Az importálásokat és tulajdonságokat a rendszer a megjelenés sorrendjében értékeli ki, mintha az importálások helyben lennének kibővítve. Így a korábban importált fájlok tulajdonságbeállításai a későbbi importált fájlokban érhetők el.

Ezeknek a bérleteknek a sorrendje jelentős következményekkel jár, és fontos tudni a projektfájl testreszabásakor. A tulajdonság- és tételértékelés sorrendjét lásdalatt.

Környezeti változók kiértékelése

Ebben a fázisban a környezeti változók az egyenértékű tulajdonságok beállítására szolgálnak. A PATH környezeti változó például $(PATH)tulajdonságként érhető el. A parancssorból vagy szkriptből való futtatáskor a rendszer a szokásos módon használja a parancskörnyezetet, a Visual Studióból való futtatáskor pedig a Visual Studio indításakor érvényes környezetet.

Importok és tulajdonságok értékelése

Ebben a fázisban a teljes bemeneti XML be van olvasva, beleértve a projektfájlokat és a teljes importálási láncot. Az MSBuild létrehoz egy memórián belüli XML-struktúrát, amely a projekt XML-jének és az összes importált fájlnak felel meg. Jelenleg a nem céltulajdonságok kiértékelése és beállítása történik.

Az MSBuild a folyamat korai szakaszában beolvassa az összes XML-bemeneti fájlt, ezért a buildelési folyamat során a bemenetek módosításai nem érintik az aktuális buildet.

A célon kívüli tulajdonságok kezelése eltér a célokon belüli tulajdonságoktól. Ebben a fázisban csak a célon kívül definiált tulajdonságok lesznek kiértékelve.

Mivel a tulajdonságok feldolgozása sorrendben történik a tulajdonságok átadásában, a bemenet bármely pontján lévő tulajdonság hozzáférhet a bemenet korábbi értékeihez, de a később megjelenő tulajdonságokhoz nem.

Mivel a tulajdonságok feldolgozása az elemek kiértékelése előtt történik, a tulajdonságok átadása során nem férhet hozzá egyetlen elem értékéhez sem.

Elemdefiníciók kiértékelése

Ebben a fázisban elemdefiníciók lesznek értelmezve, és létrejön ezeknek a definícióknak a memóriabeli ábrázolása.

Elemek kiértékelése

A célon belül definiált elemek kezelése eltér a célon kívüli elemektől. Ebben a fázisban a rendszer feldolgozja a célon kívüli elemeket és a hozzájuk tartozó metaadatokat. Az elemdefiníciók által beállított metaadatokat az elemek metaadatai felül bírálják. Mivel az elemek a megjelenésük sorrendjében vannak feldolgozva, hivatkozhat a korábban definiált elemekre, de a később megjelenő elemekre nem. Mivel az elemek átadása a tulajdonságok átadása után történik, az elemek bármilyen tulajdonsághoz hozzáférhetnek, ha a célon kívül vannak definiálva, függetlenül attól, hogy a tulajdonságdefiníció később jelenik-e meg.

Értékeld ki a UsingTask elemeket

Ebben a fázisban a UsingTask elemeket olvassák, és a feladatokat deklarálják a későbbi felhasználásra a végrehajtási fázis során.

Célok kiértékelése

Ebben a fázisban az összes célobjektum-struktúra létrejön a memóriában, a végrehajtás előkészítése céljából. Nincs tényleges végrehajtás.

Végrehajtási fázis

A végrehajtási fázisban a célokat a rendszer rendezi és futtatja, és minden tevékenységet végrehajt. Először azonban a célokon belül definiált tulajdonságokat és elemeket a rendszer egyetlen fázisban, a megjelenésük sorrendjében értékeli ki. A feldolgozás sorrendje különösen eltér a célban nem szereplő tulajdonságok és elemek feldolgozásától: először az összes tulajdonság, majd az összes elem külön áthalad. A cél tulajdonságainak és elemeinek változásait megfigyelhetjük azon a ponton túl, ahol ezeket módosították.

Cél építési sorrendje

Egyetlen projektben a célok sorozatosan hajtódnak végre. A központi probléma az, hogyan határozható meg, hogy milyen sorrendben kell mindent felépíteni annak érdekében, hogy a függőségek a célok megfelelő sorrendben történő összeállításához legyenek használva.

Minden egyes cél összeállítási sorrendjét a BeforeTargets, DependsOnTargetsés AfterTargets attribútumok használata határozza meg. A későbbi célok sorrendje befolyásolható egy korábbi cél végrehajtása során, ha a korábbi cél módosítja az attribútumokban hivatkozott tulajdonságot.

A rendelési szabályok le vannak írva a Cél felépítési sorrendjének meghatározásarészben. A folyamatot a létrehozandó célokat tartalmazó veremstruktúra határozza meg. A verem tetején lévő cél elkezdi a végrehajtást, és ha bármi mástól függ, akkor a rendszer ezeket a célokat a verem tetejére küldi, és megkezdi a végrehajtást. Ha egy cél függőségek nélkül van, a végrehajtás befejeződik, és a szülőcél folytatódik.

Projekthivatkozások

Az MSBuild két kódútvonalat használhat, a normált, amelyet itt ismertetünk, és a következő szakaszban leírt gráfbeállítást.

Az egyes projektek ProjectReference elemeken keresztül határozzák meg a más projektektől való függőségüket. Amikor egy verem tetején lévő projekt elkezdi az építést, eljut arra a pontra, ahol a ResolveProjectReferences cél végrehajtódik, ami egy szabványos célként van definiálva a közös célfájlokban.

ResolveProjectReferences meghívja az MSBuild feladatot az ProjectReference elemek bemeneteivel a kimenetek lekéréséhez. A ProjectReference elemek helyi elemekké alakulnak, például Reference. Az aktuális projekt MSBuild végrehajtási fázisa szünetel, miközben a végrehajtási fázis megkezdi a hivatkozott projekt feldolgozását (a kiértékelési fázist szükség szerint először elvégzik). A hivatkozott projekt csak a függő projekt létrehozása után épül fel, így ez létrehozza a projektek egy fáját.

A Visual Studio lehetővé teszi a projektfüggőségek létrehozását a megoldásfájlokban (.sln). A függőségek a megoldásfájlban vannak megadva, és csak a megoldás létrehozásakor, illetve a Visual Studióban való építkezéskor vannak tiszteletben tartva. Ha egyetlen projektet hoz létre, a rendszer figyelmen kívül hagyja ezt a függőségtípust. A megoldáshivatkozásokat az MSBuild ProjectReference elemekké alakítja át, és ezt követően ugyanúgy kezeli őket.

Gráf lehetőség

Ha megadja a gráf összeállítási kapcsolóját (-graphBuild vagy -graph), a ProjectReference az MSBuild által használt első osztályú fogalom lesz. Az MSBuild elemzi az összes projektet, és létrehoz egy tényleges függőségi gráfot, amelyet végigjárva meghatározzák a buildelési sorrendet. Az egyes projektek céljaihoz hasonlóan az MSBuild biztosítja, hogy a hivatkozott projektek az általuk függő projektek után épülnek fel.

Párhuzamos végrehajtás

Ha többprocesszoros támogatást (-maxCpuCount vagy -m kapcsolót) használ, az MSBuild csomópontokat hoz létre, amelyek az elérhető processzormagokat használó MSBuild folyamatok. A program minden projektet elküld egy elérhető csomópontra. Egy csomóponton belül az egyes projekt buildek sorozatosan futnak.

A feladatok párhuzamos végrehajtáshoz engedélyezhetők egy logikai változó BuildInParallelbeállításával, amely az MSBuild $(BuildInParallel) tulajdonságának értéke szerint van beállítva. A párhuzamos végrehajtáshoz engedélyezett feladatok esetében a munkaütemező kezeli a csomópontokat, és a csomópontokhoz rendeli a munkát.

Lásd: Több projekt létrehozása párhuzamosan az MSBuild

Standard importok

Microsoft.Common.props és Microsoft.Common.targets .NET-projektfájlok importálják (explicit módon vagy implicit módon SDK-stílusú projektekben), és a Visual Studio-telepítés MSBuild\Current\bin mappájában találhatók. A C++ projektek saját importálási hierarchiával rendelkeznek; lásd a C++ projektek MSBuild belső mechanizmusait.

A Microsoft.Common.props fájl alapértelmezéseket állít be, amelyeket felülírhat. A projektfájl elején (explicit módon vagy implicit módon) importálja. Így a projekt beállításai az alapértelmezett beállítások után jelennek meg, így felülbírálják őket.

A Microsoft.Common.target fájl és az importált célfájlok határozzák meg a .NET-projektek szabványos buildelési folyamatát. Emellett bővítménypontokat is biztosít, amelyekkel testre szabhatja a buildet.

A implementációban a Microsoft.Common.targets egy vékony burkoló, amely importálja Microsoft.Common.CurrentVersion.targets. Ez a fájl a szabványos tulajdonságok beállításait tartalmazza, és meghatározza a buildelési folyamatot meghatározó tényleges célokat. A Build cél itt van definiálva, de valójában üres. A Build cél azonban tartalmazza a DependsOnTargets attribútumot, amely meghatározza a tényleges buildelési lépéseket alkotó egyéni célokat , amelyek BeforeBuild, CoreBuildés AfterBuild. A Build cél meghatározása a következő:

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

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

BeforeBuild és AfterBuild bővítménypontok. A Microsoft.Common.CurrentVersion.targets.targets üresek fájlban, de a projektek saját BeforeBuild és AfterBuild célokat biztosíthatnak a fő buildelési folyamat előtt vagy után végrehajtandó feladatokkal. AfterBuild a no-op cél előtt fut, Build, mert AfterBuild megjelenik a DependsOnTargets cél Build attribútumában, de CoreBuildután következik be.

A CoreBuild cél a buildelési eszközök hívásait tartalmazza az alábbiak szerint:

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

Az alábbi táblázat ezeket a célokat ismerteti; egyes célok csak bizonyos projekttípusokra alkalmazhatók.

Cél Leírás
BuildOnlySettings Beállítások csak a valódi buildekhez, nem pedig amikor a Visual Studio az MSBuildet hívja meg a projekt betöltésekor.
PrepareForBuild Az építés előfeltételeinek előkészítése
Építés Előtti Esemény Bővítménypont a projektekhez a buildelés előtt végrehajtandó tevékenységek definiálásához
ResolveProjectReferences Projektfüggőségek elemzése és hivatkozott projektek létrehozása
Oldd meg az összeszerelési hivatkozásokat Keresse meg a hivatkozott szerelvényeket.
ResolveReferences ResolveProjectReferences és ResolveAssemblyReferences az összes függőség megkereséséhez
Erőforrások előkészítése Erőforrásfájlok feldolgozása
ResolveKeySource Oldja meg a szerelvény aláírásához használt erős névkulcsot és a ClickOnce jegyzékek aláírásához használt tanúsítványt.
Összeállít Meghívja a fordítót
ExportWindowsMDFile (WindowsMDFájl exportálása) Hozzon létre egy WinMD fájlt a fordító által létrehozott WinMDModule-fájlokból.
Felügyelet nélküli regisztráció-törlés Távolítsa el/törölje a COM Interop beállításjegyzék-bejegyzéseket egy korábbi buildből
Szerializálási összeállítások generálása XML-szerializálási szerelvény létrehozása sgen.exehasználatával.
Mellék-összeszerelések létrehozása Hozzon létre egy műholdi szerelvényt a források minden egyedi kultúrájához.
Jegyzékek létrehozása Létrehoz ClickOnce alkalmazás- és üzembehelyezési jegyzékeket vagy egy natív jegyzékfájlt.
GetTargetPath Adjon vissza egy elemet, amely tartalmazza ennek a projektnek az építési termékét (végrehajtható fájl vagy összeállítás) metaadatokkal.
PrepareForRun Ha módosultak, másolja a buildkimeneteket a végső könyvtárba.
Kezelés nélküli regisztráció Beállításjegyzék-bejegyzések beállítása COM Interop
Növekményes Tisztítás Távolítsa el azokat a fájlokat, amelyek egy korábbi buildben készültek, de nem az aktuális buildben lettek létrehozva. Ez szükséges ahhoz, hogy Clean növekményes buildekben működjön.
Építés utáni esemény Bővítménypont a projektekhez a buildelés után futtatandó tevékenységek definiálásához

Az előző táblázatban szereplő célok közül sok nyelvspecifikus importálásban található, például Microsoft.CSharp.targets. Ez a fájl a C# .NET-projektekre vonatkozó szabványos buildelési folyamat lépéseit határozza meg. Tartalmazza például azt a Compile célt, amely ténylegesen meghívja a C# fordítót.

Felhasználó által konfigurálható importálás

A szabványos importálások mellett számos importálást is hozzáadhat a buildelési folyamat testreszabásához.

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

Ezeket a fájlokat bármelyik almappában található projektekhez a standard importálások olvassák be. Ez általában a megoldás szintjén fordul elő, hogy a beállítások a megoldás összes projektjét szabályozzák, de a fájlrendszerben is magasabbak lehetnek a meghajtó gyökerétől.

A Directory.Build.props fájlt Microsoft.Common.propsimportálja, így az abban meghatározott tulajdonságok elérhetők a projektfájlban. A projektfájlban újra definiálhatók az értékek projektenkénti testreszabásához. Az Directory.Build.targets fájlt a projektfájl után olvassák be. Általában tartalmaz célokat, de itt olyan tulajdonságokat is meghatározhat, amelyeket nem szeretne újradefiniolni az egyes projektekben.

A projektfájl testreszabásai

A Visual Studio a Megoldáskezelő, a Tulajdonságok ablakban vagy projekttulajdonságokmódosításával frissíti a projektfájlokat, de saját módosításokat is végezhet a projektfájl közvetlen szerkesztésével.

Számos buildelési viselkedés konfigurálható az MSBuild tulajdonságok beállításával, akár a projektfájlban a projekthez tartozó beállításokhoz, akár az előző szakaszban említett módon, ha létrehoz egy Directory.Build.props fájlt, amely globálisan beállítja a tulajdonságokat a projektek és megoldások teljes mappáihoz. A parancssorra vagy szkriptekre épülő alkalmi buildek esetében a parancssor /p beállításával is beállíthat tulajdonságokat az MSBuild adott meghívásához. Az MSBuild projekttulajdonságok részén talál információt a beállítható tulajdonságokról.