Les RID sont utilisés avec .NET Core pour résoudre les dépendances des packages. La racine de ce processus de résolution des dépendances est votre projet, que vous marquez explicitement avec un ou plusieurs RID. Lors de la construction du projet, vous indiquez contre quel RID vous construisez.
Les RID sont définis dans un ensemble d'arbres de compatibilité, où chaque nœud dans un arbre représente un environnement d'exécution capable de prendre en charge tous ses enfants. Chaque RID est la racine d'un tel arbre.
Voici un exemple d'arbre de compatibilité RID :
win10-x64
|- win10
| `- win81
| `- win8
| `- win7
| `- win
| `- any
| `- base
`- win81-x64
|- win81 (déjà inclus ci-dessus)
`- win8-x64
|- win8 (déjà inclus ci-dessus)
`- win7-x64
|- win7 (déjà inclus ci-dessus)
`- win-x64
`- win (déjà inclus ci-dessus)
L'ensemble complet des arbres de compatibilité RID est défini ici :
https://github.com/dotnet/runtime/blob/master/src/libraries/pkg/Microsoft.NETCore.Platforms/runtime.json
Un package peut fournir une implémentation différente pour chaque RID si nécessaire. Lors de la construction, si j'ai une dépendance sur ce package, le processus de construction sélectionnera l'implémentation la plus proche de la racine de l'arbre. Si l'arbre ne contient aucun RID fourni par le package, la construction échouera.
Il existe un type spécial de package appelé "package d'exécution". Les packages d'exécution contiennent des binaires natifs qui peuvent être chargés et exécutés directement par le système d'exploitation hôte. En tant que tel, ces packages ne fournissent des implémentations que pour des versions OS concrètes : "win7-x64", par exemple, mais pas "win7" ou "win-x64", et, par exemple, "ubuntu.16.04-x64", mais pas "ubuntu.16.04", "ubuntu-x64" ou "linux".
[Mise à jour : à partir de .NET Core 2.0, vous pouvez construire pour Linux-x64 pour cibler "toutes" les versions x64 de Linux avec une seule construction. Voir https://blogs.msdn.microsoft.com/dotnet/2017/08/14/announcing-net-core-2-0/]
Les packages d'exécution entrent en jeu lors du regroupement de projets autonomes. Avec un projet autonome, tout ce qui est nécessaire pour exécuter le projet doit être inclus dans la sortie de construction. Cela signifie que la sortie de construction doit inclure un binaire natif en tant que point d'entrée de l'application. Ce binaire natif est fourni par le package d'exécution.
Donc, pour répondre à vos questions :
- Si je spécifie un RID de win7-x32, mon code s'exécutera-t-il également sur un système d'exploitation Windows 64 bits ?
Oui, mais il s'exécutera dans un processus 32 bits. J'ai vérifié cela avec une application construite et publiée à partir d'une machine virtuelle de développement Ubuntu, puis exécutée sur Windows 10 64 bits ; si l'application est publiée contre win7-x32
, alors IntPtr.Size
est de 4, et s'il est publié contre win7-x64
, alors IntPtr.Size
est de 8. Elle s'exécute de toute façon.
Le package d'exécution win7-x32
inclut un fichier EXE 32 bits hébergeant le runtime .NET Core puis charge et exécute votre projet, qui est regroupé avec lui dans un fichier DLL portant le même nom.
- Si je spécifie un RID de win7, que va-t-il construire, la version 32 bits ou la version 64 bits ?
Si vous spécifiez un RID de win7
, il va essayer de trouver des constructions binaires natifs étiquetées avec ce RID, ou un RID compatible, mais il n'en trouvera pas. La construction échouera, car il n'y a pas de version "win7" du fichier EXE principal de point d'entrée. Vous devez spécifier soit 32 bits soit 64 bits (et il semble que toutes les autres plateformes soient uniquement en 64 bits).
J'ai testé ce détail spécifique, et j'ai constaté que :
-
L'étape dotnet restore
ne se termine pas par une erreur, mais n'installe pas non plus de runtime pour win7
(ou win10
).
-
L'étape dotnet build
réussit à compiler l'application de test, mais émet ensuite cette erreur :
Impossible de rendre le projet suivant exécutable : helloworld (.NETCoreApp,Version=v1.1) raison : La bibliothèque coreclr attendue n'a pas été trouvée dans le graphe des packages. Veuillez essayer de lancer à nouveau dotnet restore.
- Si je spécifie un RID de win7, mon programme s'exécutera-t-il sous Windows 8, 8.1 ou 10 ?
En supposant que vous spécifiez soit win7-x86
soit win7-x64
, alors oui. Le package d'exécution win7-x86
ou win7-x64
fournira un point d'entrée EXE qui est un EXE 32 bits ou 64 bits, respectivement, et ces EXEs sont des binaires natifs qui s'exécuteront sur n'importe quelle version de Windows à partir de Windows 7.
À noter qu'il n'y a actuellement aucun package d'exécution pour Windows 8, Windows 8.1 ou Windows 10 spécifiquement. Les graphiques de compatibilité pour les nouvelles versions de Windows incluent soit win7-x86
soit win7-x64
, selon le cas, et donc ce package d'exécution particulier est utilisé dans la construction, même si vous ciblez un RID plus récent comme win10-x64
.
- Que fait le RID any ? Je comprends comment le déploiement portable peut être utilisé sur plusieurs plates-formes, mais comment le déploiement autonome (construit avec un RID any) peut-il fonctionner à la fois sur Linux et Windows ? Est-ce que je me méprends sur ce RID ?
Le RID any
permet à un package de fournir une implémentation pour n'importe quel RID plus en amont dans la chaîne, car tous les autres RID incluent finalement any
(et base
) dans leur arbre de compatibilité. Les packages d'exécution, cependant, ne fournissent aucune implémentation pour any
, et donc any
ne peut pas être utilisé pour construire des packages autonomes.
- Si je spécifie un RID de blah, je m'attends à une erreur. Au lieu de cela, mon application a été construite dans le répertoire bin/Release/blah. Est-ce simplement passé à un autre runtime par défaut ?
Il faut configurer votre projet avec "type" : "platform"
dans la dépendance à Microsoft.NETCore.App
. Ainsi, aucun package autonome n'a été construit, et la résolution des bibliothèques de support est laissée au runtime, à ce moment-là le RID est fourni par le runtime réel que vous utilisez pour exécuter votre application, plutôt que par la configuration de construction de votre application.
Si votre projet est une bibliothèque, alors lorsque vous essayez de la référencer à partir d'un autre projet, vous pouvez rencontrer des problèmes car votre bibliothèque ne fournit qu'une implémentation pour la plateforme "blah", qui ne sera pas dans l'arbre de compatibilité pour le RID contre lequel l'autre projet est construit. Si votre projet est une application, alors blah
est ignoré.
Si vous reconfigurez votre projet pour produire un package autonome (en supprimant ou en commentant la ligne "type" : "platform"
dans project.json
), vous constaterez qu'il ne se construit plus, car il a maintenant une dépendance sur les packages d'exécution, et il n'y a pas de package pour le RID blah
.