Simplify RID graph: keep floating and last versioned RIDs - #125076

Open
richlander wants to merge 1 commit into
mainfrom
simplify-rid-graph-soft
Open

Simplify RID graph: keep floating and last versioned RIDs#125076
richlander wants to merge 1 commit into
mainfrom
simplify-rid-graph-soft

Conversation

@richlander

Copy link
Copy Markdown
Member

Replaces: #123161

Softer approach to RID graph simplification. Instead of removing all versioned and distro-specific RIDs, this keeps:

  • All portable/base RIDs (any, unix, linux, win, etc.)
  • All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
  • The last versioned RID for each OS family and its arch variants

This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines (266 RIDs) while preserving a migration path for packages that reference the most recent versioned RIDs.

We can do more cleanup later. This approach is a much safer starting point with easier migration guidance. It's also more defensible.

Removed RIDs: all intermediate versioned RIDs (e.g. alpine.3.7 through alpine.3.17, ubuntu.14.04 through ubuntu.23.04, osx.10.10 through osx.12, etc.)

Kept last versions include: alpine.3.18, android.32, centos.9, debian.12, fedora.39, freebsd.13, ios.15, osx.13, rhel.9, rocky.9, tizen.7.0.0, tvos.15, ubuntu.23.10, and others.

Softer approach to RID graph simplification. Instead of removing all
versioned and distro-specific RIDs, this keeps:
- All portable/base RIDs (any, unix, linux, win, etc.)
- All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
- The last versioned RID for each OS family and its arch variants
This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines
(266 RIDs) while preserving a migration path for packages that reference
the most recent versioned RIDs.
Removed RIDs: all intermediate versioned RIDs (e.g. alpine.3.7 through
alpine.3.17, ubuntu.14.04 through ubuntu.23.04, osx.10.10 through
osx.12, etc.)
Kept last versions include: alpine.3.18, android.32, centos.9,
debian.12, fedora.39, freebsd.13, ios.15, osx.13, rhel.9, rocky.9,
tizen.7.0.0, tvos.15, ubuntu.23.10, and others.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings March 2, 2026 20:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review any files in this pull request.

@richlander

richlander commented Mar 2, 2026

Copy link
Copy Markdown
MemberAuthor

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke, @jeffschwMSFT, @elinor-fung
See info in area-owners.md if you want to be subscribed.

@ericstj

Copy link
Copy Markdown
Member

What have you done to test this? Did you consider making this change in the VMR so that we can see if source build and phase2 product build are happy with the changes?

@richlander

Copy link
Copy Markdown
MemberAuthor

Great questions. I haven't done anything to test it. My belief/understanding is that the fallout is compat. I can make this change in VMR. That didn't occur to me. My thinking -- perhaps naive -- is that any break there is a bug that needs to be fixed downstream. I'll apply this change to VMR.

richlander pushed a commit to dotnet/dotnet that referenced this pull request Mar 2, 2026
Softer approach to RID graph simplification. Instead of removing all
versioned and distro-specific RIDs, this keeps:
- All portable/base RIDs (any, unix, linux, win, etc.)
- All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
- The last versioned RID for each OS family and its arch variants
This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines
(266 RIDs) while preserving a migration path for packages that reference
the most recent versioned RIDs.
Backport of dotnet/runtime#125076
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ericstj

ericstj commented Mar 2, 2026

Copy link
Copy Markdown
Member

Great questions. I haven't done anything to test it. My belief/understanding is that the fallout is compat. I can make this change in VMR. That didn't occur to me. My thinking -- perhaps naive -- is that any break there is a bug that needs to be fixed downstream. I'll apply this change to VMR.

It should be, but we might want to get that signal now. I think the VMR can give at least a sampling of those it won't run the SDK tests which I think might be equally valuable, but we don't have a good way to do that in PR.

I don't have any objections to the PR itself, it's more "what's the fallout". I trust its well formed, but I am not reviewing for that. We used to have a generator for this that made it a bit easier to review the changes to the generator inputs.

@richlander

Copy link
Copy Markdown
MemberAuthor

Understood. We're on the same page.

@tmds

tmds commented Mar 3, 2026

Copy link
Copy Markdown
Member

this keeps:
All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
The last versioned RID for each OS family and its arch variants

I'd consider removing these too.

The "modern" rid handling for a non-portable SDK depends on:

 "fedora.42-x64": [
"linux-x64",
"linux",
"unix-x64",
"unix",
"any",
"base"
]

@ericstj

Copy link
Copy Markdown
Member

I shared some data offline to show what packages are using the RIDs being discussed here. That provides a view of the producer side - we can't know what people use when building apps (consumer side) but a review of that data might help understand the compat impact of removing RIDs that might be used during restore.

@richlander

Copy link
Copy Markdown
MemberAuthor

This proposal is on top of this break that we made 3 years ago: dotnet/docs#36466

That break has a workaround. You can see it in use: https://grep.app/search?q=%3CUseRidGraph%3Etrue%3C%2FUseRidGraph%3E

The use of UseRidGraph suggests that the original change would have been too breaking.

@am11

am11 commented Mar 3, 2026

Copy link
Copy Markdown
Member

My understanding is; with Microsoft SDK:

  1. PortableRuntimeIdentifierGraph.json is used by default
  2. runtime.json is used as a fallback for < .NET8 SDKs or when user specifies UseRidGraph=true (so it is set-in-stone / considered immutable)
  3. There is an override RuntimeIdentifierGraphPath where user can provide their custom graph.

Distro maintainers use 3rd option (graph gets generated during the source-bulid).

If this is correct, then we don't need to change runtime.json for older/outdated SDK deployments to keep working. Otherwise, I misunderstood. 🙂

cc @elinor-fung

@richlander

Copy link
Copy Markdown
MemberAuthor

The intent is to remove cruft from the product. The RID file is basically a wikipedia of old distros. I'd like to eventually delete the file. I grasp, as you are suggesting, that its also enable compatibility for old assets on nuget.org, otherise they are basically unusable. Consumers can either use old SDKs, insert their own RID graph, or user a newer version. Some of the libraries may be abandoned. It's OK to have to take extra steps to use abandoned software.

@richlander

Copy link
Copy Markdown
MemberAuthor

Here is the data we collected, sorted by package count with a cutoff at 10 packages. The primary data I see is that we should consider bringing some Ubuntu RIDs back. On that note, I see that Ubuntu 23.10 is the latest/retained Ubuntu RID. That's not super useful. If we follow the data, we could replace 23.10 with 18.04 and that would solve most of the problem.

RIDPackagesTotalDownloads
win-x642619207237330
win204919292274122
win-x861829177109693
linux-x641708129237714
unix11237254257098
osx-x64109849230613
win-arm6482310471924
linux-arm6463282847442
win10-x6459011712306
osx569592532030
win10-x8655811400902
linux-arm48277527334
win10-arm4608308597
osx-arm6445011622264
linux-musl-x643526193593
win-arm34962507883
linux-x862769332247
alpine-x642391957557
win7-x641969761981
browser18852817835
linux179422141284
linux-armel17062772107
linux-musl-arm641561505670
win7-x861508884912
win10-arm641481613561
linux-musl-arm1481319978
ubuntu.18.04-x641431731579
rhel-x64140879046
fedora-x641371093005
debian.9-x641301636565
alpine.3.9-x64102819572
debian-arm6497814104
ubuntu.16.04-arm6497814104
linux-mips6484277434
android-arm64788947188
maccatalyst-x64716129705
maccatalyst-arm64705851291
android-x64698941814
linux-s390x67255760
android-arm668878358
android-x86618881581
browser-wasm60105415377
ios511631429
freebsd481499857
any46527589
native1.12-tchmi446013105
win8-arm44656478
linux-ppc64le37237069
win81-x6434162713
win81-x8634161137
ubuntu.16.04-x64321885962
ios-arm64318446030
tvos311037541
win8-x6430184919
win8-x8630179797
iossimulator-x64278675284
illumos27972741
solaris27972741
alpine-arm642770014
alpine-arm2663432
iossimulator-arm64258406514
aot235585530322
debian-x6423128315
x6421307951
ios-arm2014353065
tvos-arm6420512633
tvossimulator-x6420472887
centos-x6419175450
ubuntu.20.04-x6418262325
ios-armv7s1752958
ubuntu.14.04-x64166031
osx-641551277
win7-arm1512699
models156303
win714540652238
osx.10.10-x6414164277
arm641411382
osx-universal148509
native1317253297
x8613297447
win81-arm13223363
linux-641354125
debian.8-x6412187855
rhel.7-x6411791721
opensuse-x6411248293
fedora.23-x64105948
opensuse.13.2-x64105948

@tmds

tmds commented Mar 4, 2026

Copy link
Copy Markdown
Member

runtime.json is used as a fallback for < .NET8 SDKs or when user specifies UseRidGraph=true

Ah, yes.

I think users should use APIs like NativeLibrary.SetDllImportResolver instead of UseRidGraph.

It doesn't seem a mechanism that is relied on for splitting nuget packages either. Searching for latest Ubuntu LTS shows only 7 packages (by 5 users): https://www.nuget.org/packages?q=ubuntu.24.04-x64.

@richlander

Copy link
Copy Markdown
MemberAuthor

That's a good point. As I hinted at, my hope would be to make this change for 11 and the delete most of the infra for 12.

elinor-fung pushed a commit that referenced this pull request Mar 26, 2026
This fallback code (`get_current_os_rid_platform`) will probably go away
in the future once #125076 has
landed, but as it stands, we need this for parity. C++ libraries
version-less symlinks are needed for cmake/clang to avoid falling back
to non-fPIC libc++.a (because libc++.so.x.y is versioned).
With this patch, `./build.sh host.native --cross --os openbsd --arch
x64` succeeds.
Upstream PR for eng/common change:
dotnet/arcade#16564
@github-actions

github-actionsBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Workflow state for the Holistic Review Orchestrator.

{
"version": 5,
"last_dispatched_commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"last_dispatched_base_ref": "main",
"last_dispatched_base_sha": "b0bc48eea7e28be9670d4ac499a5778d0ac99909",
"last_reviewed_commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"last_reviewed_base_ref": "main",
"last_reviewed_base_sha": "b0bc48eea7e28be9670d4ac499a5778d0ac99909",
"last_recorded_worker_run_id": "29673725116",
"review_attempt_commit": "",
"review_attempt_base_ref": "",
"review_attempt_count": 0,
"max_review_attempts": 5,
"review_history_format": "holistic-review-disclosure-v1",
"review_history": [
{
"commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"review_id": 4730113525
}
]
}

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Holistic Review

Motivation: The PR trims src/libraries/Microsoft.NETCore.Platforms/src/runtime.json from 798 RIDs (~4600 lines) to 266 RIDs (~1500 lines). The goal is to stop the unbounded growth of the non-portable RID graph by removing every intermediate versioned/distro-specific RID while preserving base/portable RIDs, all floating (unversioned) OS RIDs, and the single most-recent versioned RID for each OS family plus its arch variants. It is a softer successor to #123161 (which removed all versioned/distro RIDs) intended to leave a migration path for packages that reference the newest versioned RIDs.

Approach: This is a pure data-file change to the transport package that is redistributed into the dotnet/sdk RID graph; no code, tooling (UpdateRuntimeIdentifierGraph.cs), or PortableRuntimeIdentifierGraph.json was touched. I verified the resulting graph independently of the description:

  • JSON is well-formed (jq parses; runtimes has 266 entries).
  • No dangling imports: every RID referenced in a #import array (198 distinct) is still defined as a top-level key. So removing ~721 keys did not orphan any surviving RID.
  • Kept versioned RIDs were correctly re-pointed: previously each last-version RID chained through the removed intermediate (e.g. osx.13 -> osx.12, alpine.3.18 -> alpine.3.17, osx.13-x64 -> osx.12-x64). In the new graph they import their floating base directly (osx.13 -> osx, osx.13-x64 -> osx.13,osx-x64), which is the correct rewrite to keep the graph connected after the intermediates are gone.
  • No repo-internal fallout: I grepped eng/ and src/ for representative removed RIDs (e.g. osx.10.12, ubuntu.18.04, alpine.3.17, rhel.7) and found no build/test/pipeline references that depend on them.

The change is internally consistent and the mechanical execution looks correct.

Summary: LGTM on correctness of the graph edit itself. The substantive consideration is not a code defect but a compatibility/policy judgment that belongs to the maintainers and the SDK team: removing intermediate versioned RIDs is an intentional behavior change to NuGet RID-based asset selection. Any existing package that ships assets exclusively under a now-removed RID (e.g. runtimes/ubuntu.16.04-x64/...) will no longer have that RID in the graph, so a project resolving for such a RID would fall back to the floating/base asset (or fail to see the RID at all) rather than the version-specific one. The PR description acknowledges this as the intended tradeoff with a documented migration story, and readme.md already states the graph should no longer gain new version-specific RIDs. Because this is the whole point of the PR and there is no single changed line to attach it to, I raise it here rather than as an inline finding. I'd recommend confirming (a) the SDK-side consumption and any published compat/breaking-change guidance are lined up, and (b) that the "last versioned RID per family" selection is genuinely the newest for each family (spot checks such as alpine.3.18, osx.13, ubuntu.23.10, debian.12, fedora.39 looked right). No blocking correctness issues found in the diff.

Note

This review was generated by this repository's Holistic Review agentic workflow to complement the built-in Copilot review.

Generated by Holistic Review · 130.8 AIC · ⌖ 10.7 AIC · ⊞ 10K

@elinor-fung

Copy link
Copy Markdown
Member

I assume we'd want to breaking change doc this?

The change seems generally reasonable to me as a step towards a future larger breaking change of removing the non-portable RID graph compat mode entirely.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@richlander@ericstj@tmds@am11@elinor-fung
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Simplify RID graph: keep floating and last versioned RIDs - #125076

Open
richlander wants to merge 1 commit into
mainfrom
simplify-rid-graph-soft
Open

Simplify RID graph: keep floating and last versioned RIDs#125076
richlander wants to merge 1 commit into
mainfrom
simplify-rid-graph-soft

Conversation

@richlander

Copy link
Copy Markdown
Member

Replaces: #123161

Softer approach to RID graph simplification. Instead of removing all versioned and distro-specific RIDs, this keeps:

  • All portable/base RIDs (any, unix, linux, win, etc.)
  • All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
  • The last versioned RID for each OS family and its arch variants

This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines (266 RIDs) while preserving a migration path for packages that reference the most recent versioned RIDs.

We can do more cleanup later. This approach is a much safer starting point with easier migration guidance. It's also more defensible.

Removed RIDs: all intermediate versioned RIDs (e.g. alpine.3.7 through alpine.3.17, ubuntu.14.04 through ubuntu.23.04, osx.10.10 through osx.12, etc.)

Kept last versions include: alpine.3.18, android.32, centos.9, debian.12, fedora.39, freebsd.13, ios.15, osx.13, rhel.9, rocky.9, tizen.7.0.0, tvos.15, ubuntu.23.10, and others.

Softer approach to RID graph simplification. Instead of removing all
versioned and distro-specific RIDs, this keeps:
- All portable/base RIDs (any, unix, linux, win, etc.)
- All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
- The last versioned RID for each OS family and its arch variants
This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines
(266 RIDs) while preserving a migration path for packages that reference
the most recent versioned RIDs.
Removed RIDs: all intermediate versioned RIDs (e.g. alpine.3.7 through
alpine.3.17, ubuntu.14.04 through ubuntu.23.04, osx.10.10 through
osx.12, etc.)
Kept last versions include: alpine.3.18, android.32, centos.9,
debian.12, fedora.39, freebsd.13, ios.15, osx.13, rhel.9, rocky.9,
tizen.7.0.0, tvos.15, ubuntu.23.10, and others.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings March 2, 2026 20:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review any files in this pull request.

@richlander

richlander commented Mar 2, 2026

Copy link
Copy Markdown
MemberAuthor

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke, @jeffschwMSFT, @elinor-fung
See info in area-owners.md if you want to be subscribed.

@ericstj

Copy link
Copy Markdown
Member

What have you done to test this? Did you consider making this change in the VMR so that we can see if source build and phase2 product build are happy with the changes?

@richlander

Copy link
Copy Markdown
MemberAuthor

Great questions. I haven't done anything to test it. My belief/understanding is that the fallout is compat. I can make this change in VMR. That didn't occur to me. My thinking -- perhaps naive -- is that any break there is a bug that needs to be fixed downstream. I'll apply this change to VMR.

richlander pushed a commit to dotnet/dotnet that referenced this pull request Mar 2, 2026
Softer approach to RID graph simplification. Instead of removing all
versioned and distro-specific RIDs, this keeps:
- All portable/base RIDs (any, unix, linux, win, etc.)
- All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
- The last versioned RID for each OS family and its arch variants
This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines
(266 RIDs) while preserving a migration path for packages that reference
the most recent versioned RIDs.
Backport of dotnet/runtime#125076
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ericstj

ericstj commented Mar 2, 2026

Copy link
Copy Markdown
Member

Great questions. I haven't done anything to test it. My belief/understanding is that the fallout is compat. I can make this change in VMR. That didn't occur to me. My thinking -- perhaps naive -- is that any break there is a bug that needs to be fixed downstream. I'll apply this change to VMR.

It should be, but we might want to get that signal now. I think the VMR can give at least a sampling of those it won't run the SDK tests which I think might be equally valuable, but we don't have a good way to do that in PR.

I don't have any objections to the PR itself, it's more "what's the fallout". I trust its well formed, but I am not reviewing for that. We used to have a generator for this that made it a bit easier to review the changes to the generator inputs.

@richlander

Copy link
Copy Markdown
MemberAuthor

Understood. We're on the same page.

@tmds

tmds commented Mar 3, 2026

Copy link
Copy Markdown
Member

this keeps:
All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
The last versioned RID for each OS family and its arch variants

I'd consider removing these too.

The "modern" rid handling for a non-portable SDK depends on:

 "fedora.42-x64": [
"linux-x64",
"linux",
"unix-x64",
"unix",
"any",
"base"
]

@ericstj

Copy link
Copy Markdown
Member

I shared some data offline to show what packages are using the RIDs being discussed here. That provides a view of the producer side - we can't know what people use when building apps (consumer side) but a review of that data might help understand the compat impact of removing RIDs that might be used during restore.

@richlander

Copy link
Copy Markdown
MemberAuthor

This proposal is on top of this break that we made 3 years ago: dotnet/docs#36466

That break has a workaround. You can see it in use: https://grep.app/search?q=%3CUseRidGraph%3Etrue%3C%2FUseRidGraph%3E

The use of UseRidGraph suggests that the original change would have been too breaking.

@am11

am11 commented Mar 3, 2026

Copy link
Copy Markdown
Member

My understanding is; with Microsoft SDK:

  1. PortableRuntimeIdentifierGraph.json is used by default
  2. runtime.json is used as a fallback for < .NET8 SDKs or when user specifies UseRidGraph=true (so it is set-in-stone / considered immutable)
  3. There is an override RuntimeIdentifierGraphPath where user can provide their custom graph.

Distro maintainers use 3rd option (graph gets generated during the source-bulid).

If this is correct, then we don't need to change runtime.json for older/outdated SDK deployments to keep working. Otherwise, I misunderstood. 🙂

cc @elinor-fung

@richlander

Copy link
Copy Markdown
MemberAuthor

The intent is to remove cruft from the product. The RID file is basically a wikipedia of old distros. I'd like to eventually delete the file. I grasp, as you are suggesting, that its also enable compatibility for old assets on nuget.org, otherise they are basically unusable. Consumers can either use old SDKs, insert their own RID graph, or user a newer version. Some of the libraries may be abandoned. It's OK to have to take extra steps to use abandoned software.

@richlander

Copy link
Copy Markdown
MemberAuthor

Here is the data we collected, sorted by package count with a cutoff at 10 packages. The primary data I see is that we should consider bringing some Ubuntu RIDs back. On that note, I see that Ubuntu 23.10 is the latest/retained Ubuntu RID. That's not super useful. If we follow the data, we could replace 23.10 with 18.04 and that would solve most of the problem.

RIDPackagesTotalDownloads
win-x642619207237330
win204919292274122
win-x861829177109693
linux-x641708129237714
unix11237254257098
osx-x64109849230613
win-arm6482310471924
linux-arm6463282847442
win10-x6459011712306
osx569592532030
win10-x8655811400902
linux-arm48277527334
win10-arm4608308597
osx-arm6445011622264
linux-musl-x643526193593
win-arm34962507883
linux-x862769332247
alpine-x642391957557
win7-x641969761981
browser18852817835
linux179422141284
linux-armel17062772107
linux-musl-arm641561505670
win7-x861508884912
win10-arm641481613561
linux-musl-arm1481319978
ubuntu.18.04-x641431731579
rhel-x64140879046
fedora-x641371093005
debian.9-x641301636565
alpine.3.9-x64102819572
debian-arm6497814104
ubuntu.16.04-arm6497814104
linux-mips6484277434
android-arm64788947188
maccatalyst-x64716129705
maccatalyst-arm64705851291
android-x64698941814
linux-s390x67255760
android-arm668878358
android-x86618881581
browser-wasm60105415377
ios511631429
freebsd481499857
any46527589
native1.12-tchmi446013105
win8-arm44656478
linux-ppc64le37237069
win81-x6434162713
win81-x8634161137
ubuntu.16.04-x64321885962
ios-arm64318446030
tvos311037541
win8-x6430184919
win8-x8630179797
iossimulator-x64278675284
illumos27972741
solaris27972741
alpine-arm642770014
alpine-arm2663432
iossimulator-arm64258406514
aot235585530322
debian-x6423128315
x6421307951
ios-arm2014353065
tvos-arm6420512633
tvossimulator-x6420472887
centos-x6419175450
ubuntu.20.04-x6418262325
ios-armv7s1752958
ubuntu.14.04-x64166031
osx-641551277
win7-arm1512699
models156303
win714540652238
osx.10.10-x6414164277
arm641411382
osx-universal148509
native1317253297
x8613297447
win81-arm13223363
linux-641354125
debian.8-x6412187855
rhel.7-x6411791721
opensuse-x6411248293
fedora.23-x64105948
opensuse.13.2-x64105948

@tmds

tmds commented Mar 4, 2026

Copy link
Copy Markdown
Member

runtime.json is used as a fallback for < .NET8 SDKs or when user specifies UseRidGraph=true

Ah, yes.

I think users should use APIs like NativeLibrary.SetDllImportResolver instead of UseRidGraph.

It doesn't seem a mechanism that is relied on for splitting nuget packages either. Searching for latest Ubuntu LTS shows only 7 packages (by 5 users): https://www.nuget.org/packages?q=ubuntu.24.04-x64.

@richlander

Copy link
Copy Markdown
MemberAuthor

That's a good point. As I hinted at, my hope would be to make this change for 11 and the delete most of the infra for 12.

elinor-fung pushed a commit that referenced this pull request Mar 26, 2026
This fallback code (`get_current_os_rid_platform`) will probably go away
in the future once #125076 has
landed, but as it stands, we need this for parity. C++ libraries
version-less symlinks are needed for cmake/clang to avoid falling back
to non-fPIC libc++.a (because libc++.so.x.y is versioned).
With this patch, `./build.sh host.native --cross --os openbsd --arch
x64` succeeds.
Upstream PR for eng/common change:
dotnet/arcade#16564
@github-actions

github-actionsBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Workflow state for the Holistic Review Orchestrator.

{
"version": 5,
"last_dispatched_commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"last_dispatched_base_ref": "main",
"last_dispatched_base_sha": "b0bc48eea7e28be9670d4ac499a5778d0ac99909",
"last_reviewed_commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"last_reviewed_base_ref": "main",
"last_reviewed_base_sha": "b0bc48eea7e28be9670d4ac499a5778d0ac99909",
"last_recorded_worker_run_id": "29673725116",
"review_attempt_commit": "",
"review_attempt_base_ref": "",
"review_attempt_count": 0,
"max_review_attempts": 5,
"review_history_format": "holistic-review-disclosure-v1",
"review_history": [
{
"commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"review_id": 4730113525
}
]
}

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Holistic Review

Motivation: The PR trims src/libraries/Microsoft.NETCore.Platforms/src/runtime.json from 798 RIDs (~4600 lines) to 266 RIDs (~1500 lines). The goal is to stop the unbounded growth of the non-portable RID graph by removing every intermediate versioned/distro-specific RID while preserving base/portable RIDs, all floating (unversioned) OS RIDs, and the single most-recent versioned RID for each OS family plus its arch variants. It is a softer successor to #123161 (which removed all versioned/distro RIDs) intended to leave a migration path for packages that reference the newest versioned RIDs.

Approach: This is a pure data-file change to the transport package that is redistributed into the dotnet/sdk RID graph; no code, tooling (UpdateRuntimeIdentifierGraph.cs), or PortableRuntimeIdentifierGraph.json was touched. I verified the resulting graph independently of the description:

  • JSON is well-formed (jq parses; runtimes has 266 entries).
  • No dangling imports: every RID referenced in a #import array (198 distinct) is still defined as a top-level key. So removing ~721 keys did not orphan any surviving RID.
  • Kept versioned RIDs were correctly re-pointed: previously each last-version RID chained through the removed intermediate (e.g. osx.13 -> osx.12, alpine.3.18 -> alpine.3.17, osx.13-x64 -> osx.12-x64). In the new graph they import their floating base directly (osx.13 -> osx, osx.13-x64 -> osx.13,osx-x64), which is the correct rewrite to keep the graph connected after the intermediates are gone.
  • No repo-internal fallout: I grepped eng/ and src/ for representative removed RIDs (e.g. osx.10.12, ubuntu.18.04, alpine.3.17, rhel.7) and found no build/test/pipeline references that depend on them.

The change is internally consistent and the mechanical execution looks correct.

Summary: LGTM on correctness of the graph edit itself. The substantive consideration is not a code defect but a compatibility/policy judgment that belongs to the maintainers and the SDK team: removing intermediate versioned RIDs is an intentional behavior change to NuGet RID-based asset selection. Any existing package that ships assets exclusively under a now-removed RID (e.g. runtimes/ubuntu.16.04-x64/...) will no longer have that RID in the graph, so a project resolving for such a RID would fall back to the floating/base asset (or fail to see the RID at all) rather than the version-specific one. The PR description acknowledges this as the intended tradeoff with a documented migration story, and readme.md already states the graph should no longer gain new version-specific RIDs. Because this is the whole point of the PR and there is no single changed line to attach it to, I raise it here rather than as an inline finding. I'd recommend confirming (a) the SDK-side consumption and any published compat/breaking-change guidance are lined up, and (b) that the "last versioned RID per family" selection is genuinely the newest for each family (spot checks such as alpine.3.18, osx.13, ubuntu.23.10, debian.12, fedora.39 looked right). No blocking correctness issues found in the diff.

Note

This review was generated by this repository's Holistic Review agentic workflow to complement the built-in Copilot review.

Generated by Holistic Review · 130.8 AIC · ⌖ 10.7 AIC · ⊞ 10K

@elinor-fung

Copy link
Copy Markdown
Member

I assume we'd want to breaking change doc this?

The change seems generally reasonable to me as a step towards a future larger breaking change of removing the non-portable RID graph compat mode entirely.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@richlander@ericstj@tmds@am11@elinor-fung
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Simplify RID graph: keep floating and last versioned RIDs - #125076

Open
richlander wants to merge 1 commit into
mainfrom
simplify-rid-graph-soft
Open

Simplify RID graph: keep floating and last versioned RIDs#125076
richlander wants to merge 1 commit into
mainfrom
simplify-rid-graph-soft

Conversation

@richlander

Copy link
Copy Markdown
Member

Replaces: #123161

Softer approach to RID graph simplification. Instead of removing all versioned and distro-specific RIDs, this keeps:

  • All portable/base RIDs (any, unix, linux, win, etc.)
  • All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
  • The last versioned RID for each OS family and its arch variants

This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines (266 RIDs) while preserving a migration path for packages that reference the most recent versioned RIDs.

We can do more cleanup later. This approach is a much safer starting point with easier migration guidance. It's also more defensible.

Removed RIDs: all intermediate versioned RIDs (e.g. alpine.3.7 through alpine.3.17, ubuntu.14.04 through ubuntu.23.04, osx.10.10 through osx.12, etc.)

Kept last versions include: alpine.3.18, android.32, centos.9, debian.12, fedora.39, freebsd.13, ios.15, osx.13, rhel.9, rocky.9, tizen.7.0.0, tvos.15, ubuntu.23.10, and others.

Softer approach to RID graph simplification. Instead of removing all
versioned and distro-specific RIDs, this keeps:
- All portable/base RIDs (any, unix, linux, win, etc.)
- All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
- The last versioned RID for each OS family and its arch variants
This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines
(266 RIDs) while preserving a migration path for packages that reference
the most recent versioned RIDs.
Removed RIDs: all intermediate versioned RIDs (e.g. alpine.3.7 through
alpine.3.17, ubuntu.14.04 through ubuntu.23.04, osx.10.10 through
osx.12, etc.)
Kept last versions include: alpine.3.18, android.32, centos.9,
debian.12, fedora.39, freebsd.13, ios.15, osx.13, rhel.9, rocky.9,
tizen.7.0.0, tvos.15, ubuntu.23.10, and others.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings March 2, 2026 20:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review any files in this pull request.

@richlander

richlander commented Mar 2, 2026

Copy link
Copy Markdown
MemberAuthor

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke, @jeffschwMSFT, @elinor-fung
See info in area-owners.md if you want to be subscribed.

@ericstj

Copy link
Copy Markdown
Member

What have you done to test this? Did you consider making this change in the VMR so that we can see if source build and phase2 product build are happy with the changes?

@richlander

Copy link
Copy Markdown
MemberAuthor

Great questions. I haven't done anything to test it. My belief/understanding is that the fallout is compat. I can make this change in VMR. That didn't occur to me. My thinking -- perhaps naive -- is that any break there is a bug that needs to be fixed downstream. I'll apply this change to VMR.

richlander pushed a commit to dotnet/dotnet that referenced this pull request Mar 2, 2026
Softer approach to RID graph simplification. Instead of removing all
versioned and distro-specific RIDs, this keeps:
- All portable/base RIDs (any, unix, linux, win, etc.)
- All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
- The last versioned RID for each OS family and its arch variants
This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines
(266 RIDs) while preserving a migration path for packages that reference
the most recent versioned RIDs.
Backport of dotnet/runtime#125076
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ericstj

ericstj commented Mar 2, 2026

Copy link
Copy Markdown
Member

Great questions. I haven't done anything to test it. My belief/understanding is that the fallout is compat. I can make this change in VMR. That didn't occur to me. My thinking -- perhaps naive -- is that any break there is a bug that needs to be fixed downstream. I'll apply this change to VMR.

It should be, but we might want to get that signal now. I think the VMR can give at least a sampling of those it won't run the SDK tests which I think might be equally valuable, but we don't have a good way to do that in PR.

I don't have any objections to the PR itself, it's more "what's the fallout". I trust its well formed, but I am not reviewing for that. We used to have a generator for this that made it a bit easier to review the changes to the generator inputs.

@richlander

Copy link
Copy Markdown
MemberAuthor

Understood. We're on the same page.

@tmds

tmds commented Mar 3, 2026

Copy link
Copy Markdown
Member

this keeps:
All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
The last versioned RID for each OS family and its arch variants

I'd consider removing these too.

The "modern" rid handling for a non-portable SDK depends on:

 "fedora.42-x64": [
"linux-x64",
"linux",
"unix-x64",
"unix",
"any",
"base"
]

@ericstj

Copy link
Copy Markdown
Member

I shared some data offline to show what packages are using the RIDs being discussed here. That provides a view of the producer side - we can't know what people use when building apps (consumer side) but a review of that data might help understand the compat impact of removing RIDs that might be used during restore.

@richlander

Copy link
Copy Markdown
MemberAuthor

This proposal is on top of this break that we made 3 years ago: dotnet/docs#36466

That break has a workaround. You can see it in use: https://grep.app/search?q=%3CUseRidGraph%3Etrue%3C%2FUseRidGraph%3E

The use of UseRidGraph suggests that the original change would have been too breaking.

@am11

am11 commented Mar 3, 2026

Copy link
Copy Markdown
Member

My understanding is; with Microsoft SDK:

  1. PortableRuntimeIdentifierGraph.json is used by default
  2. runtime.json is used as a fallback for < .NET8 SDKs or when user specifies UseRidGraph=true (so it is set-in-stone / considered immutable)
  3. There is an override RuntimeIdentifierGraphPath where user can provide their custom graph.

Distro maintainers use 3rd option (graph gets generated during the source-bulid).

If this is correct, then we don't need to change runtime.json for older/outdated SDK deployments to keep working. Otherwise, I misunderstood. 🙂

cc @elinor-fung

@richlander

Copy link
Copy Markdown
MemberAuthor

The intent is to remove cruft from the product. The RID file is basically a wikipedia of old distros. I'd like to eventually delete the file. I grasp, as you are suggesting, that its also enable compatibility for old assets on nuget.org, otherise they are basically unusable. Consumers can either use old SDKs, insert their own RID graph, or user a newer version. Some of the libraries may be abandoned. It's OK to have to take extra steps to use abandoned software.

@richlander

Copy link
Copy Markdown
MemberAuthor

Here is the data we collected, sorted by package count with a cutoff at 10 packages. The primary data I see is that we should consider bringing some Ubuntu RIDs back. On that note, I see that Ubuntu 23.10 is the latest/retained Ubuntu RID. That's not super useful. If we follow the data, we could replace 23.10 with 18.04 and that would solve most of the problem.

RIDPackagesTotalDownloads
win-x642619207237330
win204919292274122
win-x861829177109693
linux-x641708129237714
unix11237254257098
osx-x64109849230613
win-arm6482310471924
linux-arm6463282847442
win10-x6459011712306
osx569592532030
win10-x8655811400902
linux-arm48277527334
win10-arm4608308597
osx-arm6445011622264
linux-musl-x643526193593
win-arm34962507883
linux-x862769332247
alpine-x642391957557
win7-x641969761981
browser18852817835
linux179422141284
linux-armel17062772107
linux-musl-arm641561505670
win7-x861508884912
win10-arm641481613561
linux-musl-arm1481319978
ubuntu.18.04-x641431731579
rhel-x64140879046
fedora-x641371093005
debian.9-x641301636565
alpine.3.9-x64102819572
debian-arm6497814104
ubuntu.16.04-arm6497814104
linux-mips6484277434
android-arm64788947188
maccatalyst-x64716129705
maccatalyst-arm64705851291
android-x64698941814
linux-s390x67255760
android-arm668878358
android-x86618881581
browser-wasm60105415377
ios511631429
freebsd481499857
any46527589
native1.12-tchmi446013105
win8-arm44656478
linux-ppc64le37237069
win81-x6434162713
win81-x8634161137
ubuntu.16.04-x64321885962
ios-arm64318446030
tvos311037541
win8-x6430184919
win8-x8630179797
iossimulator-x64278675284
illumos27972741
solaris27972741
alpine-arm642770014
alpine-arm2663432
iossimulator-arm64258406514
aot235585530322
debian-x6423128315
x6421307951
ios-arm2014353065
tvos-arm6420512633
tvossimulator-x6420472887
centos-x6419175450
ubuntu.20.04-x6418262325
ios-armv7s1752958
ubuntu.14.04-x64166031
osx-641551277
win7-arm1512699
models156303
win714540652238
osx.10.10-x6414164277
arm641411382
osx-universal148509
native1317253297
x8613297447
win81-arm13223363
linux-641354125
debian.8-x6412187855
rhel.7-x6411791721
opensuse-x6411248293
fedora.23-x64105948
opensuse.13.2-x64105948

@tmds

tmds commented Mar 4, 2026

Copy link
Copy Markdown
Member

runtime.json is used as a fallback for < .NET8 SDKs or when user specifies UseRidGraph=true

Ah, yes.

I think users should use APIs like NativeLibrary.SetDllImportResolver instead of UseRidGraph.

It doesn't seem a mechanism that is relied on for splitting nuget packages either. Searching for latest Ubuntu LTS shows only 7 packages (by 5 users): https://www.nuget.org/packages?q=ubuntu.24.04-x64.

@richlander

Copy link
Copy Markdown
MemberAuthor

That's a good point. As I hinted at, my hope would be to make this change for 11 and the delete most of the infra for 12.

elinor-fung pushed a commit that referenced this pull request Mar 26, 2026
This fallback code (`get_current_os_rid_platform`) will probably go away
in the future once #125076 has
landed, but as it stands, we need this for parity. C++ libraries
version-less symlinks are needed for cmake/clang to avoid falling back
to non-fPIC libc++.a (because libc++.so.x.y is versioned).
With this patch, `./build.sh host.native --cross --os openbsd --arch
x64` succeeds.
Upstream PR for eng/common change:
dotnet/arcade#16564
@github-actions

github-actionsBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Workflow state for the Holistic Review Orchestrator.

{
"version": 5,
"last_dispatched_commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"last_dispatched_base_ref": "main",
"last_dispatched_base_sha": "b0bc48eea7e28be9670d4ac499a5778d0ac99909",
"last_reviewed_commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"last_reviewed_base_ref": "main",
"last_reviewed_base_sha": "b0bc48eea7e28be9670d4ac499a5778d0ac99909",
"last_recorded_worker_run_id": "29673725116",
"review_attempt_commit": "",
"review_attempt_base_ref": "",
"review_attempt_count": 0,
"max_review_attempts": 5,
"review_history_format": "holistic-review-disclosure-v1",
"review_history": [
{
"commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"review_id": 4730113525
}
]
}

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Holistic Review

Motivation: The PR trims src/libraries/Microsoft.NETCore.Platforms/src/runtime.json from 798 RIDs (~4600 lines) to 266 RIDs (~1500 lines). The goal is to stop the unbounded growth of the non-portable RID graph by removing every intermediate versioned/distro-specific RID while preserving base/portable RIDs, all floating (unversioned) OS RIDs, and the single most-recent versioned RID for each OS family plus its arch variants. It is a softer successor to #123161 (which removed all versioned/distro RIDs) intended to leave a migration path for packages that reference the newest versioned RIDs.

Approach: This is a pure data-file change to the transport package that is redistributed into the dotnet/sdk RID graph; no code, tooling (UpdateRuntimeIdentifierGraph.cs), or PortableRuntimeIdentifierGraph.json was touched. I verified the resulting graph independently of the description:

  • JSON is well-formed (jq parses; runtimes has 266 entries).
  • No dangling imports: every RID referenced in a #import array (198 distinct) is still defined as a top-level key. So removing ~721 keys did not orphan any surviving RID.
  • Kept versioned RIDs were correctly re-pointed: previously each last-version RID chained through the removed intermediate (e.g. osx.13 -> osx.12, alpine.3.18 -> alpine.3.17, osx.13-x64 -> osx.12-x64). In the new graph they import their floating base directly (osx.13 -> osx, osx.13-x64 -> osx.13,osx-x64), which is the correct rewrite to keep the graph connected after the intermediates are gone.
  • No repo-internal fallout: I grepped eng/ and src/ for representative removed RIDs (e.g. osx.10.12, ubuntu.18.04, alpine.3.17, rhel.7) and found no build/test/pipeline references that depend on them.

The change is internally consistent and the mechanical execution looks correct.

Summary: LGTM on correctness of the graph edit itself. The substantive consideration is not a code defect but a compatibility/policy judgment that belongs to the maintainers and the SDK team: removing intermediate versioned RIDs is an intentional behavior change to NuGet RID-based asset selection. Any existing package that ships assets exclusively under a now-removed RID (e.g. runtimes/ubuntu.16.04-x64/...) will no longer have that RID in the graph, so a project resolving for such a RID would fall back to the floating/base asset (or fail to see the RID at all) rather than the version-specific one. The PR description acknowledges this as the intended tradeoff with a documented migration story, and readme.md already states the graph should no longer gain new version-specific RIDs. Because this is the whole point of the PR and there is no single changed line to attach it to, I raise it here rather than as an inline finding. I'd recommend confirming (a) the SDK-side consumption and any published compat/breaking-change guidance are lined up, and (b) that the "last versioned RID per family" selection is genuinely the newest for each family (spot checks such as alpine.3.18, osx.13, ubuntu.23.10, debian.12, fedora.39 looked right). No blocking correctness issues found in the diff.

Note

This review was generated by this repository's Holistic Review agentic workflow to complement the built-in Copilot review.

Generated by Holistic Review · 130.8 AIC · ⌖ 10.7 AIC · ⊞ 10K

@elinor-fung

Copy link
Copy Markdown
Member

I assume we'd want to breaking change doc this?

The change seems generally reasonable to me as a step towards a future larger breaking change of removing the non-portable RID graph compat mode entirely.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@richlander@ericstj@tmds@am11@elinor-fung
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Simplify RID graph: keep floating and last versioned RIDs - #125076

