Skip to content

Install Local Runtimes with dotnetup .md#52409

Merged
nagilson merged 10 commits intodotnet:release/dnupfrom
nagilson:nagilson-install-runtimes
Feb 4, 2026
Merged

Install Local Runtimes with dotnetup .md#52409
nagilson merged 10 commits intodotnet:release/dnupfrom
nagilson:nagilson-install-runtimes

Conversation

@nagilson
Copy link
Member

@nagilson nagilson commented Jan 12, 2026

An evaluation of how local runtime installation will be executed within dotnetup.

Design of #51098

An evaluation of how local runtime installation will be executed within dotnetup.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds documentation describing how local .NET runtime installation will work within the dotnetup tool. It covers technical details and design decisions for implementing runtime installation functionality.

Changes:

  • Added new documentation file explaining runtime installation approach for dotnetup
  • Documented differences between runtime and SDK installation (global.json handling, version parsing, muxer handling)
  • Defined command structure with options for different runtime types (runtime, ASP.NET Core, Windows Desktop)

nagilson and others added 2 commits January 12, 2026 13:21
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@nagilson nagilson requested review from a team and removed request for a team January 22, 2026 20:31
@nagilson
Copy link
Member Author

My understanding is that we were in alignment post the design meeting with our team. If we could get sign-off on this to confirm, that'd be awesome. I'll start the official implementation regardless.

Comment on lines 26 to 27
- `dotnetup runtime install aspnetcore` (or `-a`)
- `dotnetup runtime install windowsdesktop` (or `-w`)
Copy link
Member

Choose a reason for hiding this comment

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

We discussed this in a meeting and I don't remember all the details of what we ended up on.
But if dotnet sdk install 10.0.101 installs version 10.0.101 of the SDK, then users should expect that dotnet runtime install 10.0.1 will install version 10.0.1 of the runtime. I also think that it won't be to common to specify which shared frameworks should be installed.
So maybe we should do something like the following:

dotnet runtime install 10.0.1 # Installs all 10.0.1 runtimes
dotnet runtime install 10.0.1 --runtime aspnetcore # Installs ASP.NET Core 10.0.1 runtime (and implicitly the core runtime too)
dotnet runtime install 10.0.1 9.0.10 # Installs all 10.0.1 and 9.0.10 runtimes
dotnet runtime install 10.0.1 9.0.10 --runtime windowsdesktop # Installs WindowsDesktop (and core) runtime for 10.0.1 and 9.0.10
dotnet runtime install windowsdesktop@10.0.1 aspnetcore@9.0.10 8.0.20 # Installs WindowsDesktop (and core) for 10.0.1, ASP.NET (and core) for 9.0.10, and all runtimes for 8.0.20

@baronfel What do you think?

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for your feedback! I like the idea of using a token to identify the runtime_type from the version and trying to align the tokens.

Current implementation:

dotnet runtime install core 10.0.1

I did not implement dotnet runtime install 10.0.1. The PR is quite large, and I'd prefer to unblock getting the SDK to use dotnetup. The effect of the command is identical to --type aspnetcore on unix. I think that we'd ideally make that command use concurrency, which is one reason to do it after.

Feedback

I suggest we use --type over --runtime to prevent redundancy.
I similarly suggest doing the multi-token part in another PR, however, we can update the doc to reflect that specification.

I also have the opinion that dotnet runtime install should only install the core runtime, because I think that is the more common scenario, and our data suggests this:

 There are ~1.73× as many core runtime users as ASP.NET Core users.
 There are ~6.97× as many core runtime users as WinDesktop users.

However, I know that in our meeting I was the minority opinion on this belief.

Copy link
Member

Choose a reason for hiding this comment

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

I strongly prefer the [name@version ...] form, but I'd also want the ability to put a set of runtimes + versions into global.json and have the simple dotnetup runtime install adhere to that.

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't believe there's a way to specify this in the global.json today - is that correct? That is what I've remarked on in the document.

Copy link
Member

Choose a reason for hiding this comment

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

Correct - we need to spec this out and codify it as part of building out dotnetup.

so we are all talking about the same doc!

### Uninstall Strategy

When uninstalling a runtime component, we must be careful not to delete shared files that other components depend on.
Copy link
Member Author

Choose a reason for hiding this comment

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

From @dsplaisted #52649 (comment)

I think can avoid having most of these rules, or different handling between different shared runtimes. Rather, when we install a runtime or SDK, we need to record "everything" that is installed as part of that component. For the SDK, this would include something like this:

Host: host/fxr/10.0.2
Packs:
packs/Microsoft.NETCore.App.Ref/10.0.2
etc.
SDK: sdk/10.0.102
Workload manifests
sdk-manifests/10.0.100/microsoft.net.sdk.android/36.1.2
etc.
Shared runtimes
shared/Microsoft.NETCore.App/10.0.2
etc.
Templates: templates/10.0.2
Basically for each top-level folder, we need to know how many directory levels deep to go to identify the version of each component that is installed.

