2017-12-27 6 views
0

Ich habe eine große Lösung, die aus 50+ Klassenbibliotheken und ~ 10 SharePoint WSP-Projekten besteht. Ich versuche, die Build-Zeiten zu optimieren, da es standardmäßig 5+ Minuten auf einer anständigen Server-Hardware dauert.Erstellen Sie eine Lösung mit Zielen, die nur in einer Teilmenge von Projekten in der Lösung vorhanden sind.

Derzeit arbeitet der Build-Prozess wie dieser (Pseudo-Code):

MSBuild.exe MySolution.sln /T:Clean 
MSBuild.exe MySolution.sln /T:Build 
foreach (Project.csproj in *.csproj where is WSP project) 
{ 
    MSBuild.exe Project.csproj /T:CleanPackage 
    MSBuild.exe Project.csproj /T:Package 
} 

Was ich will, erreichen, ist dies alles zu tun, um einen einzelnen MSBuild.exe Aufruf verwenden, so dass der Erstellungsprozess parallelisiert werden kann und Verarbeitung duplizieren wird vermieden, wenn die WSP-Projekte verpackt werden.

ich dies leicht für einen einzigen WSP Projekt tun können:

MSBuild.exe Project.csproj /T:Clean;CleanPackage;Build;Package 

Wenn jedoch muss ich das gleiche für die ganze Lösung:

MSBuild.exe MySolution.sln /T:Clean;CleanPackage;Build;Package 

MSBuild fehlschlägt und meldet Fehler, sobald es findet ein Projekt in der Lösungsdatei, die das CleanPackage Ziel nicht enthält:

D: \ MySolution \ Clas s.Library.Project \ Class.Library.Project.csproj: Fehler MSB4057: Das Ziel "CleanPackage" existiert nicht im Projekt.

Also, die Frage ist, wie dieses Problem zu überwinden und einen Single-Kommandozeilen-Build-Aufruf ohne a) macht manuelle Änderungen an alle csproj Dateien (Wartung Alptraum), b) Schreiben Sie einen benutzerdefinierter komplizierte Build-Skript erreichen ? Ich dachte daran, eine Master-Build-Datei zu definieren, die eine einzige benutzerdefinierte enthalten würde. Ich bin mir jedoch nicht sicher, wie ich die richtigen Abhängigkeiten zu Projekten in der Lösungsdatei ausdrücken kann, ohne alle einzelnen Projekte in zwei Gruppen (Klassenbibliotheken, WSP-Projekte) manuell aufzulisten.


Hinweis: Während meine Frage an this one ähnlich ist, habe ich beschlossen, sie zu öffnen und zu halten, selbst beantworten, um die Leistungsergebnisse zu decken.

+0

Beginnen Sie mit der Beschleunigung des Build (etwas), indem Sie das Rebuild-Ziel aufrufen, anstatt msbuild zweimal mit Clean/Build aufzurufen, das Endergebnis ist das gleiche. Für den anderen Teil: sollte ein ziemlich einfaches MSbuild-Master-Skript sein, aber müssen die Projekte mit dem Paket-Ziel in einer bestimmten Reihenfolge aufgerufen werden? Sind sie abhängig vom Package-Ziel oder nur vom Build-Ziel? – stijn

+0

@stijn (1) 'Rebuild': kleines Detail, nicht genau das Problem, das ich löse, und etwas, das ich bereits losgeworden bin. (2) Nein, sie sind nicht voneinander abhängig. Ein SharePoint WSP-Paket ist das Endprodukt - etwas, das eine 'exe'-Zeile darstellt. Jede von ihnen hängt jedoch von mehreren Klassenbibliotheksprojekten in der Lösung ab. –

+0

@stijn Mit anderen Worten, was ich brauche mit Hilfe ist das "ziemlich einfache MSbuild-Master-Skript", als dies ein Werkzeug, das ich nicht das Bedürfnis hatte, viel unter die Haube zu gehen. –

Antwort

0

Wie in den Kommentaren darauf hingewiesen, bietet this answer einen guten Weg, um das zu erreichen, was ich brauchte. Der Umfang meiner Frage ist jedoch etwas breiter und konzentriert sich auf die Build-Leistung. Daher enthält diese Antwort auch andere Ergebnisse und Ergebnisse.

Mein zusätzliche Build-Skript sieht wie folgt aus:

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

    <!-- Enforce "Copy Local = false" on all references --> 
    <ItemDefinitionGroup> 
    <Reference> 
     <Private>False</Private> 
    </Reference> 
    </ItemDefinitionGroup> 

    <!-- substitute empty CleanPackage and Package targets to each project in case there is no actual implementation --> 
    <Target Name="CleanPackage" /> 
    <Target Name="Package" /> 
</Project> 

Ich habe auch eine Überschreibung „Copy Local“ zu false erzwingen, so dass das Kopieren von referenzierten Sharepoint-Baugruppen vermieden wird. Diese einzige Einstellung allein eliminiert das Kopieren von 3,2 GB (!) von DLLs und zugehörigen Dateien auf die Ausgabe von Ordnern während des Build-Prozesses. Ich halte dies noch für experimentell und benötige eine Feinabstimmung, da ich davon ausgehe, dass bestimmte Debugging- und Unit-Testing-Szenarien möglicherweise nicht mehr funktionieren.

Am Ende funktioniert der Aufruf der einzelnen Befehlszeile von MSBuild. Ein zusätzlicher Parameter ist erforderlich, um einen Verweis auf das zusätzliche Build-Skript zu übergeben.

MSBuild.exe MySolution.sln /T:Clean;CleanPackage;Build;Package /p:CustomBeforeMicrosoftCommonTargets=D:\MySolution\package.targets 

konnte ich Bauzeiten von 301 Sekunden reduzieren auf durchschnittlich 40,5 Sekunden, eine 86,5% ige Verbesserung. Die Build-Sequenzen I verwendet werden, sind:

Build sequence without packaging   Avg [sec] Improvement 
---------------------------------------- ---------- -------------- 
sequential 1xClean, 1xBuild (no package)  124.3 
parallel 1xClean, 1xBuild      58.0 -74.1 (-59.6%) 

Build sequence with packaging    Avg [sec] Improvement 
---------------------------------------- ---------- -------------- 
sequential 1xClean, 1xBuild, NxPackage   301.0 
parallel 1xClean+Build, 1xCleanP+Package  111.0 -190.0 (-63.1%) 
parallel 1xClean+Build+CleanP+Package   83.0 -218.0 (-72.4%) 
parallel optimized (Copy Local=false)   40.5 -260.5 (-86.5%) 

Hinweise:

  • parallel bedeutet, dass der /m Schalter
  • angewendet
  • CleanP ist die Abkürzung für CleanPackage
  • „Copy Local“ ist true außer in der schnellsten bauen

Hardware: Eine WS2016-VM mit 16 GB RAM, 24 vCPUs auf einem Dual-Xeon E5-2695 v2 Hyper-V-Server.

Verwandte Themen