Open
richlander wants to merge 1 commit into
mainfrom
simplify-rid-graph-soft
Open

Simplify RID graph: keep floating and last versioned RIDs#125076
richlander wants to merge 1 commit into
mainfrom
simplify-rid-graph-soft

Conversation

@richlander

Copy link
Copy Markdown
Member

Replaces: #123161

Softer approach to RID graph simplification. Instead of removing all versioned and distro-specific RIDs, this keeps:

  • All portable/base RIDs (any, unix, linux, win, etc.)
  • All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
  • The last versioned RID for each OS family and its arch variants

This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines (266 RIDs) while preserving a migration path for packages that reference the most recent versioned RIDs.

We can do more cleanup later. This approach is a much safer starting point with easier migration guidance. It's also more defensible.

Removed RIDs: all intermediate versioned RIDs (e.g. alpine.3.7 through alpine.3.17, ubuntu.14.04 through ubuntu.23.04, osx.10.10 through osx.12, etc.)

Kept last versions include: alpine.3.18, android.32, centos.9, debian.12, fedora.39, freebsd.13, ios.15, osx.13, rhel.9, rocky.9, tizen.7.0.0, tvos.15, ubuntu.23.10, and others.

Softer approach to RID graph simplification. Instead of removing all
versioned and distro-specific RIDs, this keeps:
- All portable/base RIDs (any, unix, linux, win, etc.)
- All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
- The last versioned RID for each OS family and its arch variants
This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines
(266 RIDs) while preserving a migration path for packages that reference
the most recent versioned RIDs.
Removed RIDs: all intermediate versioned RIDs (e.g. alpine.3.7 through
alpine.3.17, ubuntu.14.04 through ubuntu.23.04, osx.10.10 through
osx.12, etc.)
Kept last versions include: alpine.3.18, android.32, centos.9,
debian.12, fedora.39, freebsd.13, ios.15, osx.13, rhel.9, rocky.9,
tizen.7.0.0, tvos.15, ubuntu.23.10, and others.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings March 2, 2026 20:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review any files in this pull request.

@richlander

richlander commented Mar 2, 2026

Copy link
Copy Markdown
MemberAuthor

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke, @jeffschwMSFT, @elinor-fung
See info in area-owners.md if you want to be subscribed.

@ericstj

Copy link
Copy Markdown
Member

What have you done to test this? Did you consider making this change in the VMR so that we can see if source build and phase2 product build are happy with the changes?

@richlander

Copy link
Copy Markdown
MemberAuthor

Great questions. I haven't done anything to test it. My belief/understanding is that the fallout is compat. I can make this change in VMR. That didn't occur to me. My thinking -- perhaps naive -- is that any break there is a bug that needs to be fixed downstream. I'll apply this change to VMR.

richlander pushed a commit to dotnet/dotnet that referenced this pull request Mar 2, 2026
Softer approach to RID graph simplification. Instead of removing all
versioned and distro-specific RIDs, this keeps:
- All portable/base RIDs (any, unix, linux, win, etc.)
- All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
- The last versioned RID for each OS family and its arch variants
This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines
(266 RIDs) while preserving a migration path for packages that reference
the most recent versioned RIDs.
Backport of dotnet/runtime#125076
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ericstj

ericstj commented Mar 2, 2026

Copy link
Copy Markdown
Member

Great questions. I haven't done anything to test it. My belief/understanding is that the fallout is compat. I can make this change in VMR. That didn't occur to me. My thinking -- perhaps naive -- is that any break there is a bug that needs to be fixed downstream. I'll apply this change to VMR.

It should be, but we might want to get that signal now. I think the VMR can give at least a sampling of those it won't run the SDK tests which I think might be equally valuable, but we don't have a good way to do that in PR.

I don't have any objections to the PR itself, it's more "what's the fallout". I trust its well formed, but I am not reviewing for that. We used to have a generator for this that made it a bit easier to review the changes to the generator inputs.

@richlander

Copy link
Copy Markdown
MemberAuthor

Understood. We're on the same page.

@tmds

tmds commented Mar 3, 2026

Copy link
Copy Markdown
Member

this keeps:
All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
The last versioned RID for each OS family and its arch variants

I'd consider removing these too.

The "modern" rid handling for a non-portable SDK depends on:

 "fedora.42-x64": [
"linux-x64",
"linux",
"unix-x64",
"unix",
"any",
"base"
]

@ericstj

Copy link
Copy Markdown
Member

I shared some data offline to show what packages are using the RIDs being discussed here. That provides a view of the producer side - we can't know what people use when building apps (consumer side) but a review of that data might help understand the compat impact of removing RIDs that might be used during restore.

@richlander

Copy link
Copy Markdown
MemberAuthor

This proposal is on top of this break that we made 3 years ago: dotnet/docs#36466

That break has a workaround. You can see it in use: https://grep.app/search?q=%3CUseRidGraph%3Etrue%3C%2FUseRidGraph%3E

The use of UseRidGraph suggests that the original change would have been too breaking.

@am11

am11 commented Mar 3, 2026

Copy link
Copy Markdown
Member

My understanding is; with Microsoft SDK:

  1. PortableRuntimeIdentifierGraph.json is used by default
  2. runtime.json is used as a fallback for < .NET8 SDKs or when user specifies UseRidGraph=true (so it is set-in-stone / considered immutable)
  3. There is an override RuntimeIdentifierGraphPath where user can provide their custom graph.

Distro maintainers use 3rd option (graph gets generated during the source-bulid).

If this is correct, then we don't need to change runtime.json for older/outdated SDK deployments to keep working. Otherwise, I misunderstood. 🙂

cc @elinor-fung

@richlander

Copy link
Copy Markdown
MemberAuthor

The intent is to remove cruft from the product. The RID file is basically a wikipedia of old distros. I'd like to eventually delete the file. I grasp, as you are suggesting, that its also enable compatibility for old assets on nuget.org, otherise they are basically unusable. Consumers can either use old SDKs, insert their own RID graph, or user a newer version. Some of the libraries may be abandoned. It's OK to have to take extra steps to use abandoned software.

@richlander

Copy link
Copy Markdown
MemberAuthor

Here is the data we collected, sorted by package count with a cutoff at 10 packages. The primary data I see is that we should consider bringing some Ubuntu RIDs back. On that note, I see that Ubuntu 23.10 is the latest/retained Ubuntu RID. That's not super useful. If we follow the data, we could replace 23.10 with 18.04 and that would solve most of the problem.

RIDPackagesTotalDownloads
win-x642619207237330
win204919292274122
win-x861829177109693
linux-x641708129237714
unix11237254257098
osx-x64109849230613
win-arm6482310471924
linux-arm6463282847442
win10-x6459011712306
osx569592532030
win10-x8655811400902
linux-arm48277527334
win10-arm4608308597
osx-arm6445011622264
linux-musl-x643526193593
win-arm34962507883
linux-x862769332247
alpine-x642391957557
win7-x641969761981
browser18852817835
linux179422141284
linux-armel17062772107
linux-musl-arm641561505670
win7-x861508884912
win10-arm641481613561
linux-musl-arm1481319978
ubuntu.18.04-x641431731579
rhel-x64140879046
fedora-x641371093005
debian.9-x641301636565
alpine.3.9-x64102819572
debian-arm6497814104
ubuntu.16.04-arm6497814104
linux-mips6484277434
android-arm64788947188
maccatalyst-x64716129705
maccatalyst-arm64705851291
android-x64698941814
linux-s390x67255760
android-arm668878358
android-x86618881581
browser-wasm60105415377
ios511631429
freebsd481499857
any46527589
native1.12-tchmi446013105
win8-arm44656478
linux-ppc64le37237069
win81-x6434162713
win81-x8634161137
ubuntu.16.04-x64321885962
ios-arm64318446030
tvos311037541
win8-x6430184919
win8-x8630179797
iossimulator-x64278675284
illumos27972741
solaris27972741
alpine-arm642770014
alpine-arm2663432
iossimulator-arm64258406514
aot235585530322
debian-x6423128315
x6421307951
ios-arm2014353065
tvos-arm6420512633
tvossimulator-x6420472887
centos-x6419175450
ubuntu.20.04-x6418262325
ios-armv7s1752958
ubuntu.14.04-x64166031
osx-641551277
win7-arm1512699
models156303
win714540652238
osx.10.10-x6414164277
arm641411382
osx-universal148509
native1317253297
x8613297447
win81-arm13223363
linux-641354125
debian.8-x6412187855
rhel.7-x6411791721
opensuse-x6411248293
fedora.23-x64105948
opensuse.13.2-x64105948

@tmds

tmds commented Mar 4, 2026

Copy link
Copy Markdown
Member

runtime.json is used as a fallback for < .NET8 SDKs or when user specifies UseRidGraph=true

Ah, yes.

I think users should use APIs like NativeLibrary.SetDllImportResolver instead of UseRidGraph.

It doesn't seem a mechanism that is relied on for splitting nuget packages either. Searching for latest Ubuntu LTS shows only 7 packages (by 5 users): https://www.nuget.org/packages?q=ubuntu.24.04-x64.

@richlander

Copy link
Copy Markdown
MemberAuthor

That's a good point. As I hinted at, my hope would be to make this change for 11 and the delete most of the infra for 12.

elinor-fung pushed a commit that referenced this pull request Mar 26, 2026
This fallback code (`get_current_os_rid_platform`) will probably go away
in the future once #125076 has
landed, but as it stands, we need this for parity. C++ libraries
version-less symlinks are needed for cmake/clang to avoid falling back
to non-fPIC libc++.a (because libc++.so.x.y is versioned).
With this patch, `./build.sh host.native --cross --os openbsd --arch
x64` succeeds.
Upstream PR for eng/common change:
dotnet/arcade#16564
@github-actions

github-actionsBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Workflow state for the Holistic Review Orchestrator.

{
"version": 5,
"last_dispatched_commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"last_dispatched_base_ref": "main",
"last_dispatched_base_sha": "b0bc48eea7e28be9670d4ac499a5778d0ac99909",
"last_reviewed_commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"last_reviewed_base_ref": "main",
"last_reviewed_base_sha": "b0bc48eea7e28be9670d4ac499a5778d0ac99909",
"last_recorded_worker_run_id": "29673725116",
"review_attempt_commit": "",
"review_attempt_base_ref": "",
"review_attempt_count": 0,
"max_review_attempts": 5,
"review_history_format": "holistic-review-disclosure-v1",
"review_history": [
{
"commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"review_id": 4730113525
}
]
}

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Holistic Review

Motivation: The PR trims src/libraries/Microsoft.NETCore.Platforms/src/runtime.json from 798 RIDs (~4600 lines) to 266 RIDs (~1500 lines). The goal is to stop the unbounded growth of the non-portable RID graph by removing every intermediate versioned/distro-specific RID while preserving base/portable RIDs, all floating (unversioned) OS RIDs, and the single most-recent versioned RID for each OS family plus its arch variants. It is a softer successor to #123161 (which removed all versioned/distro RIDs) intended to leave a migration path for packages that reference the newest versioned RIDs.

Approach: This is a pure data-file change to the transport package that is redistributed into the dotnet/sdk RID graph; no code, tooling (UpdateRuntimeIdentifierGraph.cs), or PortableRuntimeIdentifierGraph.json was touched. I verified the resulting graph independently of the description:

  • JSON is well-formed (jq parses; runtimes has 266 entries).
  • No dangling imports: every RID referenced in a #import array (198 distinct) is still defined as a top-level key. So removing ~721 keys did not orphan any surviving RID.
  • Kept versioned RIDs were correctly re-pointed: previously each last-version RID chained through the removed intermediate (e.g. osx.13 -> osx.12, alpine.3.18 -> alpine.3.17, osx.13-x64 -> osx.12-x64). In the new graph they import their floating base directly (osx.13 -> osx, osx.13-x64 -> osx.13,osx-x64), which is the correct rewrite to keep the graph connected after the intermediates are gone.
  • No repo-internal fallout: I grepped eng/ and src/ for representative removed RIDs (e.g. osx.10.12, ubuntu.18.04, alpine.3.17, rhel.7) and found no build/test/pipeline references that depend on them.

The change is internally consistent and the mechanical execution looks correct.

Summary: LGTM on correctness of the graph edit itself. The substantive consideration is not a code defect but a compatibility/policy judgment that belongs to the maintainers and the SDK team: removing intermediate versioned RIDs is an intentional behavior change to NuGet RID-based asset selection. Any existing package that ships assets exclusively under a now-removed RID (e.g. runtimes/ubuntu.16.04-x64/...) will no longer have that RID in the graph, so a project resolving for such a RID would fall back to the floating/base asset (or fail to see the RID at all) rather than the version-specific one. The PR description acknowledges this as the intended tradeoff with a documented migration story, and readme.md already states the graph should no longer gain new version-specific RIDs. Because this is the whole point of the PR and there is no single changed line to attach it to, I raise it here rather than as an inline finding. I'd recommend confirming (a) the SDK-side consumption and any published compat/breaking-change guidance are lined up, and (b) that the "last versioned RID per family" selection is genuinely the newest for each family (spot checks such as alpine.3.18, osx.13, ubuntu.23.10, debian.12, fedora.39 looked right). No blocking correctness issues found in the diff.

Note

This review was generated by this repository's Holistic Review agentic workflow to complement the built-in Copilot review.

Generated by Holistic Review · 130.8 AIC · ⌖ 10.7 AIC · ⊞ 10K

@elinor-fung

Copy link
Copy Markdown
Member

I assume we'd want to breaking change doc this?

The change seems generally reasonable to me as a step towards a future larger breaking change of removing the non-portable RID graph compat mode entirely.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@richlander@ericstj@tmds@am11@elinor-fung
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Simplify RID graph: keep floating and last versioned RIDs - #125076

