Rozšíření procesu sestavení sady Visual Studio
Proces sestavení sady Visual Studio je definován řadou souborů MSBuild .targets
, které se importují do souboru projektu. Tyto importy jsou implicitní, pokud jako projekty sady Visual Studio obvykle používáte sadu SDK. Jeden z těchto importovaných souborů, Microsoft.Common.targets, je možné rozšířit, abyste mohli spouštět vlastní úlohy v několika bodech procesu sestavení. Tento článek vysvětluje tři metody, které můžete použít k rozšíření procesu sestavení sady Visual Studio:
Vytvořte vlastní cíl a určete, kdy se má spustit pomocí
BeforeTargets
aAfterTargets
atributů.DependsOn
Přepište vlastnosti definované v běžných cílech.Přepište konkrétní předdefinované cíle definované ve společných cílech (Microsoft.Common.targets nebo soubory, které importuje).
AfterTargets and BeforeTargets
Pomocí atributů vlastního BeforeTargets
cíle můžete AfterTargets
určit, kdy se má spustit.
Následující příklad ukazuje, jak pomocí atributu AfterTargets
přidat vlastní cíl, který něco dělá s výstupními soubory. V tomto případě zkopíruje výstupní soubory do nové složky CustomOutput. Příklad také ukazuje, jak vyčistit soubory vytvořené vlastní operací sestavení s CustomClean
cílem pomocí atributu BeforeTargets
a určit, že se vlastní čistá operace spustí před CoreClean
cílem.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<_OutputCopyLocation>$(OutputPath)..\..\CustomOutput\</_OutputCopyLocation>
</PropertyGroup>
<Target Name="CustomAfterBuild" AfterTargets="Build">
<ItemGroup>
<_FilesToCopy Include="$(OutputPath)**\*"/>
</ItemGroup>
<Message Text="_FilesToCopy: @(_FilesToCopy)" Importance="high"/>
<Message Text="DestFiles:
@(_FilesToCopy->'$(_OutputCopyLocation)%(RecursiveDir)%(Filename)%(Extension)')"/>
<Copy SourceFiles="@(_FilesToCopy)"
DestinationFiles=
"@(_FilesToCopy->'$(_OutputCopyLocation)%(RecursiveDir)%(Filename)%(Extension)')"/>
</Target>
<Target Name="CustomClean" BeforeTargets="CoreClean">
<Message Text="Inside Custom Clean" Importance="high"/>
<ItemGroup>
<_CustomFilesToDelete Include="$(_OutputCopyLocation)**\*"/>
</ItemGroup>
<Delete Files='@(_CustomFilesToDelete)'/>
</Target>
</Project>
Upozorňující
Nezapomeňte použít jiné názvy než předdefinované cíle (například vlastní cíl sestavení zde není CustomAfterBuild
AfterBuild
), protože tyto předdefinované cíle jsou přepsány importem sady SDK, který je také definuje. Seznam předdefinovaných cílů najdete v tabulce na konci tohoto článku.
Rozšíření vlastností DependsOn
Dalším způsobem, jak rozšířit proces sestavení, je použít DependsOn
vlastnosti (například BuildDependsOn
) k určení cílů, které se mají spustit před standardním cílem.
Tato metoda je vhodnější k přepsání předdefinovaných cílů, které jsou popsány v další části. Přepsání předdefinovaných cílů je starší metoda, která je stále podporovaná, ale vzhledem k tomu, že nástroj MSBuild vyhodnocuje definici cílů postupně, neexistuje způsob, jak zabránit dalšímu projektu, který importuje projekt v přepsání cílů, které jste už přepsali. Například poslední AfterBuild
cíl definovaný v souboru projektu bude po importu všech ostatních projektů ten, který se použije během sestavení.
Před nezamýšlenými přepsáními cílů můžete chránit přepsáním DependsOn
vlastností používaných v DependsOnTargets
atributech v rámci společných cílů. Například Build
cíl obsahuje hodnotu atributu DependsOnTargets
"$(BuildDependsOn)"
. Rozmyslete si:
<Target Name="Build" DependsOnTargets="$(BuildDependsOn)"/>
Tato část XML označuje, že před spuštěním Build
cíle musí být nejprve spuštěny všechny cíle zadané ve BuildDependsOn
vlastnosti. Vlastnost BuildDependsOn
je definována takto:
<PropertyGroup>
<BuildDependsOn>
$(BuildDependsOn);
BeforeBuild;
CoreBuild;
AfterBuild
</BuildDependsOn>
</PropertyGroup>
Tuto hodnotu vlastnosti můžete přepsat deklarováním jiné vlastnosti pojmenované BuildDependsOn
na konci souboru projektu. V projektu stylu sady SDK to znamená, že musíte použít explicitní importy. Viz Implicitní a explicitní importy, abyste mohli vlastnost umístit DependsOn
po posledním importu. Zahrnutím předchozí BuildDependsOn
vlastnosti do nové vlastnosti můžete přidat nové cíle na začátek a konec cílového seznamu. Příklad:
<PropertyGroup>
<BuildDependsOn>
MyCustomTarget1;
$(BuildDependsOn);
MyCustomTarget2
</BuildDependsOn>
</PropertyGroup>
<Target Name="MyCustomTarget1">
<Message Text="Running MyCustomTarget1..."/>
</Target>
<Target Name="MyCustomTarget2">
<Message Text="Running MyCustomTarget2..."/>
</Target>
Projekty, které importují váš soubor projektu, mohou dále rozšířit tyto vlastnosti bez přepsání vlastních nastavení, která jste provedli.
Přepsání vlastnosti DependsOn
Identifikujte předdefinovanou
DependsOn
vlastnost v běžných cílech, které chcete přepsat. Seznam běžně přepsanýchDependsOn
vlastností najdete v následující tabulce.Na konci souboru projektu definujte jinou instanci vlastnosti nebo vlastností. Do nové vlastnosti zahrňte původní vlastnost, například
$(BuildDependsOn)
.Definujte vlastní cíle před definicí vlastnosti nebo za ji.
Sestavte soubor projektu.
Běžně přepsané vlastnosti DependsOn
Název vlastnosti | Přidané cíle se spouštějí před tímto bodem: |
---|---|
BuildDependsOn |
Hlavní vstupní bod sestavení. Tuto vlastnost přepište, pokud chcete vložit vlastní cíle před nebo za celý proces sestavení. |
RebuildDependsOn |
Rebuild |
RunDependsOn |
Spuštění konečného výstupu sestavení (pokud se jedná o .EXE) |
CompileDependsOn |
Kompilace (Compile cíl). Tuto vlastnost přepište, pokud chcete vložit vlastní procesy před nebo za krok kompilace. |
CreateSatelliteAssembliesDependsOn |
Vytvoření satelitních sestavení |
CleanDependsOn |
Cíl Clean (odstranění všech průběžných a konečných výstupů sestavení) Tuto vlastnost přepište, pokud chcete vyčistit výstup z vlastního procesu sestavení. |
PostBuildEventDependsOn |
Cíl PostBuildEvent |
PublishBuildDependsOn |
Publikování sestavení |
ResolveAssemblyReferencesDependsOn |
Cíl ResolveAssemblyReferences (nalezení přechodného uzavření závislostí pro danou závislost). Viz třída ResolveAssemblyReference . |
Příklad: BuildDependsOn a CleanDependsOn
Následující příklad je podobný jako v příkladu BeforeTargets
, AfterTargets
ale ukazuje, jak dosáhnout podobných funkcí. Rozšiřuje sestavení pomocí BuildDependsOn
přidat vlastní úlohu CustomAfterBuild
, která zkopíruje výstupní soubory po sestavení, a také přidá odpovídající CustomClean
úlohu pomocí CleanDependsOn
.
V tomto příkladu se jedná o projekt ve stylu sady SDK. Jak je uvedeno v poznámce o projektech ve stylu sady SDK dříve v tomto článku, musíte místo atributu, který Sada Visual Studio používá při generování souborů projektu, použít metodu ručního Sdk
importu.
<Project>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk"/>
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk"/>
<PropertyGroup>
<BuildDependsOn>
$(BuildDependsOn);CustomAfterBuild
</BuildDependsOn>
<CleanDependsOn>
$(CleanDependsOn);CustomClean
</CleanDependsOn>
<_OutputCopyLocation>$(OutputPath)..\..\CustomOutput\</_OutputCopyLocation>
</PropertyGroup>
<Target Name="CustomAfterBuild">
<ItemGroup>
<_FilesToCopy Include="$(OutputPath)**\*"/>
</ItemGroup>
<Message Importance="high" Text="_FilesToCopy: @(_FilesToCopy)"/>
<Message Text="DestFiles:
@(_FilesToCopy->'$(_OutputCopyLocation)%(RecursiveDir)%(Filename)%(Extension)')"/>
<Copy SourceFiles="@(_FilesToCopy)"
DestinationFiles="@(_FilesToCopy->'$(_OutputCopyLocation)%(RecursiveDir)%(Filename)%(Extension)')"/>
</Target>
<Target Name="CustomClean">
<Message Importance="high" Text="Inside Custom Clean"/>
<ItemGroup>
<_CustomFilesToDelete Include="$(_OutputCopyLocation)**\*"/>
</ItemGroup>
<Delete Files="@(_CustomFilesToDelete)"/>
</Target>
</Project>
Pořadí prvků je důležité. Prvky BuildDependsOn
a CleanDependsOn
prvky se musí zobrazit po importu standardního souboru cílů sady SDK.
Přepsání předdefinovaných cílů
Společné .targets
soubory obsahují sadu předdefinovaných prázdných cílů, které se volají před a po některých hlavních cílech v procesu sestavení. Nástroj MSBuild například volá BeforeBuild
cíl před hlavním CoreBuild
cílem a AfterBuild
cílem za CoreBuild
cílem. Prázdné cíle ve společných cílech ve výchozím nastavení nedělají nic, ale jejich výchozí chování můžete přepsat definováním požadovaných cílů v souboru projektu. Upřednostňované jsou metody popsané výše v tomto článku, ale můžete narazit na starší kód, který tuto metodu používá.
Pokud váš projekt používá sadu SDK (například Microsoft.Net.Sdk
), musíte provést změnu z implicitního na explicitní import, jak je popsáno v explicitních a implicitních importech.
Přepsání předdefinovaného cíle
Pokud projekt používá
Sdk
atribut, změňte ho na explicitní syntaxi importu. Viz explicitní a implicitní importy.Určete předdefinovaný cíl v běžných cílech, které chcete přepsat. Úplný seznam cílů, které můžete bezpečně přepsat, najdete v následující tabulce.
Definujte cíl nebo cíle na konci souboru projektu bezprostředně před značkou
</Project>
a po explicitním importu sady SDK. Příklad:<Project> <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" /> ... <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" /> <Target Name="BeforeBuild"> <!-- Insert tasks to run before build here --> </Target> <Target Name="AfterBuild"> <!-- Insert tasks to run after build here --> </Target> </Project>
Všimněte si, že
Sdk
atribut v elementu nejvyšší úrovněProject
byl odebrán.Sestavte soubor projektu.
Tabulka předdefinovaných cílů
V následující tabulce jsou uvedeny všechny cíle ve společných cílech, které můžete přepsat.
Cílový název | Popis |
---|---|
BeforeCompile , AfterCompile |
Úlohy vložené do jednoho z těchto cílů se spouští před nebo po dokončení kompilace jádra. Většina přizpůsobení se provádí v jednom z těchto dvou cílů. |
BeforeBuild , AfterBuild |
Úkoly vložené do jednoho z těchto cílů se spustí před nebo za vším ostatním v sestavení. Poznámka: Cíle BeforeBuild jsou AfterBuild již definovány v komentářích na konci většiny souborů projektu, což vám umožní snadno přidávat události před sestavením do souboru projektu. |
BeforeRebuild , AfterRebuild |
Úlohy vložené do jednoho z těchto cílů se spouští před nebo po vyvolání základní funkce opětovného sestavení. Pořadí provádění cíle v Microsoft.Common.targets je: BeforeRebuild , Clean Build , a pak AfterRebuild . |
BeforeClean , AfterClean |
Úlohy vložené do jednoho z těchto cílů se spustí před nebo po vyvolání základních čistých funkcí. |
BeforePublish , AfterPublish |
Úlohy vložené do jednoho z těchto cílů se spustí před nebo po vyvolání základní funkce publikování. |
BeforeResolveReferences , AfterResolveReferences |
Úlohy vložené do jednoho z těchto cílů se spustí před nebo po vyřešení odkazů na sestavení. |
BeforeResGen , AfterResGen |
Úlohy vložené do jednoho z těchto cílů se spouštějí před nebo po vygenerování prostředků. |
V systému sestavení a sadě .NET SDK existuje mnoho dalších cílů, viz cíle NÁSTROJE MSBuild – SADA SDK a výchozí cíle sestavení.
Osvědčené postupy pro vlastní cíle
Vlastnosti DependsOnTargets
a BeforeTargets
oba můžou určit, že cíl musí běžet před jiným cílem, ale oba jsou potřeba v různých scénářích. Liší se v tom, ve kterém cílí požadavek na závislost. Máte kontrolu nad vlastními cíli a nemůžete bezpečně upravovat systémové cíle ani jiný importovaný cíl, aby se tím vybrali metody.
Při vytváření vlastního cíle postupujte podle těchto obecných pokynů, abyste zajistili, že se cíl spustí v zamýšleném pořadí.
Pomocí atributu
DependsOnTargets
určete cíle, které je nutné provést před spuštěním cíle. Pro řetězec cílů, které řídíte, může každý cíl určit předchozí člen řetězce vDependsOnTargets
.Použijte
BeforeTargets
pro jakýkoli cíl, který neřídíte, než je nutné provést (napříkladBeforeTargets="PrepareForBuild"
pro cíl, který je potřeba spustit dříve v sestavení).Použijte
AfterTargets
pro jakýkoli cíl, který neřídíte, které zaručuje, že jsou výstupy, které potřebujete, k dispozici. Zadejte například něco,AfterTargets="ResolveReferences"
co změní seznam odkazů.Můžete je použít v kombinaci. Například
DependsOnTargets="GenerateAssemblyInfo" BeforeTargets="BeforeCompile"
.
Explicitní a implicitní importy
Projekty generované sadou Visual Studio obvykle používají Sdk
atribut elementu projektu. Tyto typy projektů se nazývají projekty ve stylu sady SDK. Viz Použití sad SDK projektu MSBuild. Tady je příklad:
<Project Sdk="Microsoft.Net.Sdk">
Když váš projekt používá Sdk
atribut, přidají se implicitně dva importy, jeden na začátku souboru projektu a jeden na konci.
Implicitní importy jsou ekvivalentní tomu, že jako první řádek v souboru projektu za elementem mají podobný příkaz importu Project
:
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
a následující příkaz importu jako poslední řádek v souboru projektu:
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
Tato syntaxe se označuje jako explicitní import sady SDK. Pokud použijete tuto explicitní syntaxi, měli byste vynechat Sdk
atribut elementu projektu.
Implicitní import sady SDK je ekvivalentní importu konkrétních "běžných" .props
nebo .targets
souborů, které jsou typickým konstruktorem ve starších souborech projektu, například:
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
a
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Všechny takové staré odkazy by se měly nahradit explicitní syntaxí sady SDK uvedenou výše v této části.
Použití explicitní syntaxe sady SDK znamená, že můžete před prvním importem nebo po dokončení importu sady SDK přidat vlastní kód. To znamená, že chování můžete změnit nastavením vlastností před prvním importem, který se projeví v importovaném .props
souboru, a po posledním importu můžete přepsat cíl definovaný v jednom ze souborů sady SDK .targets
. Pomocí této metody můžete přepsat BeforeBuild
nebo AfterBuild
jak je popsáno dále.
Další kroky
S nástrojem MSBuild je toho mnohem víc, než si sestavení přizpůsobíte. Viz Přizpůsobení sestavení.