Then, when uninstalling an SDK or runtime, we can remove any of the components that are no longer referenced by other top-level components in the manifest.

Then we also need logic for items in the root. We already have logic for the muxer, but there's also the dnx script and the License and third party notice files. Probably we can handle the other files the same as the muxer.

Copy link
Member Author

@nagilson nagilson Feb 3, 2026

Choose a reason for hiding this comment

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

I think this is worth discussing, though this contends to manifest and uninstall design, which I somewhat want to avoid tangling with this discussion. All of this will be revisited when we implement that.

At a brief level, I'm intrigued by the idea of tracking the templates, the host, and the license files separately. That seems like a mature approach. However, I'm unsure of the advantages - we believe the SDK will always include the templates for its corresponding version, so this data doesn't provide info we don't already have. Maybe this will be more useful if we want to compartmentalize the SDK though.

Core Question

If a user types:

`dotnetup sdk install 9.0`
`dotnetup runtime install 9.0`
`dotnetup sdk uninstall 9.0` // (or whichever the command ends up being)

Do we:
A. keep the runtime installed
B. uninstall the runtime

If a user types:

`dotnetup sdk install 8.0`
`dotnetup runtime install 8.0`
`dotnetup sdk update 9.0` // (or whichever the command ends up being)

Do we:
A. keep the 8.0 runtime installed
B. uninstall the runtime

The document here suggests we do A, because the user explicitly asked for the runtime. It also suggests if the runtime wasn't installed via a standalone command, we would do B. The same applies to updates - do I want to remove the runtime bundled with the SDK upon update if the user had previously ran dotnetup runtime install 8.0 but then did dotnetup sdk update (to 9.0)?

I'm unsure how educated users are about the fact that uninstalling the SDK will uninstall the runtime and whether that's a clear gesture, so I was thinking we would only track the runtime in the manifest if we want to uninstall it separately. The same goes for updates, I don't want to accidentally update the runtime a user had installed explicitly.

Copy link
Member Author

Choose a reason for hiding this comment

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

Adding @baronfel for an opinion!

Copy link
Member

Choose a reason for hiding this comment

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

Mature upgrade support includes tracking everything but that can be tricky. Leaving behind packs or templates often can have minimal impact so we should balance complexity and value here. For the admin install (which is probably the comparison of the ideal state), we would do A for both scenarios you listed.

Copy link
Member Author

Choose a reason for hiding this comment

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

I agree to prefer A.

With respect to implementation and the root comment:

Approach 1: (current spec)

The runtime component isn't added to the manifest when the SDK is installed.

A component in the manifest represents an explicit user action to install that individual component. When we uninstall/update, we know what components are bundled with the SDK, so before we modify those components, we check if they're in the manifest or not.

Approach 2: Suggestion

The runtime component (and other components) are all added for every install.

This means we need to also track either:
a. data representing an explicit install request for an object
b. ref counts/ref links, or subcomponents, to which component owns other components

The implementation would depend on that - maybe we can take this approach but remark upon the other components as sub components.

Copy link
Member

Choose a reason for hiding this comment

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

It feels to me like it will actually be simpler to track everything, because then we are treating everything consistently and we don't need to worry about whether we have the right rules about what versions of what ship inside the SDK or runtime.

It looks like there are only six top-level folders, so we would need to hard-code for each of those folders how "deep" we go to get the final version. For example, under sdk we would only go two levels (sdk/10.0.101), but under sdk-manifests we would go four levels: sdk-manifests/10.0.100/microsoft.net.sdk.android/36.1.2

That's the level at which we'd have to record things in the manifest too. By my count that would be about 30 for the SDK, and I think that matches what we would call the number of separate versionable components.

If you want to separate it out and get runtime install done first, then I think we could split that out. We could support installing runtimes and it doesn't matter what we track in the manifest or what rules we have until we want to support uninstall and update. I think this would make sense.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think this makes sense, perhaps we can classify those as subcomponents under the SDK so we can still search the root of the manifest for an explicit runtime install. I agree though, let's implement/document this separately. I'll try to remove this from the documentation for the runtime installs themselves to prevent duplicate sources of truth.

Copy link
Member Author

@nagilson nagilson Feb 4, 2026

Choose a reason for hiding this comment

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

moved this to the new discussion design doc #52834

This is the result of the discussion we had.

There is some concern about providing the 'version' option at all but we lean towards parity with the sdk install command.

We decided not to have --type to prevent confusion with the other command, not to overload the number of ways to do an install with dotnetup. Thus, encourage use of the @ syntax amongst other reasons.
@nagilson nagilson enabled auto-merge February 4, 2026 21:21
@nagilson nagilson merged commit 3aa6ae5 into dotnet:release/dnup Feb 4, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants