SDK de projet .NET

Les projets modernes .NET 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

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.

Pour les projets Windows Forms et Windows Presentation Foundation (WPF), vous spécifiez le kit de développement logiciel (SDK) .NET (Microsoft.NET.Sdk) et définissez des propriétés supplémentaires dans le fichier projet. Pour plus d’informations, consultez Activer le kit de développement logiciel (SDK) .NET Desktop.

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 kit de développement logiciel (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=net8.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 kit de développement logiciel (SDK) .NET Desktop comporte des inclusions et des exclusions supplémentaires pour WPF. Pour plus d’informations, consultez Inclusions et exclusions WPF par défaut.

Si vous définissez explicitement l’un de ces éléments dans votre fichier projet, vous obtiendrez probablement une erreur de build NETSDK1022. Pour plus d’informations sur la résolution de l’erreur, consultez NETSDK1022 : Des éléments en double ont été inclus.

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 votre projet cible .NET Standard 1.0-2.0, le kit de développement logiciel (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 des versions cibles de .NET Framework spécifiées dans la propriété TargetFramework ou TargetFrameworks (au pluriel) de votre fichier projet.

<PropertyGroup>
  <TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
  <TargetFrameworks>netstandard2.0;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 ou .NET Standard 1.0-2.0, n’ajoutez pas de référence explicite aux métapaquets NETStandard.Library via un élément <PackageReference> de votre fichier projet. Pour les projets .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 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