Open
richlander wants to merge 1 commit into
mainfrom
simplify-rid-graph-soft
Open

Simplify RID graph: keep floating and last versioned RIDs#125076
richlander wants to merge 1 commit into
mainfrom
simplify-rid-graph-soft

Conversation

@richlander

Copy link
Copy Markdown
Member

Replaces: #123161

Softer approach to RID graph simplification. Instead of removing all versioned and distro-specific RIDs, this keeps:

  • All portable/base RIDs (any, unix, linux, win, etc.)
  • All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
  • The last versioned RID for each OS family and its arch variants

This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines (266 RIDs) while preserving a migration path for packages that reference the most recent versioned RIDs.

We can do more cleanup later. This approach is a much safer starting point with easier migration guidance. It's also more defensible.

Removed RIDs: all intermediate versioned RIDs (e.g. alpine.3.7 through alpine.3.17, ubuntu.14.04 through ubuntu.23.04, osx.10.10 through osx.12, etc.)

Kept last versions include: alpine.3.18, android.32, centos.9, debian.12, fedora.39, freebsd.13, ios.15, osx.13, rhel.9, rocky.9, tizen.7.0.0, tvos.15, ubuntu.23.10, and others.

Softer approach to RID graph simplification. Instead of removing all
versioned and distro-specific RIDs, this keeps:
- All portable/base RIDs (any, unix, linux, win, etc.)
- All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
- The last versioned RID for each OS family and its arch variants
This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines
(266 RIDs) while preserving a migration path for packages that reference
the most recent versioned RIDs.
Removed RIDs: all intermediate versioned RIDs (e.g. alpine.3.7 through
alpine.3.17, ubuntu.14.04 through ubuntu.23.04, osx.10.10 through
osx.12, etc.)
Kept last versions include: alpine.3.18, android.32, centos.9,
debian.12, fedora.39, freebsd.13, ios.15, osx.13, rhel.9, rocky.9,
tizen.7.0.0, tvos.15, ubuntu.23.10, and others.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings March 2, 2026 20:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review any files in this pull request.

@richlander

richlander commented Mar 2, 2026

Copy link
Copy Markdown
MemberAuthor

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke, @jeffschwMSFT, @elinor-fung
See info in area-owners.md if you want to be subscribed.

@ericstj

Copy link
Copy Markdown
Member

What have you done to test this? Did you consider making this change in the VMR so that we can see if source build and phase2 product build are happy with the changes?

@richlander

Copy link
Copy Markdown
MemberAuthor

Great questions. I haven't done anything to test it. My belief/understanding is that the fallout is compat. I can make this change in VMR. That didn't occur to me. My thinking -- perhaps naive -- is that any break there is a bug that needs to be fixed downstream. I'll apply this change to VMR.

richlander pushed a commit to dotnet/dotnet that referenced this pull request Mar 2, 2026
Softer approach to RID graph simplification. Instead of removing all
versioned and distro-specific RIDs, this keeps:
- All portable/base RIDs (any, unix, linux, win, etc.)
- All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
- The last versioned RID for each OS family and its arch variants
This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines
(266 RIDs) while preserving a migration path for packages that reference
the most recent versioned RIDs.
Backport of dotnet/runtime#125076
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ericstj

ericstj commented Mar 2, 2026

Copy link
Copy Markdown
Member

Great questions. I haven't done anything to test it. My belief/understanding is that the fallout is compat. I can make this change in VMR. That didn't occur to me. My thinking -- perhaps naive -- is that any break there is a bug that needs to be fixed downstream. I'll apply this change to VMR.

It should be, but we might want to get that signal now. I think the VMR can give at least a sampling of those it won't run the SDK tests which I think might be equally valuable, but we don't have a good way to do that in PR.

I don't have any objections to the PR itself, it's more "what's the fallout". I trust its well formed, but I am not reviewing for that. We used to have a generator for this that made it a bit easier to review the changes to the generator inputs.

@richlander

Copy link
Copy Markdown
MemberAuthor

Understood. We're on the same page.

@tmds

tmds commented Mar 3, 2026

Copy link
Copy Markdown
Member

this keeps:
All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
The last versioned RID for each OS family and its arch variants

I'd consider removing these too.

The "modern" rid handling for a non-portable SDK depends on:

 "fedora.42-x64": [
"linux-x64",
"linux",
"unix-x64",
"unix",
"any",
"base"
]

@ericstj

Copy link
Copy Markdown
Member

I shared some data offline to show what packages are using the RIDs being discussed here. That provides a view of the producer side - we can't know what people use when building apps (consumer side) but a review of that data might help understand the compat impact of removing RIDs that might be used during restore.

@richlander

Copy link
Copy Markdown
MemberAuthor

This proposal is on top of this break that we made 3 years ago: dotnet/docs#36466

That break has a workaround. You can see it in use: https://grep.app/search?q=%3CUseRidGraph%3Etrue%3C%2FUseRidGraph%3E

The use of UseRidGraph suggests that the original change would have been too breaking.

@am11

am11 commented Mar 3, 2026

Copy link
Copy Markdown
Member

My understanding is; with Microsoft SDK:

  1. PortableRuntimeIdentifierGraph.json is used by default
  2. runtime.json is used as a fallback for < .NET8 SDKs or when user specifies UseRidGraph=true (so it is set-in-stone / considered immutable)
  3. There is an override RuntimeIdentifierGraphPath where user can provide their custom graph.

Distro maintainers use 3rd option (graph gets generated during the source-bulid).

If this is correct, then we don't need to change runtime.json for older/outdated SDK deployments to keep working. Otherwise, I misunderstood. 🙂

cc @elinor-fung

@richlander

Copy link
Copy Markdown
MemberAuthor

The intent is to remove cruft from the product. The RID file is basically a wikipedia of old distros. I'd like to eventually delete the file. I grasp, as you are suggesting, that its also enable compatibility for old assets on nuget.org, otherise they are basically unusable. Consumers can either use old SDKs, insert their own RID graph, or user a newer version. Some of the libraries may be abandoned. It's OK to have to take extra steps to use abandoned software.

@richlander

Copy link
Copy Markdown
MemberAuthor

Here is the data we collected, sorted by package count with a cutoff at 10 packages. The primary data I see is that we should consider bringing some Ubuntu RIDs back. On that note, I see that Ubuntu 23.10 is the latest/retained Ubuntu RID. That's not super useful. If we follow the data, we could replace 23.10 with 18.04 and that would solve most of the problem.

RIDPackagesTotalDownloads
win-x642619207237330
win204919292274122
win-x861829177109693
linux-x641708129237714
unix11237254257098
osx-x64109849230613
win-arm6482310471924
linux-arm6463282847442
win10-x6459011712306
osx569592532030
win10-x8655811400902
linux-arm48277527334
win10-arm4608308597
osx-arm6445011622264
linux-musl-x643526193593
win-arm34962507883
linux-x862769332247
alpine-x642391957557
win7-x641969761981
browser18852817835
linux179422141284
linux-armel17062772107
linux-musl-arm641561505670
win7-x861508884912
win10-arm641481613561
linux-musl-arm1481319978
ubuntu.18.04-x641431731579
rhel-x64140879046
fedora-x641371093005
debian.9-x641301636565
alpine.3.9-x64102819572
debian-arm6497814104
ubuntu.16.04-arm6497814104
linux-mips6484277434
android-arm64788947188
maccatalyst-x64716129705
maccatalyst-arm64705851291
android-x64698941814
linux-s390x67255760
android-arm668878358
android-x86618881581
browser-wasm60105415377
ios511631429
freebsd481499857
any46527589
native1.12-tchmi446013105
win8-arm44656478
linux-ppc64le37237069
win81-x6434162713
win81-x8634161137
ubuntu.16.04-x64321885962
ios-arm64318446030
tvos311037541
win8-x6430184919
win8-x8630179797
iossimulator-x64278675284
illumos27972741
solaris27972741
alpine-arm642770014
alpine-arm2663432
iossimulator-arm64258406514
aot235585530322
debian-x6423128315
x6421307951
ios-arm2014353065
tvos-arm6420512633
tvossimulator-x6420472887
centos-x6419175450
ubuntu.20.04-x6418262325
ios-armv7s1752958
ubuntu.14.04-x64166031
osx-641551277
win7-arm1512699
models156303
win714540652238
osx.10.10-x6414164277
arm641411382
osx-universal148509
native1317253297
x8613297447
win81-arm13223363
linux-641354125
debian.8-x6412187855
rhel.7-x6411791721
opensuse-x6411248293
fedora.23-x64105948
opensuse.13.2-x64105948

@tmds

tmds commented Mar 4, 2026

Copy link
Copy Markdown
Member

runtime.json is used as a fallback for < .NET8 SDKs or when user specifies UseRidGraph=true

Ah, yes.

I think users should use APIs like NativeLibrary.SetDllImportResolver instead of UseRidGraph.

It doesn't seem a mechanism that is relied on for splitting nuget packages either. Searching for latest Ubuntu LTS shows only 7 packages (by 5 users): https://www.nuget.org/packages?q=ubuntu.24.04-x64.

@richlander

Copy link
Copy Markdown
MemberAuthor

That's a good point. As I hinted at, my hope would be to make this change for 11 and the delete most of the infra for 12.

elinor-fung pushed a commit that referenced this pull request Mar 26, 2026
This fallback code (`get_current_os_rid_platform`) will probably go away
in the future once #125076 has
landed, but as it stands, we need this for parity. C++ libraries
version-less symlinks are needed for cmake/clang to avoid falling back
to non-fPIC libc++.a (because libc++.so.x.y is versioned).
With this patch, `./build.sh host.native --cross --os openbsd --arch
x64` succeeds.
Upstream PR for eng/common change:
dotnet/arcade#16564
@github-actions

github-actionsBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Workflow state for the Holistic Review Orchestrator.

{
"version": 5,
"last_dispatched_commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"last_dispatched_base_ref": "main",
"last_dispatched_base_sha": "b0bc48eea7e28be9670d4ac499a5778d0ac99909",
"last_reviewed_commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"last_reviewed_base_ref": "main",
"last_reviewed_base_sha": "b0bc48eea7e28be9670d4ac499a5778d0ac99909",
"last_recorded_worker_run_id": "29673725116",
"review_attempt_commit": "",
"review_attempt_base_ref": "",
"review_attempt_count": 0,
"max_review_attempts": 5,
"review_history_format": "holistic-review-disclosure-v1",
"review_history": [
{
"commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"review_id": 4730113525
}
]
}

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Holistic Review

Motivation: The PR trims src/libraries/Microsoft.NETCore.Platforms/src/runtime.json from 798 RIDs (~4600 lines) to 266 RIDs (~1500 lines). The goal is to stop the unbounded growth of the non-portable RID graph by removing every intermediate versioned/distro-specific RID while preserving base/portable RIDs, all floating (unversioned) OS RIDs, and the single most-recent versioned RID for each OS family plus its arch variants. It is a softer successor to #123161 (which removed all versioned/distro RIDs) intended to leave a migration path for packages that reference the newest versioned RIDs.

Approach: This is a pure data-file change to the transport package that is redistributed into the dotnet/sdk RID graph; no code, tooling (UpdateRuntimeIdentifierGraph.cs), or PortableRuntimeIdentifierGraph.json was touched. I verified the resulting graph independently of the description:

  • JSON is well-formed (jq parses; runtimes has 266 entries).
  • No dangling imports: every RID referenced in a #import array (198 distinct) is still defined as a top-level key. So removing ~721 keys did not orphan any surviving RID.
  • Kept versioned RIDs were correctly re-pointed: previously each last-version RID chained through the removed intermediate (e.g. osx.13 -> osx.12, alpine.3.18 -> alpine.3.17, osx.13-x64 -> osx.12-x64). In the new graph they import their floating base directly (osx.13 -> osx, osx.13-x64 -> osx.13,osx-x64), which is the correct rewrite to keep the graph connected after the intermediates are gone.
  • No repo-internal fallout: I grepped eng/ and src/ for representative removed RIDs (e.g. osx.10.12, ubuntu.18.04, alpine.3.17, rhel.7) and found no build/test/pipeline references that depend on them.

The change is internally consistent and the mechanical execution looks correct.

Summary: LGTM on correctness of the graph edit itself. The substantive consideration is not a code defect but a compatibility/policy judgment that belongs to the maintainers and the SDK team: removing intermediate versioned RIDs is an intentional behavior change to NuGet RID-based asset selection. Any existing package that ships assets exclusively under a now-removed RID (e.g. runtimes/ubuntu.16.04-x64/...) will no longer have that RID in the graph, so a project resolving for such a RID would fall back to the floating/base asset (or fail to see the RID at all) rather than the version-specific one. The PR description acknowledges this as the intended tradeoff with a documented migration story, and readme.md already states the graph should no longer gain new version-specific RIDs. Because this is the whole point of the PR and there is no single changed line to attach it to, I raise it here rather than as an inline finding. I'd recommend confirming (a) the SDK-side consumption and any published compat/breaking-change guidance are lined up, and (b) that the "last versioned RID per family" selection is genuinely the newest for each family (spot checks such as alpine.3.18, osx.13, ubuntu.23.10, debian.12, fedora.39 looked right). No blocking correctness issues found in the diff.

Note

This review was generated by this repository's Holistic Review agentic workflow to complement the built-in Copilot review.

Generated by Holistic Review · 130.8 AIC · ⌖ 10.7 AIC · ⊞ 10K

@elinor-fung

Copy link
Copy Markdown
Member

I assume we'd want to breaking change doc this?

The change seems generally reasonable to me as a step towards a future larger breaking change of removing the non-portable RID graph compat mode entirely.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@richlander@ericstj@tmds@am11@elinor-fung
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Simplify RID graph: keep floating and last versioned RIDs - #125076

Open
richlander wants to merge 1 commit into
mainfrom
simplify-rid-graph-soft
Open

