Sdílet prostřednictvím


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 a AfterTargets 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í CustomAfterBuildAfterBuild), 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

  1. Identifikujte předdefinovanou DependsOn vlastnost v běžných cílech, které chcete přepsat. Seznam běžně přepsaných DependsOn vlastností najdete v následující tabulce.

  2. Na konci souboru projektu definujte jinou instanci vlastnosti nebo vlastností. Do nové vlastnosti zahrňte původní vlastnost, například $(BuildDependsOn).

  3. Definujte vlastní cíle před definicí vlastnosti nebo za ji.

  4. 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-&gt;'$(_OutputCopyLocation)%(RecursiveDir)%(Filename)%(Extension)')"/>

    <Copy SourceFiles="@(_FilesToCopy)"
          DestinationFiles="@(_FilesToCopy-&gt;'$(_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

  1. Pokud projekt používá Sdk atribut, změňte ho na explicitní syntaxi importu. Viz explicitní a implicitní importy.

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

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

  4. 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, CleanBuild, 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í.

  1. 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 v DependsOnTargets.

  2. Použijte BeforeTargets pro jakýkoli cíl, který neřídíte, než je nutné provést (například BeforeTargets="PrepareForBuild" pro cíl, který je potřeba spustit dříve v sestavení).

  3. 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ů.

  4. 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í.