• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

Configurations.propsH A D24-Aug-2018274 88

Microsoft.NETCore.Platforms.buildsH A D24-Aug-2018587 88

Microsoft.NETCore.Platforms.pkgprojH A D24-Aug-2018959 2317

readme.mdH A D24-Aug-201811.5 KiB156124

runtime.compatibility.jsonH A D24-Aug-201882 KiB5,2215,221

runtime.jsonH A D24-Aug-201838.6 KiB2,2612,261

runtimeGroups.propsH A D24-Aug-20185.2 KiB154126

readme.md

1# Runtime IDs
2The package `Microsoft.NETCore.Platforms` defines the runtime identifiers (RIDs) used by .NET packages to represent runtime-specific assets in NuGet packages.
3
4## What is a RID?
5A RID is an opaque string that identifies a platform.  RIDs have relationships to other RIDs by "importing" the other RID.  In that way a RID is a directed graph of compatible RIDs.
6
7## How does NuGet use RIDs?
8When NuGet is deciding which assets to use from a package and which packages to include NuGet will consider a RID if the project.json lists a RID in its `runtimes` section.
9
10- NuGet chooses the best RID-specific asset, where best is determined by a breadth first traversal of the RID graph.  Breadth ordering is document order.
11- NuGet considers RID-specific assets for two asset types: lib and native.
12- NuGet never considers RID-specific assets for compile.
13
14### Best RID
15Consider the partial RID-graph:
16```
17        "any": {},
18
19        "win": {
20            "#import": [ "any" ]
21        },
22        "win-x86": {
23            "#import": [ "win" ]
24        },
25        "win-x64": {
26            "#import": [ "win" ]
27        },
28        "win7": {
29            "#import": [ "win" ]
30        },
31        "win7-x86": {
32            "#import": [ "win7", "win-x86" ]
33        },
34        "win7-x64": {
35            "#import": [ "win7", "win-x64" ]
36        }
37```
38
39This can be visualized as a directed graph, as follows:
40```
41    win7-x64    win7-x86
42       |   \   /    |
43       |   win7     |
44       |     |      |
45    win-x64  |  win-x86
46          \  |  /
47            win
48             |
49            any
50```
51As such, best RID, when evaluating for win7-x64 would be:`win7-x64`, `win7`, `win-x64`, `win`, `any`
52Similarly, when evaluating for `win-x64`: `win-x64`, `win`, `any`
53Note that `win7` comes before `win-x64` due to the import for `win7` appearing before the import for `win-x64` in document order.
54
55### RID-qualified assets are preferred
56NuGet will always prefer a RID-qualified asset over a RID-less asset.  For example if a package contains
57```
58lib/netcoreapp1.0/foo.dll
59runtimes/win/lib/netcoreapp1.0/foo.dll
60```
61When resolving for netstandard1.0/win7-x64 NuGet will choose `runtimes/win/lib/netcoreapp1.0/foo.dll`.
62
63Additionally, NuGet will always prefer a RID-qualified asset over a RID-less asset, even if the framework is less specific for the RID-qualified asset.
64```
65lib/netstandard1.5/foo.dll
66runtimes/win/lib/netstandard1.0/foo.dll
67```
68When resolving for netstandard1.5/win7-x64 NuGet will choose `runtimes/win/lib/netstandard1.0/foo.dll` over `lib/netstandard1.5/foo.dll` even though `netstandard1.5` is more specific than `netstandard1.0`.
69
70### RID-qualified assets are never used for compile
71NuGet will select different compile-assets than runtime-assets.  The compile assets can never be RID-qualified.  Consider the package:
72```
73lib/netstandard1.5/foo.dll
74runtimes/win/lib/netstandard1.0/foo.dll
75```
76When resolving for netstandard1.5/win7-x64 will select `lib/netstandard1.5/foo.dll` for the compile asset and `runtimes/win/lib/netstandard1.0/foo.dll` for the runtime asset.
77
78## Adding new RIDs
79
80### Why do I need to add a new RID?
81NuGet's extensibility mechanism for platform-specific assets requires a RID be defined for any platform that needs assets specific to that platform.  Unlike TFMs, which have a known relationship in NuGet (eg net4.5 is compatible with net4.0), RIDs are opaque strings which NuGet knows nothing about.  The definition and relationship of RIDs comes solely from the `runtime.json` files within the root of the packages referenced by the project.
82As such, whenever we want to put a new RID in a project.json in order to get assets specific for that RID we have to define the rid in some package.  Typically that package is `Microsoft.NETCore.Platforms` if the RID is "official".  If you'd like to prototype you can put the RID in any other package and so long as that package is referenced you can use that RID.
83
84### Do I really need to add a new RID?
85If you're prototyping on a platform that is compatible with an existing platform then you can reuse the RID for that exsisting platform.  New RIDs are only needed when an asset needs to be different on a particular platform.
86
87`Microsoft.NETCore.Platforms` attempts to define all RIDs that packages may need, and as such will define RIDs for platforms that we don't actually cross compile for.  This is to support higher-level packages, 3rd party packages, that may need to cross-compile for that RID.
88
89### Adding a new OS
90Add a new `RuntimeGroup` item in `runtimeGroups.props`.
91
92For example:
93```xml
94    <RuntimeGroup Include="myLinuxDistro">
95      <Parent>linux</Parent>
96      <Architectures>x86;x64;arm</Architectures>
97      <Versions>42.0;43.0</Versions>
98    </RuntimeGroup>
99```
100
101This will create a new RID for `myLinuxDistro` where `myLinuxDistro` should be the string used for the `ID=` value in the `/etc/os-release` file.
102
103Whenever modifying the `runtimeGroups.props` you should rebuild the project with `/p:UpdateRuntimeFiles=true` so that your changes will be regenerated in the checked-in `runtime.json`.
104
105RuntimeGroup items have the following format:
106- `Identity`: the base string for the RID, without version architecture, or qualifiers.
107- `Parent`: the base string for the parent of this RID.  This RID will be imported by the baseRID, architecture-specific, and qualifier-specific RIDs (with the latter two appending appropriate architecture and qualifiers).
108- `Versions`: A list of strings delimited by semi-colons that represent the versions for this RID.
109- `TreatVersionsAsCompatible`: Default is true.  When true, version-specific RIDs will import the previous version-specific RID in the Versions list, with the first version importing the version-less RID.  When false all version-specific RIDs will import the version-less RID (bypassing previous version-specific RIDs)
110- `OmitVersionDelimiter`: Default is false.  When true no characters will separate the base RID and version (EG: win7). When false a '.' will separate the base RID and version (EG: osx.10.12).
111- `ApplyVersionsToParent`: Default is false.  When true, version-specific RIDs will import version-specific Parent RIDs similar to is done for architecture and qualifier (see Parent above).
112- `Architectures`: A list of strings delimited by semi-colons that represent the architectures for this RID.
113- `AdditionalQualifiers`: A list of strings delimited by semi-colons that represent the additional qualifiers for this RID.  Additional qualifers do not stack, each only applies to the qualifier-less RIDs (so as not to cause combinatorial exponential growth of RIDs).
114
115### Adding a new version to an existing OS
116Find the existing `RuntimeGroup` in `runtimeGroups.props` and add the version to the list of `Versions`, separated by a semi-colon.
117
118If the version you are adding needs to be treated as not-compatible with previous versions and the `RuntimeGroup` has not set `TreatVersionsAsCompatible`=`false` then you may create a new `RuntimeGroup` to represent the new compatibility band.
119
120### Checking your work
121After making a change to `runtimeGroups.props` you can examine the resulting changes in `runtime.json` and `runtime.compatibility.json`.
122
123`runtime.json` is the graph representation of the RIDs and is what ships in the package.
124
125`runtime.compatibility.json` is a flattened version of the graph that shows the RID precedence for each RID in the graph.
126
127### Version compatibility
128Version compatibility is represented through imports.  If a platform is considered compatible with another version of the same platform, or a specific version of another platform, then it can import that platform.  This permits packages to reuse assets that were built for the imported platform on the compatible platform.  Compatibility here is a bit nebulous because inevitably different platforms will have observable differences that can cause compatibility problems.  For the purposes of RIDs we'll try to represent compatibility as versions of a platform that are explicitly advertised as being compatible with a previous version and/or another platform and don't have any known broad breaking changes.  It is usually better to opt to treat platforms as compatible since that enables the scenario of building an asset for a particular version and using that in future versions, otherwise you force people to cross-compile for all future versions the moment they target a specific version.
129
130## Appendix : details of RID graph generation
131
132### Naming convention
133We use the following convention in all newly-defined RIDs.  Some RIDs (win7-x64, win8-x64) predate this convention and don't follow it, but all new RIDs should follow it.
134`[os name].[version]-[architecture]-[additional qualifiers]`, for example `osx.10.10-x64` or `ubuntu.14.04-x64`
135- `[os name]` can contain any characters other than `.`
136- `[version]` can contain any characters other than `-`.  Typically a numeric version like 14.04 or 10.0.
137- `[architecture]` can contain any characters other than `-`. Typically: `x86`, `x64`, `arm`, `arm64`
138- `[additional qualifiers]` can be things like `aot`.  Used to further differentiate different platforms.
139
140For all of these we strive to make them something that can be uniquely discoverable at runtime, so that a RID may be computed from an executing application.  As such these properties should be derivable from `/etc/os-release` or similar platform APIs / data.
141
142### Import convention
143Imports should be used when the added RID is considered compatible with an existing RID.
144
1451. Architecture-specific RIDs should first import the architecture-less RID.  EG: `osx.10.11-x64` should first import `osx.10.11`.
1462. Architecture-specific RIDs that are compatible with a previous version RID for the same OS should then import the previous version, architecture specific RID.  EG: `osx.10.11-x64` should then import `osx.10.10-x64`.  If there is no earlier compatible/supported version, then a versionless RID should be imported.  EG: `osx.10.10-x64` should import `osx-x64`.
1473. Architecture-less RIDs that are compatible with a previous version RID for the same OS should then import the previous version, architecture neutral RID.  EG: `osx.10.11` should import `osx.10.10`. If there is no earlier compatible/supported version, then a versionless RID should be imported.  EG: `osx.10.10` should import `osx`.
1484. Version-less RIDs should import an OS category.  EG: `osx-x64` should import `unix-x64`, `osx` should import `unix`.
149
150### Advanced RuntimeGroup metadata
151The following options can be used under special circumstances but break the normal precedence rules we try to establish by generating the RID graph from common logic. These options make it possible to create a RID fallback chain that doesn't  match the rest of the RIDs and therefore is hard for developers/package authors to reason about.  Only use these options for cases where you know what you are doing and have carefully reviewed the resulting RID fallbacks using the CompatibliltyMap.
152
153- `OmitRIDs`: A list of strings delimited by semi-colons that represent RIDs calculated from this RuntimeGroup that should be omitted from the RuntimeGraph.  These RIDs will not be referenced nor defined.
154- `OmitRIDDefinitions`: A list of strings delimited by semi-colons that represent RIDs calculated from this RuntimeGroup that should be omitted from the RuntimeGraph.  These RIDs will not be defined by this RuntimeGroup, but will be referenced: useful in case some other RuntimeGroup (or runtime.json template) defines them.
155- `OmitRIDReferences`: A list of strings delimited by semi-colons that represent RIDs calculated from this RuntimeGroup that should be omitted from the RuntimeGraph.  These RIDs will be defined but not referenced by this RuntimeGroup.
156