Simplify RID graph: keep floating and last versioned RIDs#125076
richlander wants to merge 1 commit into
mainfrom
simplify-rid-graph-soft

Conversation

@richlander

Copy link
Copy Markdown
Member

Replaces: #123161

Softer approach to RID graph simplification. Instead of removing all versioned and distro-specific RIDs, this keeps:

  • All portable/base RIDs (any, unix, linux, win, etc.)
  • All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
  • The last versioned RID for each OS family and its arch variants

This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines (266 RIDs) while preserving a migration path for packages that reference the most recent versioned RIDs.

We can do more cleanup later. This approach is a much safer starting point with easier migration guidance. It's also more defensible.

Removed RIDs: all intermediate versioned RIDs (e.g. alpine.3.7 through alpine.3.17, ubuntu.14.04 through ubuntu.23.04, osx.10.10 through osx.12, etc.)

Kept last versions include: alpine.3.18, android.32, centos.9, debian.12, fedora.39, freebsd.13, ios.15, osx.13, rhel.9, rocky.9, tizen.7.0.0, tvos.15, ubuntu.23.10, and others.

Softer approach to RID graph simplification. Instead of removing all
versioned and distro-specific RIDs, this keeps:
- All portable/base RIDs (any, unix, linux, win, etc.)
- All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
- The last versioned RID for each OS family and its arch variants
This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines
(266 RIDs) while preserving a migration path for packages that reference
the most recent versioned RIDs.
Removed RIDs: all intermediate versioned RIDs (e.g. alpine.3.7 through
alpine.3.17, ubuntu.14.04 through ubuntu.23.04, osx.10.10 through
osx.12, etc.)
Kept last versions include: alpine.3.18, android.32, centos.9,
debian.12, fedora.39, freebsd.13, ios.15, osx.13, rhel.9, rocky.9,
tizen.7.0.0, tvos.15, ubuntu.23.10, and others.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings March 2, 2026 20:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review any files in this pull request.

@richlander

richlander commented Mar 2, 2026

Copy link
Copy Markdown
MemberAuthor

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke, @jeffschwMSFT, @elinor-fung
See info in area-owners.md if you want to be subscribed.

@ericstj

Copy link
Copy Markdown
Member

What have you done to test this? Did you consider making this change in the VMR so that we can see if source build and phase2 product build are happy with the changes?

@richlander

Copy link
Copy Markdown
MemberAuthor

Great questions. I haven't done anything to test it. My belief/understanding is that the fallout is compat. I can make this change in VMR. That didn't occur to me. My thinking -- perhaps naive -- is that any break there is a bug that needs to be fixed downstream. I'll apply this change to VMR.

richlander pushed a commit to dotnet/dotnet that referenced this pull request Mar 2, 2026
Softer approach to RID graph simplification. Instead of removing all
versioned and distro-specific RIDs, this keeps:
- All portable/base RIDs (any, unix, linux, win, etc.)
- All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
- The last versioned RID for each OS family and its arch variants
This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines
(266 RIDs) while preserving a migration path for packages that reference
the most recent versioned RIDs.
Backport of dotnet/runtime#125076
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ericstj

ericstj commented Mar 2, 2026

Copy link
Copy Markdown
Member

Great questions. I haven't done anything to test it. My belief/understanding is that the fallout is compat. I can make this change in VMR. That didn't occur to me. My thinking -- perhaps naive -- is that any break there is a bug that needs to be fixed downstream. I'll apply this change to VMR.

It should be, but we might want to get that signal now. I think the VMR can give at least a sampling of those it won't run the SDK tests which I think might be equally valuable, but we don't have a good way to do that in PR.

I don't have any objections to the PR itself, it's more "what's the fallout". I trust its well formed, but I am not reviewing for that. We used to have a generator for this that made it a bit easier to review the changes to the generator inputs.

@richlander

Copy link
Copy Markdown
MemberAuthor

Understood. We're on the same page.

@tmds

tmds commented Mar 3, 2026

Copy link
Copy Markdown
Member

this keeps:
All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
The last versioned RID for each OS family and its arch variants

I'd consider removing these too.

The "modern" rid handling for a non-portable SDK depends on:

 "fedora.42-x64": [
"linux-x64",
"linux",
"unix-x64",
"unix",
"any",
"base"
]

@ericstj

Copy link
Copy Markdown
Member

I shared some data offline to show what packages are using the RIDs being discussed here. That provides a view of the producer side - we can't know what people use when building apps (consumer side) but a review of that data might help understand the compat impact of removing RIDs that might be used during restore.

@richlander

Copy link
Copy Markdown
MemberAuthor

This proposal is on top of this break that we made 3 years ago: dotnet/docs#36466

That break has a workaround. You can see it in use: https://grep.app/search?q=%3CUseRidGraph%3Etrue%3C%2FUseRidGraph%3E

The use of UseRidGraph suggests that the original change would have been too breaking.

@am11

am11 commented Mar 3, 2026

Copy link
Copy Markdown
Member

My understanding is; with Microsoft SDK:

  1. PortableRuntimeIdentifierGraph.json is used by default
  2. runtime.json is used as a fallback for < .NET8 SDKs or when user specifies UseRidGraph=true (so it is set-in-stone / considered immutable)
  3. There is an override RuntimeIdentifierGraphPath where user can provide their custom graph.

Distro maintainers use 3rd option (graph gets generated during the source-bulid).

If this is correct, then we don't need to change runtime.json for older/outdated SDK deployments to keep working. Otherwise, I misunderstood. 🙂

cc @elinor-fung

@richlander

Copy link
Copy Markdown
MemberAuthor

The intent is to remove cruft from the product. The RID file is basically a wikipedia of old distros. I'd like to eventually delete the file. I grasp, as you are suggesting, that its also enable compatibility for old assets on nuget.org, otherise they are basically unusable. Consumers can either use old SDKs, insert their own RID graph, or user a newer version. Some of the libraries may be abandoned. It's OK to have to take extra steps to use abandoned software.

@richlander

Copy link
Copy Markdown
MemberAuthor

Here is the data we collected, sorted by package count with a cutoff at 10 packages. The primary data I see is that we should consider bringing some Ubuntu RIDs back. On that note, I see that Ubuntu 23.10 is the latest/retained Ubuntu RID. That's not super useful. If we follow the data, we could replace 23.10 with 18.04 and that would solve most of the problem.

RIDPackagesTotalDownloads
win-x642619207237330
win204919292274122
win-x861829177109693
linux-x641708129237714
unix11237254257098
osx-x64109849230613
win-arm6482310471924
linux-arm6463282847442
win10-x6459011712306
osx569592532030
win10-x8655811400902
linux-arm48277527334
win10-arm4608308597
osx-arm6445011622264
linux-musl-x643526193593
win-arm34962507883
linux-x862769332247
alpine-x642391957557
win7-x641969761981
browser18852817835
linux179422141284
linux-armel17062772107
linux-musl-arm641561505670
win7-x861508884912
win10-arm641481613561
linux-musl-arm1481319978
ubuntu.18.04-x641431731579
rhel-x64140879046
fedora-x641371093005
debian.9-x641301636565
alpine.3.9-x64102819572
debian-arm6497814104
ubuntu.16.04-arm6497814104
linux-mips6484277434
android-arm64788947188
maccatalyst-x64716129705
maccatalyst-arm64705851291
android-x64698941814
linux-s390x67255760
android-arm668878358
android-x86618881581
browser-wasm60105415377
ios511631429
freebsd481499857
any46527589
native1.12-tchmi446013105
win8-arm44656478
linux-ppc64le37237069
win81-x6434162713
win81-x8634161137
ubuntu.16.04-x64321885962
ios-arm64318446030
tvos311037541
win8-x6430184919
win8-x8630179797
iossimulator-x64278675284
illumos27972741
solaris27972741
alpine-arm642770014
alpine-arm2663432
iossimulator-arm64258406514
aot235585530322
debian-x6423128315
x6421307951
ios-arm2014353065
tvos-arm6420512633
tvossimulator-x6420472887
centos-x6419175450
ubuntu.20.04-x6418262325
ios-armv7s1752958
ubuntu.14.04-x64166031
osx-641551277
win7-arm1512699
models156303
win714540652238
osx.10.10-x6414164277
arm641411382
osx-universal148509
native1317253297
x8613297447
win81-arm13223363
linux-641354125
debian.8-x6412187855
rhel.7-x6411791721
opensuse-x6411248293
fedora.23-x64105948
opensuse.13.2-x64105948

@tmds

tmds commented Mar 4, 2026

Copy link
Copy Markdown
Member

runtime.json is used as a fallback for < .NET8 SDKs or when user specifies UseRidGraph=true

Ah, yes.

I think users should use APIs like NativeLibrary.SetDllImportResolver instead of UseRidGraph.

It doesn't seem a mechanism that is relied on for splitting nuget packages either. Searching for latest Ubuntu LTS shows only 7 packages (by 5 users): https://www.nuget.org/packages?q=ubuntu.24.04-x64.

@richlander

Copy link
Copy Markdown
MemberAuthor

That's a good point. As I hinted at, my hope would be to make this change for 11 and the delete most of the infra for 12.

elinor-fung pushed a commit that referenced this pull request Mar 26, 2026
This fallback code (`get_current_os_rid_platform`) will probably go away
in the future once #125076 has
landed, but as it stands, we need this for parity. C++ libraries
version-less symlinks are needed for cmake/clang to avoid falling back
to non-fPIC libc++.a (because libc++.so.x.y is versioned).
With this patch, `./build.sh host.native --cross --os openbsd --arch
x64` succeeds.
Upstream PR for eng/common change:
dotnet/arcade#16564
@github-actions

github-actionsBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Workflow state for the Holistic Review Orchestrator.

{
"version": 5,
"last_dispatched_commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"last_dispatched_base_ref": "main",
"last_dispatched_base_sha": "b0bc48eea7e28be9670d4ac499a5778d0ac99909",
"last_reviewed_commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"last_reviewed_base_ref": "main",
"last_reviewed_base_sha": "b0bc48eea7e28be9670d4ac499a5778d0ac99909",
"last_recorded_worker_run_id": "29673725116",
"review_attempt_commit": "",
"review_attempt_base_ref": "",
"review_attempt_count": 0,
"max_review_attempts": 5,
"review_history_format": "holistic-review-disclosure-v1",
"review_history": [
{
"commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"review_id": 4730113525
}
]
}

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Holistic Review

Motivation: The PR trims src/libraries/Microsoft.NETCore.Platforms/src/runtime.json from 798 RIDs (~4600 lines) to 266 RIDs (~1500 lines). The goal is to stop the unbounded growth of the non-portable RID graph by removing every intermediate versioned/distro-specific RID while preserving base/portable RIDs, all floating (unversioned) OS RIDs, and the single most-recent versioned RID for each OS family plus its arch variants. It is a softer successor to #123161 (which removed all versioned/distro RIDs) intended to leave a migration path for packages that reference the newest versioned RIDs.

Approach: This is a pure data-file change to the transport package that is redistributed into the dotnet/sdk RID graph; no code, tooling (UpdateRuntimeIdentifierGraph.cs), or PortableRuntimeIdentifierGraph.json was touched. I verified the resulting graph independently of the description:

  • JSON is well-formed (jq parses; runtimes has 266 entries).
  • No dangling imports: every RID referenced in a #import array (198 distinct) is still defined as a top-level key. So removing ~721 keys did not orphan any surviving RID.
  • Kept versioned RIDs were correctly re-pointed: previously each last-version RID chained through the removed intermediate (e.g. osx.13 -> osx.12, alpine.3.18 -> alpine.3.17, osx.13-x64 -> osx.12-x64). In the new graph they import their floating base directly (osx.13 -> osx, osx.13-x64 -> osx.13,osx-x64), which is the correct rewrite to keep the graph connected after the intermediates are gone.
  • No repo-internal fallout: I grepped eng/ and src/ for representative removed RIDs (e.g. osx.10.12, ubuntu.18.04, alpine.3.17, rhel.7) and found no build/test/pipeline references that depend on them.

The change is internally consistent and the mechanical execution looks correct.

Summary: LGTM on correctness of the graph edit itself. The substantive consideration is not a code defect but a compatibility/policy judgment that belongs to the maintainers and the SDK team: removing intermediate versioned RIDs is an intentional behavior change to NuGet RID-based asset selection. Any existing package that ships assets exclusively under a now-removed RID (e.g. runtimes/ubuntu.16.04-x64/...) will no longer have that RID in the graph, so a project resolving for such a RID would fall back to the floating/base asset (or fail to see the RID at all) rather than the version-specific one. The PR description acknowledges this as the intended tradeoff with a documented migration story, and readme.md already states the graph should no longer gain new version-specific RIDs. Because this is the whole point of the PR and there is no single changed line to attach it to, I raise it here rather than as an inline finding. I'd recommend confirming (a) the SDK-side consumption and any published compat/breaking-change guidance are lined up, and (b) that the "last versioned RID per family" selection is genuinely the newest for each family (spot checks such as alpine.3.18, osx.13, ubuntu.23.10, debian.12, fedora.39 looked right). No blocking correctness issues found in the diff.

Note

This review was generated by this repository's Holistic Review agentic workflow to complement the built-in Copilot review.

Generated by Holistic Review · 130.8 AIC · ⌖ 10.7 AIC · ⊞ 10K

@elinor-fung

Copy link
Copy Markdown
Member

I assume we'd want to breaking change doc this?

The change seems generally reasonable to me as a step towards a future larger breaking change of removing the non-portable RID graph compat mode entirely.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@richlander@ericstj@tmds@am11@elinor-fung
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Simplify RID graph: keep floating and last versioned RIDs - #125076

Open
richlander wants to merge 1 commit into
mainfrom
simplify-rid-graph-soft
Open

