Erweitern des Erstellungsprozesses mit MSBuild

Der Artikel soll ein wenig über MSBuild erzählen, zeigen, welche Ziele und Aufgaben in MSBuild enthalten sind, wie man mit einer .csproj-Datei arbeitet und nützliche Links bereitstellt. Wenn Sie einen passenderen Titel für den Artikel haben, werde ich gerne in den Kommentaren diskutieren.

Menü



Grundbegriffe ( Menü )


MSBuild ist so konzipiert, dass die Montage des Projekts in mehrere Phasen unterteilt ist.

Ziel ist eine bestimmte Phase (Ereignis), die während der Montage eines Projekts auftritt. Sie können Standardziele verwenden oder eigene definieren.

Aufgabe ist eine Aufgabe, die zu einem bestimmten Zeitpunkt ausgeführt werden kann. Sie können Standardaufgaben verwenden oder eigene erstellen.

Zitat aus der Dokumentation zum Targeting ( https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-targets ):
Zielt darauf ab, Aufgaben in einer bestimmten Reihenfolge zu gruppieren und den Erstellungsprozess in kleinere Einheiten zu zerlegen.
Beispielsweise kann ein Ziel alle Dateien im Ausgabeverzeichnis löschen, um den Build vorzubereiten, während ein anderes Ziel
Kompiliert die Eingaben für das Projekt und legt sie im leeren Verzeichnis ab.

MSBuild Build Lifecycle ( Menü )


Für MSBuild hat Microsoft eine Reihe von Standardzielen definiert (in den Dateien Microsoft.Common.targets, Microsoft.CSharp.targets usw.). Eine große Anzahl verschiedener Ziele ist definiert, aber in diesem Artikel werden wir nicht im Detail darauf eingehen. Einige Standardziele (bestellt):

Zielliste (Spoiler)
  • Vor dem Bau
  • Sauber
  • Vor dem Bau
  • BuildOnlySettings
  • PrepareForBuild
  • PreBuildEvent
  • ResolveReferences
  • PrepareResources
  • ResolveKeySource
  • Kompilieren
  • Nicht verwaltete Registrierung
  • GenerateSerializationAssemblies
  • CreateSatelliteAssemblies
  • GenerateManifests
  • GetTargetPath
  • PrepareForRun
  • Nicht verwaltete Registrierung
  • Inkrementell sauber
  • PostBuildEvent
  • Nachbau
  • Nachbau


Die Ziele BeforeBuild und AfterBuild wurden speziell zum Überschreiben entwickelt und können verwendet werden. Ich empfehle nicht, die verbleibenden Ziele aus der Liste zu verwenden, damit nichts kaputt geht .

Für eine detailliertere Ansicht der Liste der Ziele können Sie die Option / pp: verwenden . Dank dieses Parameters wird eine Datei generiert, in der alle Importe enthalten sind (einschließlich .targets-Dateien). Sie können viele Ziele und Variablen darin finden (danke aikixd für den Tipp).


Vorbereiten der Umgebung für Beispiele ( Menü )


Zum Beispiel benötigen Sie:

  • Installierte Entwicklungsumgebung von Visual Studio
  • Erstellen Sie ein Projekt vom Typ Konsolenanwendung mit dem Namen MSBuildExample
  • Öffnen Sie den Projektordner und suchen Sie dort die Datei MSBuildExample.csproj
  • Öffnen Sie die Datei MSBuildExample.csproj im Editor oder einem anderen Editor

In allen Beispielen in diesem Artikel müssen Sie die Datei MSBuildExample.csproj bearbeiten. In jedem Beispiel wird der Code aus dem vorherigen Beispiel entfernt und ein neuer hinzugefügt. Der Code muss am Ende der .csproj-Datei in die letzte Zeile mit dem schließenden Project-Tag eingefügt werden.

Bild

Achtung! In einer .csproj-Datei ist der Fall wichtig .
Um das Beispiel auszuführen, müssen Sie build in der Visual Studio-Entwicklungsumgebung ausführen. Für einige Beispiele müssen Sie eine Lösungskonfiguration auswählen.

Bild

Das Ergebnis wird im Ausgabefenster von Visual Studio (unten) angezeigt. Ist dies nicht der Fall, öffnen Sie es über die Menüpunkte Ansicht => Ausgabe.

Bild


Targeting in MSBuild ( Menü )


Zum Beispiel verwenden wir die Nachrichtenaufgabe , die Informationen im Ausgabefenster in Visual Studio anzeigt. Wie bereits erwähnt, gibt es Standardziele BeforeBuild und AfterBuild, die wir verwenden werden. Lesen Sie zum Training den Abschnitt Vorbereiten der Umgebung für Beispiele .

Beispiel für die Zielnutzung (Spoiler)
Beispielcode:

