SDK de projet .NET

Les projets .NET Core, .NET 5 et versions ultérieures sont associés à un kit de développement logiciel (SDK). Chaque SDK de projet constitue un ensemble de cibles MSBuild et de tâches associées responsables de la compilation, de l’empaquetage et de la publication de code. Un projet qui fait référence à SDK est parfois appelé projet de style SDK.

Kits de développement logiciel (SDK) disponibles

Les kits de développement logiciel (SDK) suivants sont disponibles :

id Description Dépôt
Microsoft.NET.Sdk Le kit de développement logiciel (SDK) .NET https://github.com/dotnet/sdk
Microsoft.NET.Sdk.Web SDK web .NET https://github.com/dotnet/sdk
Microsoft.NET.Sdk.BlazorWebAssembly SDK Blazor WebAssembly https://github.com/dotnet/aspnetcore
Microsoft.NET.Sdk.Razor SDK Razor .NET https://github.com/dotnet/aspnetcore
Microsoft.NET.Sdk.Worker SDK Service Worker .NET
Microsoft.NET.Sdk.WindowsDesktop Desktop SDK .NET, qui inclut Windows Forms (WinForms) et Windows Presentation Foundation (WPF).* https://github.com/dotnet/winforms et https://github.com/dotnet/wpf

Le SDK .NET est le SDK de base pour .NET. Les autres SDK font référence au SDK .NET et les projets associés aux autres SDK disposent de toutes les propriétés du SDK .NET. Le SDK web, par exemple, dépend du SDK .NET et du SDK Razor.

Vous avez également la possibilité de créer votre propre SDK qui peut être distribué via NuGet.

* À partir de .NET 5, les projets Windows Forms et Windows Presentation Foundation (WPF) doivent spécifier le SDK .NET (Microsoft.NET.Sdk) plutôt que Microsoft.NET.Sdk.WindowsDesktop. Pour ces projets, la définition de TargetFramework sur net5.0-windows et de UseWPF ou UseWindowsForms sur true importe automatiquement le SDK Desktop Windows. Si votre projet cible .NET 5 ou version ultérieure et spécifie le SDK Microsoft.NET.Sdk.WindowsDesktop, vous recevez l’avertissement de générationNETDK1137.

Fichiers projet

Les projets .NET sont basés sur le format MSBuild . Les fichiers projet, présentant des extensions telles que .csproj pour les projets C# et .fsproj pour les projets F#, sont au format XML. L’élément racine d’un fichier projet MSBuild correspond à l’élément Project. L’élément Project possède un attribut facultatif Sdk qui spécifie le SDK (et la version) à utiliser. Pour utiliser les outils .NET et générer votre code, définissez l’attribut Sdk sur l’un des ID de la table SDK disponibles.

<Project Sdk="Microsoft.NET.Sdk">
  ...
</Project>

Pour spécifier un SDK provenant de NuGet, incluez la version à la fin du nom ou spécifiez le nom et la version dans le fichier global.json.

<Project Sdk="MSBuild.Sdk.Extras/2.0.54">
  ...
</Project>

L’élément de niveau supérieur Sdk permet aussi de spécifier le SDK :

<Project>
  <Sdk Name="Microsoft.NET.Sdk" />
  ...
</Project>

Le référencement d’un SDK simplifie considérablement les fichiers projet pour .NET. Lors de l’évaluation du projet, MSBuild ajoute des importations implicites pour Sdk.props en haut du fichier projet et Sdk.targets en bas.

<Project>
  <!-- Implicit top import -->
  <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
  ...
  <!-- Implicit bottom import -->
  <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
</Project>

Conseil

Sur un ordinateur Windows, les fichiers Sdk.props et Sdk.targets sont disponibles dans le dossier %ProgramFiles%\dotnet\sdk\[version]\Sdks\Microsoft.NET.Sdk\Sdk.

Prétraiter le fichier projet

Vous pouvez voir le projet entièrement développé comme MSBuild le voit après inclusion du SDK et de ses cibles à l’aide de la commande dotnet msbuild -preprocess. Le commutateur de prétraitement de la commande dotnet msbuild indique les fichiers importés, leurs sources et leurs contributions à la build sans réellement générer le projet.

Si le projet comporte plusieurs versions cibles de .Net Framework, concentrez les résultats de la commande sur une seule d’entre elles en la spécifiant en tant que propriété MSBuild. Par exemple :