Simplify RID graph: keep floating and last versioned RIDs#125076
richlander wants to merge 1 commit into
mainfrom
simplify-rid-graph-soft

Conversation

@richlander

Copy link
Copy Markdown
Member

Replaces: #123161

Softer approach to RID graph simplification. Instead of removing all versioned and distro-specific RIDs, this keeps:

  • All portable/base RIDs (any, unix, linux, win, etc.)
  • All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
  • The last versioned RID for each OS family and its arch variants

This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines (266 RIDs) while preserving a migration path for packages that reference the most recent versioned RIDs.

We can do more cleanup later. This approach is a much safer starting point with easier migration guidance. It's also more defensible.

Removed RIDs: all intermediate versioned RIDs (e.g. alpine.3.7 through alpine.3.17, ubuntu.14.04 through ubuntu.23.04, osx.10.10 through osx.12, etc.)

Kept last versions include: alpine.3.18, android.32, centos.9, debian.12, fedora.39, freebsd.13, ios.15, osx.13, rhel.9, rocky.9, tizen.7.0.0, tvos.15, ubuntu.23.10, and others.

Softer approach to RID graph simplification. Instead of removing all
versioned and distro-specific RIDs, this keeps:
- All portable/base RIDs (any, unix, linux, win, etc.)
- All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
- The last versioned RID for each OS family and its arch variants
This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines
(266 RIDs) while preserving a migration path for packages that reference
the most recent versioned RIDs.
Removed RIDs: all intermediate versioned RIDs (e.g. alpine.3.7 through
alpine.3.17, ubuntu.14.04 through ubuntu.23.04, osx.10.10 through
osx.12, etc.)
Kept last versions include: alpine.3.18, android.32, centos.9,
debian.12, fedora.39, freebsd.13, ios.15, osx.13, rhel.9, rocky.9,
tizen.7.0.0, tvos.15, ubuntu.23.10, and others.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings March 2, 2026 20:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review any files in this pull request.

@richlander

richlander commented Mar 2, 2026

Copy link
Copy Markdown
MemberAuthor

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke, @jeffschwMSFT, @elinor-fung
See info in area-owners.md if you want to be subscribed.

@ericstj

Copy link
Copy Markdown
Member

What have you done to test this? Did you consider making this change in the VMR so that we can see if source build and phase2 product build are happy with the changes?

@richlander

Copy link
Copy Markdown
MemberAuthor

Great questions. I haven't done anything to test it. My belief/understanding is that the fallout is compat. I can make this change in VMR. That didn't occur to me. My thinking -- perhaps naive -- is that any break there is a bug that needs to be fixed downstream. I'll apply this change to VMR.

richlander pushed a commit to dotnet/dotnet that referenced this pull request Mar 2, 2026
Softer approach to RID graph simplification. Instead of removing all
versioned and distro-specific RIDs, this keeps:
- All portable/base RIDs (any, unix, linux, win, etc.)
- All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
- The last versioned RID for each OS family and its arch variants
This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines
(266 RIDs) while preserving a migration path for packages that reference
the most recent versioned RIDs.
Backport of dotnet/runtime#125076
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ericstj

ericstj commented Mar 2, 2026

Copy link
Copy Markdown
Member

Great questions. I haven't done anything to test it. My belief/understanding is that the fallout is compat. I can make this change in VMR. That didn't occur to me. My thinking -- perhaps naive -- is that any break there is a bug that needs to be fixed downstream. I'll apply this change to VMR.

It should be, but we might want to get that signal now. I think the VMR can give at least a sampling of those it won't run the SDK tests which I think might be equally valuable, but we don't have a good way to do that in PR.

I don't have any objections to the PR itself, it's more "what's the fallout". I trust its well formed, but I am not reviewing for that. We used to have a generator for this that made it a bit easier to review the changes to the generator inputs.

@richlander

Copy link
Copy Markdown
MemberAuthor

Understood. We're on the same page.

@tmds

tmds commented Mar 3, 2026

Copy link
Copy Markdown
Member

this keeps:
All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
The last versioned RID for each OS family and its arch variants

I'd consider removing these too.

The "modern" rid handling for a non-portable SDK depends on:

 "fedora.42-x64": [
"linux-x64",
"linux",
"unix-x64",
"unix",
"any",
"base"
]

@ericstj

Copy link
Copy Markdown
Member

I shared some data offline to show what packages are using the RIDs being discussed here. That provides a view of the producer side - we can't know what people use when building apps (consumer side) but a review of that data might help understand the compat impact of removing RIDs that might be used during restore.

@richlander

Copy link
Copy Markdown
MemberAuthor

This proposal is on top of this break that we made 3 years ago: dotnet/docs#36466

That break has a workaround. You can see it in use: https://grep.app/search?q=%3CUseRidGraph%3Etrue%3C%2FUseRidGraph%3E

The use of UseRidGraph suggests that the original change would have been too breaking.

@am11

am11 commented Mar 3, 2026

Copy link
Copy Markdown
Member

My understanding is; with Microsoft SDK:

  1. PortableRuntimeIdentifierGraph.json is used by default
  2. runtime.json is used as a fallback for < .NET8 SDKs or when user specifies UseRidGraph=true (so it is set-in-stone / considered immutable)
  3. There is an override RuntimeIdentifierGraphPath where user can provide their custom graph.

Distro maintainers use 3rd option (graph gets generated during the source-bulid).

If this is correct, then we don't need to change runtime.json for older/outdated SDK deployments to keep working. Otherwise, I misunderstood. 🙂

cc @elinor-fung

@richlander

Copy link
Copy Markdown
MemberAuthor

The intent is to remove cruft from the product. The RID file is basically a wikipedia of old distros. I'd like to eventually delete the file. I grasp, as you are suggesting, that its also enable compatibility for old assets on nuget.org, otherise they are basically unusable. Consumers can either use old SDKs, insert their own RID graph, or user a newer version. Some of the libraries may be abandoned. It's OK to have to take extra steps to use abandoned software.

@richlander

Copy link
Copy Markdown
MemberAuthor

Here is the data we collected, sorted by package count with a cutoff at 10 packages. The primary data I see is that we should consider bringing some Ubuntu RIDs back. On that note, I see that Ubuntu 23.10 is the latest/retained Ubuntu RID. That's not super useful. If we follow the data, we could replace 23.10 with 18.04 and that would solve most of the problem.

RIDPackagesTotalDownloads
win-x642619207237330
win204919292274122
win-x861829177109693
linux-x641708129237714
unix11237254257098
osx-x64109849230613
win-arm6482310471924
linux-arm6463282847442
win10-x6459011712306
osx569592532030
win10-x8655811400902
linux-arm48277527334
win10-arm4608308597
osx-arm6445011622264
linux-musl-x643526193593
win-arm34962507883
linux-x862769332247
alpine-x642391957557
win7-x641969761981
browser18852817835
linux179422141284
linux-armel17062772107
linux-musl-arm641561505670
win7-x861508884912
win10-arm641481613561
linux-musl-arm1481319978
ubuntu.18.04-x641431731579
rhel-x64140879046
fedora-x641371093005
debian.9-x641301636565
alpine.3.9-x64102819572
debian-arm6497814104
ubuntu.16.04-arm6497814104
linux-mips6484277434
android-arm64788947188
maccatalyst-x64716129705
maccatalyst-arm64705851291
android-x64698941814
linux-s390x67255760
android-arm668878358
android-x86618881581
browser-wasm60105415377
ios511631429
freebsd481499857
any46527589
native1.12-tchmi446013105
win8-arm44656478
linux-ppc64le37237069
win81-x6434162713
win81-x8634161137
ubuntu.16.04-x64321885962
ios-arm64318446030
tvos311037541
win8-x6430184919
win8-x8630179797
iossimulator-x64278675284
illumos27972741
solaris27972741
alpine-arm642770014
alpine-arm2663432
iossimulator-arm64258406514
aot235585530322
debian-x6423128315
x6421307951
ios-arm2014353065
tvos-arm6420512633
tvossimulator-x6420472887
centos-x6419175450
ubuntu.20.04-x6418262325
ios-armv7s1752958
ubuntu.14.04-x64166031
osx-641551277
win7-arm1512699
models156303
win714540652238
osx.10.10-x6414164277
arm641411382
osx-universal148509
native1317253297
x8613297447
win81-arm13223363
linux-641354125
debian.8-x6412187855
rhel.7-x6411791721
opensuse-x6411248293
fedora.23-x64105948
opensuse.13.2-x64105948

@tmds

tmds commented Mar 4, 2026

Copy link
Copy Markdown
Member

runtime.json is used as a fallback for < .NET8 SDKs or when user specifies UseRidGraph=true

Ah, yes.

I think users should use APIs like NativeLibrary.SetDllImportResolver instead of UseRidGraph.

It doesn't seem a mechanism that is relied on for splitting nuget packages either. Searching for latest Ubuntu LTS shows only 7 packages (by 5 users): https://www.nuget.org/packages?q=ubuntu.24.04-x64.

@richlander

Copy link
Copy Markdown
MemberAuthor

That's a good point. As I hinted at, my hope would be to make this change for 11 and the delete most of the infra for 12.

elinor-fung pushed a commit that referenced this pull request Mar 26, 2026
This fallback code (`get_current_os_rid_platform`) will probably go away
in the future once #125076 has
landed, but as it stands, we need this for parity. C++ libraries
version-less symlinks are needed for cmake/clang to avoid falling back
to non-fPIC libc++.a (because libc++.so.x.y is versioned).
With this patch, `./build.sh host.native --cross --os openbsd --arch
x64` succeeds.
Upstream PR for eng/common change:
dotnet/arcade#16564
@github-actions

github-actionsBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Workflow state for the Holistic Review Orchestrator.

{
"version": 5,
"last_dispatched_commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"last_dispatched_base_ref": "main",
"last_dispatched_base_sha": "b0bc48eea7e28be9670d4ac499a5778d0ac99909",
"last_reviewed_commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"last_reviewed_base_ref": "main",
"last_reviewed_base_sha": "b0bc48eea7e28be9670d4ac499a5778d0ac99909",
"last_recorded_worker_run_id": "29673725116",
"review_attempt_commit": "",
"review_attempt_base_ref": "",
"review_attempt_count": 0,
"max_review_attempts": 5,
"review_history_format": "holistic-review-disclosure-v1",
"review_history": [
{
"commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"review_id": 4730113525
}
]
}

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Holistic Review

Motivation: The PR trims src/libraries/Microsoft.NETCore.Platforms/src/runtime.json from 798 RIDs (~4600 lines) to 266 RIDs (~1500 lines). The goal is to stop the unbounded growth of the non-portable RID graph by removing every intermediate versioned/distro-specific RID while preserving base/portable RIDs, all floating (unversioned) OS RIDs, and the single most-recent versioned RID for each OS family plus its arch variants. It is a softer successor to #123161 (which removed all versioned/distro RIDs) intended to leave a migration path for packages that reference the newest versioned RIDs.

Approach: This is a pure data-file change to the transport package that is redistributed into the dotnet/sdk RID graph; no code, tooling (UpdateRuntimeIdentifierGraph.cs), or PortableRuntimeIdentifierGraph.json was touched. I verified the resulting graph independently of the description:

  • JSON is well-formed (jq parses; runtimes has 266 entries).
  • No dangling imports: every RID referenced in a #import array (198 distinct) is still defined as a top-level key. So removing ~721 keys did not orphan any surviving RID.
  • Kept versioned RIDs were correctly re-pointed: previously each last-version RID chained through the removed intermediate (e.g. osx.13 -> osx.12, alpine.3.18 -> alpine.3.17, osx.13-x64 -> osx.12-x64). In the new graph they import their floating base directly (osx.13 -> osx, osx.13-x64 -> osx.13,osx-x64), which is the correct rewrite to keep the graph connected after the intermediates are gone.
  • No repo-internal fallout: I grepped eng/ and src/ for representative removed RIDs (e.g. osx.10.12, ubuntu.18.04, alpine.3.17, rhel.7) and found no build/test/pipeline references that depend on them.

The change is internally consistent and the mechanical execution looks correct.

Summary: LGTM on correctness of the graph edit itself. The substantive consideration is not a code defect but a compatibility/policy judgment that belongs to the maintainers and the SDK team: removing intermediate versioned RIDs is an intentional behavior change to NuGet RID-based asset selection. Any existing package that ships assets exclusively under a now-removed RID (e.g. runtimes/ubuntu.16.04-x64/...) will no longer have that RID in the graph, so a project resolving for such a RID would fall back to the floating/base asset (or fail to see the RID at all) rather than the version-specific one. The PR description acknowledges this as the intended tradeoff with a documented migration story, and readme.md already states the graph should no longer gain new version-specific RIDs. Because this is the whole point of the PR and there is no single changed line to attach it to, I raise it here rather than as an inline finding. I'd recommend confirming (a) the SDK-side consumption and any published compat/breaking-change guidance are lined up, and (b) that the "last versioned RID per family" selection is genuinely the newest for each family (spot checks such as alpine.3.18, osx.13, ubuntu.23.10, debian.12, fedora.39 looked right). No blocking correctness issues found in the diff.

Note

This review was generated by this repository's Holistic Review agentic workflow to complement the built-in Copilot review.

Generated by Holistic Review · 130.8 AIC · ⌖ 10.7 AIC · ⊞ 10K

@elinor-fung

Copy link
Copy Markdown
Member

I assume we'd want to breaking change doc this?

The change seems generally reasonable to me as a step towards a future larger breaking change of removing the non-portable RID graph compat mode entirely.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@richlander@ericstj@tmds@am11@elinor-fung
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Simplify RID graph: keep floating and last versioned RIDs - #125076

Open
richlander wants to merge 1 commit into
mainfrom
simplify-rid-graph-soft
Open