<Target Name="AfterBuild"> <Message Text="AfterBuild event" Importance="high"></Message> </Target> <Target Name="BeforeBuild"> <Message Text="BeforeBuild event" Importance="high"></Message> </Target> 

Ausführungsergebnis (unnötig ausgeschlossen):
...
Vor dem Build-Event
...
Afterbuild-Ereignis
...


Wie Sie sehen, wurde die Tasknachricht ausgeführt, in der der Text angezeigt wurde, den wir zum Zeitpunkt von BeforeBuild und AfterBuild im Ausgabefenster von Visual Studio angegeben haben.
Wenn Sie ein Ziel mit demselben Namen definieren, wird es überschrieben!

Beispiel für das Umschreiben von Zielen (Spoiler)
Beispielcode:

 <Target Name="BeforeBuild"> <Message Text="First message" Importance="high"></Message> </Target> <Target Name="BeforeBuild"> <Message Text="Second message" Importance="high"></Message> </Target> 

Ausführungsergebnis (unnötig ausgeschlossen):
...
Zweite Nachricht
...


Es wurde nur die zweite Nachricht angezeigt, da sie Ziele mit demselben Namen verwendeten und diese durch den zweiten Wert überschrieben wurden.

Erstellen eines eigenen MSBuild-Ziels ( Menü )


Wenn die Ziele BeforeBuild und AfterBuild nicht ausreichen oder die Aufgaben in einer anderen Phase des Baugruppenlebenszyklus ausgeführt werden sollen, können Sie Ihr eigenes Ziel definieren. Für diese Zwecke gibt es die Parameter BeforeTargets und AfterTargets.

Beispiel für die Definition eigener Ziele (Spoiler)
Beispielcode:

  <Target Name="BeforeBuild"> <Message Text="BeforeBuild event" Importance="high"></Message> </Target> <Target Name="MyCustomBeforeTarget" BeforeTargets="BeforeBuild"> <Message Text="MyCustomBeforeTarget event" Importance="high"></Message> </Target> <Target Name="MyCustomAfterTarget" AfterTargets="BeforeBuild"> <Message Text="MyCustomAfterTarget event" Importance="high"></Message> </Target> 

Ausführungsergebnis (unnötig ausgeschlossen):
...
MyCustomBeforeTarget-Ereignis
Vor dem Build-Event
MyCustomAfterTarget-Ereignis
...


Es wurden zwei benutzerdefinierte Ziele definiert - MyCustomBeforeTarget und MyCustomAfterTarget.
Das MyCustomBeforeTarget-Ziel wird vor dem BeforeBuild-Ziel ausgeführt, da wir Folgendes angegeben haben:

 BeforeTargets="BeforeBuild" 

Das MyCustomAfterTarget-Ziel wird nach dem BeforeBuild-Ziel ausgeführt, da wir Folgendes angegeben haben:

 AfterTargets="BeforeBuild" 

Aufgaben in MSBuild ( Menü )


In diesem Artikel wird nicht erläutert, wie Sie Ihre eigenen Aufgaben schreiben können. Bevor Sie jedoch Aufgaben schreiben , lesen Sie die Liste der von Microsoft bereitgestellten Aufgaben .

Schauen wir uns einige Beispiele für die Verwendung von Aufgaben und Makros an.

Bedingungsparameter (Spoiler)
Der Parameter Bedingung ist in allen Aufgaben vorhanden. Zitat aus der Dokumentation docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-task-reference :
Ein boolescher Ausdruck, mit dem die MSBuild-Engine bestimmt, ob diese Aufgabe ausgeführt wird.
Beispielcode:

 <Target Name="BeforeBuild"> <Message Text="Current configuration is Debug" Condition="'$(Configuration)' == 'Debug'" Importance="high"></Message> <Message Text="Current configuration is Release" Condition="'$(Configuration)' == 'Release'" Importance="high"></Message> </Target> 

Wenn die Debug-Konfigurationslösung ausgewählt ist, sieht das Ergebnis folgendermaßen aus (unnötig ausgeschlossen):
...
Die aktuelle Konfiguration ist Debug
...
Wenn die Lösungskonfiguration Release ausgewählt ist, sieht das Ergebnis folgendermaßen aus (unnötig ausgeschlossen):
...
Die aktuelle Konfiguration ist Release
...
Informationen zum Makro $ (Konfiguration) und zu anderen Makros finden Sie im Abschnitt zu Variablen und Makros in .csproj .

Informationen zur Syntax von Bedingungen finden Sie dort https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-conditions

Variablendefinition in csproj (Spoiler)
Im obigen Beispiel haben wir Text, der vereinheitlicht werden kann. Um Doppelarbeit zu vermeiden, platzieren wir den Nachrichtentext in einer separaten Variablen.