dotnet msbuild -property:TargetFramework=netcoreapp2.0 -preprocess:output.xml

Inclusions et exclusions de la valeur par défaut

La valeur par défaut inclut et exclut les éléments Compile, les ressources intégrées, et les éléments None sont définis dans le kit de développement logiciel (SDK). Contrairement aux projets .NET Framework non SDK, vous n’avez pas besoin de spécifier ces éléments dans votre fichier projet, car les valeurs par défaut couvrent les cas d’usage les plus courants. Ce comportement réduit la taille du fichier projet et facilite sa compréhension et sa modification manuellement, si nécessaire.

Le tableau suivant indique les éléments et globs inclus et exclus dans le SDK .NET :

Élément Inclure Glob Exclure Glob Supprimer Glob
Compile **/*.cs (ou autres extensions de langage) **/*.user; **/*.*proj; **/*.sln; **/*.vssscc N/A
EmbeddedResource **/*.resx **/*.user, **/*.*proj, **/*.sln, **/*.vssscc N/A
None **/* **/*.user, **/*.*proj, **/*.sln, **/*.vssscc **/*.cs; **/*.resx

Notes

Les dossiers ./bin et ./obj, représentés par les propriétés MSBuild $(BaseOutputPath) et $(BaseIntermediateOutputPath), sont exclus des globs par défaut. Les exclusions sont représentées par la propriété DefaultItemExcludes.

Le SDK Desktop .NET présente plus d’inclusions et d’exclusions pour WPF. Pour plus d’informations, consultez Inclusions et exclusions WPF par défaut.

Erreurs de build

Si vous définissez explicitement l’un de ces éléments dans votre fichier projet, vous obtiendrez probablement une erreur de build « NETSDK1022 » similaire à ce qui suit :

Les éléments « Compile » dupliqués ont été inclus. Le SDK .NET inclut des éléments « Compile » de votre répertoire de projet par défaut. Vous pouvez supprimer ces éléments de votre fichier projet ou définir la propriété « EnableDefaultCompileItems » sur « false » si vous souhaitez explicitement les inclure dans votre fichier projet.

Les éléments « EmbeddedResource » dupliqués ont été inclus. Le SDK .NET inclut des éléments « EmbeddedResource » de votre répertoire de projet par défaut. Vous pouvez supprimer ces éléments de votre fichier projet ou définir la propriété « EnableDefaultEmbeddedResourceItems » sur « false » si vous souhaitez explicitement les inclure dans votre fichier projet.

Pour résoudre les erreurs, procédez de l’une des façons suivantes :

  • Supprimez les éléments explicites Compile, EmbeddedResource ou None qui correspondent aux éléments implicites répertoriés dans le tableau précédent.

  • Définissez la propriété EnableDefaultItems sur false pour désactiver toutes les inclusions de fichiers implicites :

    <PropertyGroup>
      <EnableDefaultItems>false</EnableDefaultItems>
    </PropertyGroup>
    

    Si vous souhaitez spécifier des fichiers à publier avec votre application, vous pouvez toujours utiliser les mécanismes MSBuild connus, par exemple l’élément Content.

  • Désactivez de manière sélective les globs Compile, EmbeddedResource ou None uniquement en définissant la propriété EnableDefaultCompileItems, EnableDefaultEmbeddedResourceItems ou EnableDefaultNoneItems sur false :

    <PropertyGroup>
      <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
      <EnableDefaultEmbeddedResourceItems>false</EnableDefaultEmbeddedResourceItems>
      <EnableDefaultNoneItems>false</EnableDefaultNoneItems>
    </PropertyGroup>
    

    Si vous désactivez les globs Compile uniquement, l’Explorateur de solutions de Visual Studio affiche toujours les éléments *.cs dans le cadre du projet, inclus en tant qu’éléments None. Pour désactiver le glob implicite None, définissez également EnableDefaultNoneItems sur false.

Directives d’utilisation implicites

À compter de .NET 6, des directives global using implicites sont ajoutées aux nouveaux projets C#. Cela signifie que vous pouvez utiliser des types définis dans ces espaces de noms sans avoir à spécifier leur nom complet ou ajouter manuellement une directive using. L’aspect implicite fait référence au fait que les directives global using sont ajoutées à un fichier généré dans le répertoire obj du projet.

Les directives implicites global using sont ajoutées pour les projets qui utilisent l’un des SDK suivants :

  • Microsoft.NET.Sdk
  • Microsoft.NET.Sdk.Web
  • Microsoft.NET.Sdk.Worker
  • Microsoft.NET.Sdk.WindowsDesktop

Une directive global using est ajoutée pour chaque espace de noms dans un ensemble d’espaces de noms par défaut basés sur SDK du projet. Ces espaces de noms par défaut sont affichés dans le tableau suivant.

Kit SDK Espaces de noms par défaut
Microsoft.NET.Sdk System
System.Collections.Generic
System.IO
System.Linq
System.Net.Http
System.Threading
System.Threading.Tasks
Microsoft.NET.Sdk.Web Espaces de noms Microsoft.NET.Sdk
System.Net.Http.Json
Microsoft.AspNetCore.Builder
Microsoft.AspNetCore.Hosting
Microsoft.AspNetCore.Http
Microsoft.AspNetCore.Routing
Microsoft.Extensions.Configuration
Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.Hosting
Microsoft.Extensions.Logging
Microsoft.NET.Sdk.Worker Espaces de noms Microsoft.NET.Sdk
Microsoft.Extensions.Configuration
Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.Hosting
Microsoft.Extensions.Logging
Microsoft.NET.Sdk.WindowsDesktop (Windows Forms) Espaces de noms Microsoft.NET.Sdk
System.Drawing
System.Windows.Forms
Microsoft.NET.Sdk.WindowsDesktop (WPF) Espaces de noms Microsoft.NET.Sdk
Suppression de System.IO
Suppression de System.Net.Http

Si vous souhaitez désactiver cette fonctionnalité ou activer des directives implicites global using dans un projet C# existant, vous pouvez le faire via la propriété MSBuild ImplicitUsings.

Vous pouvez spécifier des directives implicites global using supplémentaires en ajoutant des éléments Using (ou des éléments Import pour les projets Visual Basic) à votre fichier projet, par exemple :

<ItemGroup>
  <Using Include="System.IO.Pipes" />
</ItemGroup>

Références de package implicites

Lorsque vous ciblez .NET Core 1.0 - 2.2 ou .NET Standard 1.0 - 2.0, le SDK .NET ajoute des références implicites à certains métapaquets. Un métapaquet est un package basé sur l’infrastructure qui se compose uniquement de dépendances portant sur d’autres packages. Les métapaquets sont référencés implicitement en fonction du ou des frameworks cibles spécifiés dans la propriété TargetFramework or TargetFrameworks de votre fichier projet.

<PropertyGroup>
  <TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<PropertyGroup>
  <TargetFrameworks>netcoreapp2.1;net462</TargetFrameworks>
</PropertyGroup>

Si nécessaire, vous pouvez désactiver les références de package implicites à l’aide de la propriété DisableImplicitFrameworkReferences et ajouter des références explicites aux seuls frameworks ou packages dont vous avez besoin.

Recommandations :

  • Lorsque vous ciblez .NET Framework, .NET Core 1.0 - 2.2 ou .NET Standard 1.0 - 2.0, n’ajoutez pas de référence explicite aux métapaquets Microsoft.NETCore.App ou NETStandard.Library via un élément <PackageReference> de votre fichier projet. Pour les projets .NET Core 1.0 - 2.2 et .NET Standard 1.0 - 2.0, ces métapaquets sont implicitement référencés. Pour les projets .NET Framework, si une version de NETStandard.Library est nécessaire lors de l’utilisation d’un package NuGet basé sur .NET Standard, NuGet installe automatiquement cette version.
  • Si vous avez besoin d’une version spécifique du runtime quand vous ciblez .NET Core 1.0 - 2.2, vous devez utiliser la propriété <RuntimeFrameworkVersion> dans votre projet (par exemple, 1.0.4) au lieu de référencer le métapaquet. Par exemple, vous devrez peut-être disposer d’une version corrective spécifique du runtime 1.0.0 LTS si vous utilisez des déploiements autonomes.
  • Si vous avez besoin d’une version spécifique du métapaquet NETStandard.Library quand vous ciblez .NET Standard 1.0 - 2.0, vous pouvez utiliser la propriété <NetStandardImplicitPackageVersion> et définir la version dont vous avez besoin.

Événements de build

Dans les projets de style SDK, utilisez une cible MSBuild nommée PreBuild ou PostBuild et définissez la propriété BeforeTargets pour PreBuild ou la propriété AfterTargets pour PostBuild.

<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
    <Exec Command="&quot;$(ProjectDir)PreBuildEvent.bat&quot; &quot;$(ProjectDir)..\&quot; &quot;$(ProjectDir)&quot; &quot;$(TargetDir)&quot;" />
</Target>

<Target Name="PostBuild" AfterTargets="PostBuildEvent">
   <Exec Command="echo Output written to $(TargetDir)" />
</Target>

Notes

  • Vous pouvez utiliser n’importe quel nom pour les cibles MSBuild. Toutefois, l’IDE Visual Studio reconnaît les cibles PreBuild et PostBuild. Par conséquent, en utilisant ces noms, vous pouvez modifier les commandes dans l’IDE.
  • Les propriétés PreBuildEvent et PostBuildEvent sont déconseillée pour les projets de style SDK, car les macros telles que $(ProjectDir) ne sont pas résolues. Par exemple, le code suivant n’est pas pris en charge :
<PropertyGroup>
  <PreBuildEvent>"$(ProjectDir)PreBuildEvent.bat" "$(ProjectDir)..\" "$(ProjectDir)" "$(TargetDir)"</PreBuildEvent>
</PropertyGroup>

Personnaliser la build

Il existe différentes façons de personnaliser une build. Vous pouvez remplacer une propriété en la transmettant en tant qu’argument à une commande msbuild ou dotnet. Vous pouvez également ajouter la propriété au fichier projet ou à un fichier Directory.Build.props. Pour obtenir la liste des propriétés utiles pour les projets .NET, consultez Référence MSBuild pour les projets SDK .NET.

Conseil

Utiliser la commande dotnet new buildprops à la racine de votre référentiel permet de créer facilement un nouveau fichier Directory.Build.props à partir de la ligne de commande.

Cibles personnalisées

Les projets .NET peuvent empaqueter des cibles et des propriétés MSBuild personnalisées à utiliser par les projets qui consomment le package. Utilisez ce type d’extensibilité lorsque vous souhaitez :

  • Étendre le processus de génération.
  • Accéder aux artefacts du processus de génération, tels que les fichiers générés.
  • Inspecter la configuration sous laquelle la build est appelée.

Vous ajoutez des cibles ou des propriétés de build personnalisées en plaçant des fichiers dans le formulaire <package_id>.targets ou <package_id>.props (par exemple, Contoso.Utility.UsefulStuff.targets) dans le dossier de build du projet.

Le code XML suivant est un extrait de code de fichier .csproj qui indique à la commande dotnet pack les éléments à empaqueter. L’élément <ItemGroup Label="dotnet pack instructions"> place les fichiers cibles dans le dossier de build à l’intérieur du package. L’élément <Target Name="CollectRuntimeOutputs" BeforeTargets="_GetPackageFiles"> place les assemblys et les fichiers .json dans le dossier de build.

<Project Sdk="Microsoft.NET.Sdk">

  ...
  <ItemGroup Label="dotnet pack instructions">
    <Content Include="build\*.targets">
      <Pack>true</Pack>
      <PackagePath>build\</PackagePath>
    </Content>
  </ItemGroup>
  <Target Name="CollectRuntimeOutputs" BeforeTargets="_GetPackageFiles">
    <!-- Collect these items inside a target that runs after build but before packaging. -->
    <ItemGroup>
      <Content Include="$(OutputPath)\*.dll;$(OutputPath)\*.json">
        <Pack>true</Pack>
        <PackagePath>build\</PackagePath>
      </Content>
    </ItemGroup>
  </Target>
  ...

</Project>

Pour utiliser une cible personnalisée dans votre projet, ajoutez un élément PackageReference qui pointe vers le package et sa version. Contrairement aux outils, le package des cibles personnalisées est inclus dans la fermeture de dépendance du projet de consommation.

Vous pouvez configurer l’utilisation de la cible personnalisée. Puisqu’il s’agit d’une cible MSBuild, elle peut dépendre d’une cible donnée, exécutée après une autre cible, ou peut être appelée manuellement à l’aide de la commande dotnet msbuild -t:<target-name>. Toutefois, pour une meilleure expérience utilisateur, vous pouvez combiner des outils par projet et des cibles personnalisées. Dans ce scénario, l’outil par projet accepte tous les paramètres nécessaires et les convertit en appel dotnet msbuild requis qui exécute la cible. Vous pouvez voir un exemple de ce type de synergie sur le dépôt des exemples du MVP Summit 2016 Hackathon du projet dotnet-packer.

Voir aussi