Simplify RID graph: keep floating and last versioned RIDs#125076
richlander wants to merge 1 commit into
mainfrom
simplify-rid-graph-soft

Conversation

@richlander

Copy link
Copy Markdown
Member

Replaces: #123161

Softer approach to RID graph simplification. Instead of removing all versioned and distro-specific RIDs, this keeps:

  • All portable/base RIDs (any, unix, linux, win, etc.)
  • All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
  • The last versioned RID for each OS family and its arch variants

This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines (266 RIDs) while preserving a migration path for packages that reference the most recent versioned RIDs.

We can do more cleanup later. This approach is a much safer starting point with easier migration guidance. It's also more defensible.

Removed RIDs: all intermediate versioned RIDs (e.g. alpine.3.7 through alpine.3.17, ubuntu.14.04 through ubuntu.23.04, osx.10.10 through osx.12, etc.)

Kept last versions include: alpine.3.18, android.32, centos.9, debian.12, fedora.39, freebsd.13, ios.15, osx.13, rhel.9, rocky.9, tizen.7.0.0, tvos.15, ubuntu.23.10, and others.

Softer approach to RID graph simplification. Instead of removing all
versioned and distro-specific RIDs, this keeps:
- All portable/base RIDs (any, unix, linux, win, etc.)
- All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
- The last versioned RID for each OS family and its arch variants
This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines
(266 RIDs) while preserving a migration path for packages that reference
the most recent versioned RIDs.
Removed RIDs: all intermediate versioned RIDs (e.g. alpine.3.7 through
alpine.3.17, ubuntu.14.04 through ubuntu.23.04, osx.10.10 through
osx.12, etc.)
Kept last versions include: alpine.3.18, android.32, centos.9,
debian.12, fedora.39, freebsd.13, ios.15, osx.13, rhel.9, rocky.9,
tizen.7.0.0, tvos.15, ubuntu.23.10, and others.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings March 2, 2026 20:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review any files in this pull request.

@richlander

richlander commented Mar 2, 2026

Copy link
Copy Markdown
MemberAuthor

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke, @jeffschwMSFT, @elinor-fung
See info in area-owners.md if you want to be subscribed.

@ericstj

Copy link
Copy Markdown
Member

What have you done to test this? Did you consider making this change in the VMR so that we can see if source build and phase2 product build are happy with the changes?

@richlander

Copy link
Copy Markdown
MemberAuthor

Great questions. I haven't done anything to test it. My belief/understanding is that the fallout is compat. I can make this change in VMR. That didn't occur to me. My thinking -- perhaps naive -- is that any break there is a bug that needs to be fixed downstream. I'll apply this change to VMR.

richlander pushed a commit to dotnet/dotnet that referenced this pull request Mar 2, 2026
Softer approach to RID graph simplification. Instead of removing all
versioned and distro-specific RIDs, this keeps:
- All portable/base RIDs (any, unix, linux, win, etc.)
- All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
- The last versioned RID for each OS family and its arch variants
This reduces runtime.json from ~4600 lines (798 RIDs) to ~1500 lines
(266 RIDs) while preserving a migration path for packages that reference
the most recent versioned RIDs.
Backport of dotnet/runtime#125076
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ericstj

ericstj commented Mar 2, 2026

Copy link
Copy Markdown
Member

Great questions. I haven't done anything to test it. My belief/understanding is that the fallout is compat. I can make this change in VMR. That didn't occur to me. My thinking -- perhaps naive -- is that any break there is a bug that needs to be fixed downstream. I'll apply this change to VMR.

It should be, but we might want to get that signal now. I think the VMR can give at least a sampling of those it won't run the SDK tests which I think might be equally valuable, but we don't have a good way to do that in PR.

I don't have any objections to the PR itself, it's more "what's the fallout". I trust its well formed, but I am not reviewing for that. We used to have a generator for this that made it a bit easier to review the changes to the generator inputs.

@richlander

Copy link
Copy Markdown
MemberAuthor

Understood. We're on the same page.

@tmds

tmds commented Mar 3, 2026

Copy link
Copy Markdown
Member

this keeps:
All floating (unversioned) OS RIDs (alpine, ubuntu, osx, etc.)
The last versioned RID for each OS family and its arch variants

I'd consider removing these too.

The "modern" rid handling for a non-portable SDK depends on:

 "fedora.42-x64": [
"linux-x64",
"linux",
"unix-x64",
"unix",
"any",
"base"
]

@ericstj

Copy link
Copy Markdown
Member

I shared some data offline to show what packages are using the RIDs being discussed here. That provides a view of the producer side - we can't know what people use when building apps (consumer side) but a review of that data might help understand the compat impact of removing RIDs that might be used during restore.

@richlander

Copy link
Copy Markdown
MemberAuthor

This proposal is on top of this break that we made 3 years ago: dotnet/docs#36466

That break has a workaround. You can see it in use: https://grep.app/search?q=%3CUseRidGraph%3Etrue%3C%2FUseRidGraph%3E

The use of UseRidGraph suggests that the original change would have been too breaking.

@am11

am11 commented Mar 3, 2026

Copy link
Copy Markdown
Member

My understanding is; with Microsoft SDK:

  1. PortableRuntimeIdentifierGraph.json is used by default
  2. runtime.json is used as a fallback for < .NET8 SDKs or when user specifies UseRidGraph=true (so it is set-in-stone / considered immutable)
  3. There is an override RuntimeIdentifierGraphPath where user can provide their custom graph.

Distro maintainers use 3rd option (graph gets generated during the source-bulid).

If this is correct, then we don't need to change runtime.json for older/outdated SDK deployments to keep working. Otherwise, I misunderstood. 🙂

cc @elinor-fung

@richlander

Copy link
Copy Markdown
MemberAuthor

The intent is to remove cruft from the product. The RID file is basically a wikipedia of old distros. I'd like to eventually delete the file. I grasp, as you are suggesting, that its also enable compatibility for old assets on nuget.org, otherise they are basically unusable. Consumers can either use old SDKs, insert their own RID graph, or user a newer version. Some of the libraries may be abandoned. It's OK to have to take extra steps to use abandoned software.

@richlander

Copy link
Copy Markdown
MemberAuthor

Here is the data we collected, sorted by package count with a cutoff at 10 packages. The primary data I see is that we should consider bringing some Ubuntu RIDs back. On that note, I see that Ubuntu 23.10 is the latest/retained Ubuntu RID. That's not super useful. If we follow the data, we could replace 23.10 with 18.04 and that would solve most of the problem.

RIDPackagesTotalDownloads
win-x642619207237330
win204919292274122
win-x861829177109693
linux-x641708129237714
unix11237254257098
osx-x64109849230613
win-arm6482310471924
linux-arm6463282847442
win10-x6459011712306
osx569592532030
win10-x8655811400902
linux-arm48277527334
win10-arm4608308597
osx-arm6445011622264
linux-musl-x643526193593
win-arm34962507883
linux-x862769332247
alpine-x642391957557
win7-x641969761981
browser18852817835
linux179422141284
linux-armel17062772107
linux-musl-arm641561505670
win7-x861508884912
win10-arm641481613561
linux-musl-arm1481319978
ubuntu.18.04-x641431731579
rhel-x64140879046
fedora-x641371093005
debian.9-x641301636565
alpine.3.9-x64102819572
debian-arm6497814104
ubuntu.16.04-arm6497814104
linux-mips6484277434
android-arm64788947188
maccatalyst-x64716129705
maccatalyst-arm64705851291
android-x64698941814
linux-s390x67255760
android-arm668878358
android-x86618881581
browser-wasm60105415377
ios511631429
freebsd481499857
any46527589
native1.12-tchmi446013105
win8-arm44656478
linux-ppc64le37237069
win81-x6434162713
win81-x8634161137
ubuntu.16.04-x64321885962
ios-arm64318446030
tvos311037541
win8-x6430184919
win8-x8630179797
iossimulator-x64278675284
illumos27972741
solaris27972741
alpine-arm642770014
alpine-arm2663432
iossimulator-arm64258406514
aot235585530322
debian-x6423128315
x6421307951
ios-arm2014353065
tvos-arm6420512633
tvossimulator-x6420472887
centos-x6419175450
ubuntu.20.04-x6418262325
ios-armv7s1752958
ubuntu.14.04-x64166031
osx-641551277
win7-arm1512699
models156303
win714540652238
osx.10.10-x6414164277
arm641411382
osx-universal148509
native1317253297
x8613297447
win81-arm13223363
linux-641354125
debian.8-x6412187855
rhel.7-x6411791721
opensuse-x6411248293
fedora.23-x64105948
opensuse.13.2-x64105948

@tmds

tmds commented Mar 4, 2026

Copy link
Copy Markdown
Member

runtime.json is used as a fallback for < .NET8 SDKs or when user specifies UseRidGraph=true

Ah, yes.

I think users should use APIs like NativeLibrary.SetDllImportResolver instead of UseRidGraph.

It doesn't seem a mechanism that is relied on for splitting nuget packages either. Searching for latest Ubuntu LTS shows only 7 packages (by 5 users): https://www.nuget.org/packages?q=ubuntu.24.04-x64.

@richlander

Copy link
Copy Markdown
MemberAuthor

That's a good point. As I hinted at, my hope would be to make this change for 11 and the delete most of the infra for 12.

elinor-fung pushed a commit that referenced this pull request Mar 26, 2026
This fallback code (`get_current_os_rid_platform`) will probably go away
in the future once #125076 has
landed, but as it stands, we need this for parity. C++ libraries
version-less symlinks are needed for cmake/clang to avoid falling back
to non-fPIC libc++.a (because libc++.so.x.y is versioned).
With this patch, `./build.sh host.native --cross --os openbsd --arch
x64` succeeds.
Upstream PR for eng/common change:
dotnet/arcade#16564
@github-actions

github-actionsBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Workflow state for the Holistic Review Orchestrator.

{
"version": 5,
"last_dispatched_commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"last_dispatched_base_ref": "main",
"last_dispatched_base_sha": "b0bc48eea7e28be9670d4ac499a5778d0ac99909",
"last_reviewed_commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"last_reviewed_base_ref": "main",
"last_reviewed_base_sha": "b0bc48eea7e28be9670d4ac499a5778d0ac99909",
"last_recorded_worker_run_id": "29673725116",
"review_attempt_commit": "",
"review_attempt_base_ref": "",
"review_attempt_count": 0,
"max_review_attempts": 5,
"review_history_format": "holistic-review-disclosure-v1",
"review_history": [
{
"commit": "1226615d9d617de8344fecfa35c9e91c65417538",
"review_id": 4730113525
}
]
}

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Holistic Review

Motivation: The PR trims src/libraries/Microsoft.NETCore.Platforms/src/runtime.json from 798 RIDs (~4600 lines) to 266 RIDs (~1500 lines). The goal is to stop the unbounded growth of the non-portable RID graph by removing every intermediate versioned/distro-specific RID while preserving base/portable RIDs, all floating (unversioned) OS RIDs, and the single most-recent versioned RID for each OS family plus its arch variants. It is a softer successor to #123161 (which removed all versioned/distro RIDs) intended to leave a migration path for packages that reference the newest versioned RIDs.

Approach: This is a pure data-file change to the transport package that is redistributed into the dotnet/sdk RID graph; no code, tooling (UpdateRuntimeIdentifierGraph.cs), or PortableRuntimeIdentifierGraph.json was touched. I verified the resulting graph independently of the description:

  • JSON is well-formed (jq parses; runtimes has 266 entries).
  • No dangling imports: every RID referenced in a #import array (198 distinct) is still defined as a top-level key. So removing ~721 keys did not orphan any surviving RID.
  • Kept versioned RIDs were correctly re-pointed: previously each last-version RID chained through the removed intermediate (e.g. osx.13 -> osx.12, alpine.3.18 -> alpine.3.17, osx.13-x64 -> osx.12-x64). In the new graph they import their floating base directly (osx.13 -> osx, osx.13-x64 -> osx.13,osx-x64), which is the correct rewrite to keep the graph connected after the intermediates are gone.
  • No repo-internal fallout: I grepped eng/ and src/ for representative removed RIDs (e.g. osx.10.12, ubuntu.18.04, alpine.3.17, rhel.7) and found no build/test/pipeline references that depend on them.

The change is internally consistent and the mechanical execution looks correct.

Summary: LGTM on correctness of the graph edit itself. The substantive consideration is not a code defect but a compatibility/policy judgment that belongs to the maintainers and the SDK team: removing intermediate versioned RIDs is an intentional behavior change to NuGet RID-based asset selection. Any existing package that ships assets exclusively under a now-removed RID (e.g. runtimes/ubuntu.16.04-x64/...) will no longer have that RID in the graph, so a project resolving for such a RID would fall back to the floating/base asset (or fail to see the RID at all) rather than the version-specific one. The PR description acknowledges this as the intended tradeoff with a documented migration story, and readme.md already states the graph should no longer gain new version-specific RIDs. Because this is the whole point of the PR and there is no single changed line to attach it to, I raise it here rather than as an inline finding. I'd recommend confirming (a) the SDK-side consumption and any published compat/breaking-change guidance are lined up, and (b) that the "last versioned RID per family" selection is genuinely the newest for each family (spot checks such as alpine.3.18, osx.13, ubuntu.23.10, debian.12, fedora.39 looked right). No blocking correctness issues found in the diff.

Note

This review was generated by this repository's Holistic Review agentic workflow to complement the built-in Copilot review.

Generated by Holistic Review · 130.8 AIC · ⌖ 10.7 AIC · ⊞ 10K

@elinor-fung

Copy link
Copy Markdown
Member

I assume we'd want to breaking change doc this?

The change seems generally reasonable to me as a step towards a future larger breaking change of removing the non-portable RID graph compat mode entirely.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@richlander@ericstj@tmds@am11@elinor-fung