Beispielcode:

 <PropertyGroup> <MessageText>Current configuration is $(Configuration)</MessageText> </PropertyGroup> <Target Name="BeforeBuild"> <Message Text="$(MessageText)" Condition="'$(Configuration)' == 'Debug'" Importance="high"></Message> <Message Text="$(MessageText)" Condition="'$(Configuration)' == 'Release'" Importance="high"></Message> </Target> 

Verwenden Sie das PropertyGroup- Element, um Ihre eigene Variable zu definieren.


Überprüfen der Existenz einer Datei, Ausgabe eines Fehlers (Spoiler)
In diesem Beispiel erstellen wir eine Aufgabe, die überprüft, ob die Datei App.Debug.config erstellt wurde. Wenn es nicht erstellt wird, werfen wir einen Fehler. Im Fehlerfall wird der Build gestoppt und der Fehler als Kompilierungsfehler im Fenster Fehlerliste angezeigt.
Wir verwenden die Fehleraufgabe und den uns bereits bekannten Bedingungsparameter.

Beispielcode:

 <Target Name="BeforeBuild"> <Error Condition="!Exists('App.Debug.config')" Text="File App.Debug.config not found"></Error> </Target> 

Ergebnis:
Bild

Die Exists-Klausel verwendet den relativen Pfad aus dem Ordner, in dem sich die .csproj-Datei befindet. Um auf den Ordner über dem aktuellen zuzugreifen, verwenden Sie '../'. Wenn Sie auf den Unterordner zugreifen müssen, verwenden Sie das Format '[Verzeichnisname] /App.Debug.config'.

Dateien kopieren (Spoiler)
In diesem Beispiel verwenden wir die Aufgabe " Kopieren" . Kopieren Sie mithilfe der Task die Datei App.config in den Ordner bin / [Configuration] / Config in die beiden Dateien App.config und App.test.config.

Beispielcode:

 <Target Name="BeforeBuild"> <Copy SourceFiles="App.config;App.config" DestinationFiles="$(OutputPath)/Test/App.config;$(OutputPath)/Test/App.test.config"></Copy> </Target> 

Die SourceFiles-Eigenschaft ist ein Array von Dateien, die heruntergeladen werden sollen. Geben Sie ohne Anführungszeichen an, getrennt durch Semikolons.

Die DestinationFiles-Eigenschaft ist ein Array von Dateien, in die Dateien kopiert werden. Geben Sie ohne Anführungszeichen an, getrennt durch Semikolons.

Weitere Informationen zum Makro $ (OutputPath) finden Sie im Abschnitt zu Variablen und Makros in .csproj .

Variablen und Makros in .csproj ( Menü )


In der .csproj-Datei können eine Reihe von Standardmakros verwendet werden. Eine Liste davon finden Sie hier https://msdn.microsoft.com/en-us/library/c02as0cs.aspx und hier https://msdn.microsoft.com/en-us/ library / bb629394.aspx . Betrachten Sie einige nützliche Makros:

  • $ (MSBuildToolsPath) - Gibt den Pfad zum MSBuild-Ordner an. Beispiel: C: \ Programme (x86) \ MSBuild \ 14.0 \ Bin. Verwenden Sie dieses Makro beim Kombinieren eines Pfads mit einem Schrägstrich. Beispiel: $ (MSBuildToolsPath) \ Microsoft.Web.Publishing.Tasks.dll. Andernfalls wird der Pfad möglicherweise falsch gebildet und es wird ein Fehler angezeigt, dass die Datei nicht gefunden wurde.
  • $ (OutputPath) - relativer Pfad zum Ausgabeordner. Zum Beispiel bin \ Stage. Verwenden Sie dieses Makro mit einem Schrägstrich, z. B. $ (OutputPath) \ $ (TargetFileName) .config.
  • $ (TargetFileName) - Der Name der Ausgabedatei mit der Erweiterung. Zum Beispiel MSBuildExample.exe. Die Erweiterung und das Format des Ausgabedateinamens können sich von verschiedenen Projekttypen unterscheiden. Mit diesem Makro können Sie sicher bestimmen, wie der Name der Konfigurationsdatei lautet. Dies kann für Konfigurationstransformationen hilfreich sein.
  • $ (Konfiguration) ist der Name der aktuellen Konfiguration. Zum Beispiel Release, Debug
  • $ (IntermediateOutputPath) - Pfad zum Ordner obj. Zum Beispiel obj \ Stage.

Verwenden Sie die PropertyGroup, um Ihre eigenen Parameter zu definieren. Ein Beispiel für die Definition Ihrer eigenen Variablen finden Sie im Aufgabenbereich in MSBuild .

Links ( Menü )


Source: https://habr.com/ru/post/de414969/


All Articles