40 votes

Qu'est-ce que le win/any temps d'exécution signifie dans .NET Core

Je construis une application C# .NET core qui cible le framework net452. Lorsque je publie, je peux spécifier un runtime (--runtime), si je ne spécifie aucun runtime, il utilise win7-x64 (je suppose que c'est parce que c'est ce que mon ordinateur exécute). Cependant, je peux également spécifier manuellement le runtime et il semble accepter n'importe quelle chaîne que je lui donne. Cependant, le catalogue RID semble suggérer que à la fois win ainsi que any sont valides.

MISE À JOUR: Je n'ai pas de bonnes réponses donc je vais clarifier mes questions et ajouter une prime. J'ai également demandé sur les forums ASP.NET core mais je n'ai reçu aucune réponse.

  1. Si je spécifie un RID de win7-x32, mon code fonctionnera-t-il également sur un système d'exploitation Windows 64 bits ?

  2. Si je spécifie un RID de win7, que va-t-il construire, construira-t-il la version 32 bits ou la version 64 bits ?

  3. Si je spécifie un RID de win7, mon programme fonctionnera-t-il sous Windows 8, 8.1 ou 10 ?

  4. Que fait le RID any ? Je comprends comment le déploiement portable peut être utilisé sur plusieurs plateformes mais comment le déploiement autonome (construit avec un RID de any) peut-il fonctionner sur Linux ainsi que sur Windows ? Est-ce que je comprends mal ce RID ?

  5. Si je spécifie un RID de blah, je m'attendais à une erreur. Au lieu de cela, mon application a été construite dans le répertoire bin/Release/blah. A-t-il simplement basculé vers un autre runtime par défaut ?

37voto

Jonathan Gilbert Points 497

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 :

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

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

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

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

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

17voto

Nkosi Points 95895

Je crois que la documentation officielle liée dans le message d'Origine fournit toutes les informations nécessaires.

Tout d'abord

Qu'est-ce que les RID ?

RID est l'abréviation de Runtime IDentifier. Les RID sont utilisés pour identifier les systèmes d'exploitation cibles sur lesquels une application ou une ressource (c'est-à-dire, une assembly) s'exécutera.

Il est important de noter que les RID sont en fait des chaînes opaques. Cela signifie qu'ils doivent correspondre exactement pour que les opérations les utilisant fonctionnent.

Cela a également été cité à partir de GitHub

Un RID est une chaîne opaque qui identifie une plateforme. Les RID ont des relations avec d'autres RID en "important" l'autre RID. De cette manière, un RID est un graphe orienté de RID compatibles.

Meilleur RID Considérez le graphe partiel de RID :

"any": {},

"win": {
    "#import": [ "any" ]
},
"win-x86": {
    "#import": [ "win" ]
},
"win-x64": {
    "#import": [ "win" ]
},
"win7": {
    "#import": [ "win" ]
},
"win7-x86": {
    "#import": [ "win7", "win-x86" ]
},
"win7-x64": {
    "#import": [ "win7", "win-x64" ]
}

Ceci peut être visualisé comme un graphe dirigé, comme suit :

win7-x64    win7-x86
   |   \   /    |
   |   win7     |
   |     |      |
win-x64  |  win-x86
      \  |  /
        win
         |
        any

Ainsi, pour le meilleur RID, en évaluant pour win7-x64, serait : win7-x64, win7, win-x64, win, any De même, en évaluant pour win-x64 : win-x64, win, any Notez que win7 vient avant win-x64 en raison de l'import pour win7 apparaissant avant l'import pour win-x64 dans l'ordre du document.

Cela dit, et en faisant référence à runtime.json sur le dépôt CoreFX.

Si vous utilisez ce fichier, vous remarquerez que certains des RID ont une déclaration "#import" en eux. Ces déclarations sont des déclarations de compatibilité. Cela signifie qu'un RID qui a un RID importé peut être une cible pour restaurer les packages pour ce RID.

Extrait uniquement les parties pertinentes,

1) Si je spécifie un RID de win7-x32 mon code fonctionnera-t-il également sur un système d'exploitation Windows 64 bits ?

"base": {
},

"any": {
    "#import": [ "base" ]
},
...
"win": {
    "#import": [ "any" ]
},
...
"win7": {
        "#import": [ "win" ]
    },
"win7-x86": {
    "#import": [ "win7", "win-x86" ]
},
"win7-x64": {
    "#import": [ "win7", "win-x64" ]
},
...

2) Si je spécifie un RID de win7, que construit-il, construira-t-il la version 32 bits ou la version 64 bits ?

Il construira une version commune qui peut s'exécuter sur les deux plateformes. Reportez-vous à la visualisation ci-dessus.

3) Si je spécifie un RID de win7, mon programme s'exécutera-t-il sur Windows 8, 8.1 ou 10 ?

Oui. Selon les imports des versions référencées.

"win8": {
    "#import": [ "win7" ]
},
"win8-x86": {
    "#import": [ "win8", "win7-x86" ]
},
"win8-x64": {
    "#import": [ "win8", "win7-x64" ]
},
"win8-arm": {
    "#import": [ "win8" ]
},

"win81": {
    "#import": [ "win8" ]
},
"win81-x86": {
    "#import": [ "win81", "win8-x86" ]
},
"win81-x64": {
    "#import": [ "win81", "win8-x64" ]
},
"win81-arm": {
    "#import": [ "win81", "win8-arm" ]
},

"win10": {
    "#import": [ "win81" ]
},
"win10-x86": {
    "#import": [ "win10", "win81-x86" ]
},
"win10-x64": {
    "#import": [ "win10", "win81-x64" ]
},

4) Que fait le RID any ?

Cela signifie que la construction est compatible avec any des plates-formes prises en charge et peut être une cible pour restaurer les packages pour n'importe quel RID.

5) Si je spécifie un RID de blah je m'attendais à une erreur. Au lieu de cela, mon application a été construite dans le répertoire bin/Release/blah. A-t-il simplement utilisé par défaut une autre exécution ?

En citant la documentation :

Tous les RID finissent par se rapporter au RID racine any.

Et enfin, encore une fois à partir de la documentation, prenez note

Bien qu'ils semblent assez simples à utiliser, il y a quelques éléments spéciaux à à propos des RID que vous devez garder en tête lorsque vous travaillez avec eux :

  • Il s'agit de chaînes opaques et doit être traité comme des boîtes noires

  • Vous ne devez pas construire les RID de manière programmatique

  • Vous devez utiliser les RID qui sont déjà définis pour la plate-forme et ce document le montre

  • Les RID doivent être spécifiques, donc ne supposez rien de la valeur du RID réel; veuillez consulter ce document pour déterminer quel(s) RID vous avez besoin pour une plate-forme donnée

4voto

John Rusk Points 21

Sous .NET Core 2.0, il suffit de compiler pour les cibles suivantes :

  • linux-x64, linux-arm
  • win-x64, win-x86
  • osx-x64

Voir https://blogs.msdn.microsoft.com/dotnet/2017/08/14/announcing-net-core-2-0/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X