Skip to content

Add --arch option for --list-runtimes and --list-sdks in host #116078

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jun 3, 2025

Conversation

elinor-fung
Copy link
Member

@elinor-fung elinor-fung commented May 28, 2025

Allow specifying --arch <arch> for --list-runtimes and --list-sdks commands in host. Must be in the order --list-runtimes/sdks --arch <arch>.

  • If not specified, behaviour remains the same - list runtimes/SDKs for the invoked dotnet (for SDKs, any paths specified any found global.json are respected).
  • If specified and not the same as the host architecture, searches for registered or default install locations for that architecture and lists runtimes/SDKs found there.
  • If specified and the same as the host architecture, behaves the same as if not specified - note that this means it will not search for registered/default installs of the host architecture and only list runtimes/SDKs relative to the invoked dotnet.

Example - x64 host, registered x86 install, no arm64 install

>C:\net10.0-windows-Release-x64\dotnet.exe --list-runtimes
Microsoft.NETCore.App 10.0.0 [C:\net10.0-windows-Release-x64\shared\Microsoft.NETCore.App]

>C:\net10.0-windows-Release-x64\dotnet.exe --list-runtimes --arch x64
Microsoft.NETCore.App 10.0.0 [C:\net10.0-windows-Release-x64\shared\Microsoft.NETCore.App]

>C:\net10.0-windows-Release-x64\dotnet.exe --list-runtimes --arch arm64

>C:\net10.0-windows-Release-x64\dotnet.exe --list-runtimes --arch x86
Microsoft.AspNetCore.App 8.0.16 [C:\Program Files (x86)\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 9.0.5 [C:\Program Files (x86)\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 8.0.16 [C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 9.0.5 [C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 8.0.16 [C:\Program Files (x86)\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 9.0.5 [C:\Program Files (x86)\dotnet\shared\Microsoft.WindowsDesktop.App]

>C:\net10.0-windows-Release-x64\dotnet.exe --list-sdks
10.0.100-preview.4.25258.110 [C:\net10.0-windows-Release-x64\sdk]

>C:\net10.0-windows-Release-x64\dotnet.exe --list-sdks --arch x64
10.0.100-preview.4.25258.110 [C:\net10.0-windows-Release-x64\sdk]

>C:\net10.0-windows-Release-x64\dotnet.exe --list-sdks --arch arm64

>C:\net10.0-windows-Release-x64\dotnet.exe --list-sdks --arch x86
8.0.410 [C:\Program Files (x86)\dotnet\sdk]
9.0.300 [C:\Program Files (x86)\dotnet\sdk]

New tests are in a HostCommands test class. This also moves some existing tests for host commands into the new class (bdcc21a).

  • Info covers DotnetArgValidation.DotNetInfo_WithSDK, MultipleHives.DotNetInfo, MultilevelSDKLookup.DotNetInfo
  • Info_NoSDK covers DotnetArgValidation.DotNetInfo_NoSDK
  • Info_Utf8Path covers DotnetArgValidation.DotNetInfo_Utf8Path
  • ListRuntimes covers MultipleHives.ListRuntimes
  • ListSdks covers MultilevelSDKLookup.ListSdks
  • ListRuntimes_OtherArchitecture* and ListSdks_OtherArchitecture* cover the functionality added in this PR

This does remove tests running the host commands with the multi-level lookup environment variable set, but I don't think those are interesting anymore - it has been disabled since 7.0 and should always be disabled (unlike for actually running an app, where it can be based on the tfm)

Resolves #108503

cc @dotnet/appmodel @AaronRobinsonMSFT @nagilson

@elinor-fung elinor-fung added this to the 10.0.0 milestone May 28, 2025
@Copilot Copilot AI review requested due to automatic review settings May 28, 2025 21:32
Copy link
Contributor

Tagging subscribers to this area: @vitek-karas, @agocke, @VSadov
See info in area-owners.md if you want to be subscribed.

Copy link
Contributor

@Copilot 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 a --arch <arch> option to the --list-runtimes and --list-sdks host commands, allowing users to target a specific architecture’s install location when listing available runtimes or SDKs.

  • Introduces get_default_installation_dir_for_arch and install_info::try_get_install_location to resolve architecture-specific install paths.
  • Updates the FX muxer (fx_muxer.cpp) and command-line help (command_line.cpp) to parse and document the new --arch flag.
  • Changes print_all_sdks and print_all_frameworks signatures to accept const pal::char_t* for leading whitespace, and reorganizes tests to focus on the --arch behavior.

Reviewed Changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/native/corehost/hostmisc/pal.windows.cpp Forward get_default_installation_dir to the new ARCH overload
src/native/corehost/hostmisc/pal.unix.cpp Same change on Unix and rename test ENV var to environment_override
src/native/corehost/fxr/sdk_info.h & sdk_info.cpp Change print_all_sdks to take const pal::char_t*
src/native/corehost/fxr/install_info.h & install_info.cpp Add try_get_install_location and unify install-location logic
src/native/corehost/fxr/fx_muxer.cpp Add get_requested_architecture, handle --arch in list commands
src/native/corehost/fxr/framework_info.h & framework_info.cpp Change print_all_frameworks to take const pal::char_t*
src/native/corehost/fxr/command_line.cpp Document --arch <arch> in usage output and adjust padding
src/installer/tests/HostActivation.Tests/... Remove outdated multilevel-lookup tests; add new HostCommands suite
Comments suppressed due to low confidence (2)

src/native/corehost/hostmisc/pal.windows.cpp:392

  • [nitpick] The local variable name environmentOverride uses camelCase, whereas the Unix counterpart uses environment_override. Consider renaming to environment_override for consistency.
pal::string_t environmentOverride;

src/native/corehost/fxr/fx_muxer.cpp:1030

  • There are no tests covering the error paths when --arch is provided without a value or with an unrecognized value. Consider adding unit or integration tests that verify an InvalidArgFailure exit code and the corresponding error message.
if (argc < 4)

Comment on lines 358 to 359
trace::println(_X(" --list-runtimes [--arch <arch>] Display the installed runtimes."));
trace::println(_X(" --list-sdks [--arch <arch>] Display the installed SDKs."));
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
trace::println(_X(" --list-runtimes [--arch <arch>] Display the installed runtimes."));
trace::println(_X(" --list-sdks [--arch <arch>] Display the installed SDKs."));
trace::println(_X(" --list-runtimes [--arch <arch>] Display the installed runtimes matching the host or specified architecture. Valid options are x64 and arm64."));
trace::println(_X(" --list-sdks [--arch <arch>] Display the installed SDKs matching the host or specified architecture. Valid options are x64 and arm64."));

Would it be helpful to include this information? Or, should we include this elsewhere?

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 started with listing all valid arch values, but there are a decent number and listing them all didn't seem that helpful:

const pal::char_t* s_all_architectures[] =
{
_X("arm"),
_X("arm64"),
_X("armv6"),
_X("loongarch64"),
_X("ppc64le"),
_X("riscv64"),
_X("s390x"),
_X("x64"),
_X("x86")
};

Maybe just listing common ones as examples?
Display the installed runtimes matching the host or specified architecture. Example architectures: arm64, x64, x86

Copy link
Member

Choose a reason for hiding this comment

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

I like this suggestion! To me it would be valuable to document the values it accepts somewhere and what string format they are in because different ecosystems can describe the same architecture in different ways. I never would have expected 'rscv64' to be a valid value, though I don't work in anything related to that space. If I was a dev outside of dotnet and wanted to use this, there's a chance I'd end up at this comment thread to resolve that question 😁

@nagilson
Copy link
Member

@elinor-fung Hm, I just realized this might be tricky for us to adopt and know whether --arch is supported or not, since it will have the 'same' output and just ignore the arch flag if it is not provided for older hosts. One way is for us to check the host version via dotnet --info but that would defeat the point because we want to avoid calling --info as it is slow. Another is --help but that isn't any better. Is there a better way for us to check the host version and or know that --arch is supported?

@elinor-fung
Copy link
Member Author

elinor-fung commented May 30, 2025

Yeah, I was thinking that could be a concern. Two (not great, but functional) ways I see:

  1. dotnet --list-runtimes --arch invalid
    • in the existing host, this succeeds (and prints the runtimes for the host arch)
    • with the changes in this PR, this would error out (non-zero exit code)
  2. dotnet --list-runtimes --arch <desired_arch> and dotnet --list-runtimes --arch <some_other_arch>
    • in the existing host, both commands will have exactly the same output
    • with the changes in this PR, the output should be different - with the exception of the case where both archs have no runtimes.

Both involve an extra call to --list-runtimes/sdks, but 1 is probably a bit better, since the extra call doesn't actually have to go try to list the runtimes/sdks.

@agocke
Copy link
Member

agocke commented May 30, 2025

Must be in the order --list-runtimes/sdks --arch

Is this restriction necessary? It violates the GNU getopt spec.

@elinor-fung
Copy link
Member Author

Must be in the order --list-runtimes/sdks --arch

Is this restriction necessary? It violates the GNU getopt spec.

Technically, we could probably make that work. I had started with that, but went back to the specific order because:

  • Existing functionality requires --list-runtimes/sdks to be the first argument
  • We use this to know that the command is for the host, not the SDK
  • We could only allow flipped order of --list-runtimes/sdks and --arch <arch> as the first arguments, nothing before/in between, as anything else should go to the SDK.

I mentally went with --list-runtimes/sdks being more like a command (like build) that had to come first. If we add other options for --list-runtimes/sdks at some point, those should be order-independent.

@agocke
Copy link
Member

agocke commented May 30, 2025

  • Existing functionality requires --list-runtimes/sdks to be the first argument
  • We use this to know that the command is for the host, not the SDK
  • We could only allow flipped order of --list-runtimes/sdks and --arch as the first arguments, nothing before/in between, as anything else should go to the SDK.

Hmm, doesn't this still match up with getopts semantics? That is, my understanding the host options are basically

dotnet [options] [command] [command-options]

In that sense we would expect that [options] could be re-ordered arbitrarily, but they couldn't be moved past [command]. And similarly, [command-options] couldn't be moved before [command].

I think there are other ways for a getopts parser to interpret that command line, but it seems like this is one valid way, and if we do interpret it that way, all of our existing restrictions are getopts-compatible. This would be the only one that isn't.

@elinor-fung
Copy link
Member Author

I was seeing it as --list-runtimes/sdks is the command and --arch a command-option. --list-runtimes/sdks is unlike the actual options in that they can't be combined with other host options and don't actually apply to any command - for example dotnet --roll-forward major --list-runtimes <app_path> and dotnet --roll-forward major --list-runtimes will error out.

I think maybe they should be separated out from the options in the help usage so it is:

+Usage: dotnet [host-commands]
Usage: dotnet [host-options] [path-to-application]

@agocke
Copy link
Member

agocke commented May 30, 2025

--list-runtimes/sdks is unlike the actual options in that they can't be combined with other host options and don't actually apply to any command

This doesn't strike me as very different from --help in most unix commands. ChatGPT sums it up like this:

✅ Can --help Be Combined with Other Options?
Conventionally, No: Most well-behaved Unix commands ignore all other options and execute only --help when it is present.

Example:
ls --help --all  # Shows help, ignores --all

Reason: --help is meant to override other behaviors to aid the user.

✅ Does Position Matter?
Typically, No: Whether --help appears at the beginning, middle, or end of the arguments, it has the same effect.

Example:
grep --help pattern file
grep pattern --help file
grep pattern file --help

All of these usually trigger the help message and ignore pattern, file, etc.

My interpretation is: options can either be flags to other commands, or they can be commands to the host to do things like print data. They can be combined with other flags, but the semantics can be that other options may be ignored, or other options may be incompatible. And it doesn't seem like ordering matters.

@elinor-fung
Copy link
Member Author

Our existing --info, --help, --list-runtimes, and --list-sdks all violate that then? They all have to be first.

@nagilson
Copy link
Member

I should say: Thank you for this! I am excited to see what kind of perf improvement we get in C# load times in VS Code with this change; I expect it will be quite good.

@agocke
Copy link
Member

agocke commented May 30, 2025

Our existing --info, --help, --list-runtimes, and --list-sdks all violate that then? They all have to be first.

Hm ok, then maybe we can improve this later. Is there anything stopping us from allowing reordering the architecture flag in the future?

nagilson added a commit to nagilson/vscode-dotnet-runtime that referenced this pull request Jun 2, 2025
 dotnet/runtime#116078 --arch was not added until .NET 10 to allow us to skip calling dotnet --info because that is slow, as it is not native code.
        // However, --arch gets ignored if the host does not support it. The output is also identical with or without --arch.
        // After discussion with the runtime team, the best way to determine if the host supports --arch is to call it with an invalid arch to see if it fails, because that only happens when --arch is supported.

        // The --arch flag was added in the middle of .NET 10, so we can assume it is supported if the version is 10.0 or later.
        // We don't want to slow down the current common case for people without .NET 10 by adding another process spawn check.
        // We don't check that the version is 10.0 or later after 2026 when .NET 11 starts rolling out, as It will be slower to check all of the numbers in the output for versions >= 10.
@elinor-fung
Copy link
Member Author

elinor-fung commented Jun 2, 2025

There would be nothing stopping us from allowing reordering (relaxing a requirement, so existing scenarios would continue to work normally and I don't thing there's anything added here that would complicate allowing reordering in the future).

I opened: #116225
Please do update it with any more context/concerns.

Copy link
Member

@agocke agocke left a comment

Choose a reason for hiding this comment

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

LGTM

@elinor-fung elinor-fung merged commit b79d4c4 into dotnet:main Jun 3, 2025
148 of 150 checks passed
@elinor-fung elinor-fung deleted the listSdksRuntimes-arch branch June 4, 2025 22:47
nagilson added a commit to dotnet/vscode-dotnet-runtime that referenced this pull request Jun 5, 2025
#2296)

* Consider if host has --arch

* Update check to whether --arch is supported

 dotnet/runtime#116078 --arch was not added until .NET 10 to allow us to skip calling dotnet --info because that is slow, as it is not native code.
        // However, --arch gets ignored if the host does not support it. The output is also identical with or without --arch.
        // After discussion with the runtime team, the best way to determine if the host supports --arch is to call it with an invalid arch to see if it fails, because that only happens when --arch is supported.

        // The --arch flag was added in the middle of .NET 10, so we can assume it is supported if the version is 10.0 or later.
        // We don't want to slow down the current common case for people without .NET 10 by adding another process spawn check.
        // We don't check that the version is 10.0 or later after 2026 when .NET 11 starts rolling out, as It will be slower to check all of the numbers in the output for versions >= 10.

* Add a test

Also support .NET 11 behavior while its in pre-release

* Fix Bug Where HostArch is set to ''

* increase test timeout

they take longer now that they need to execute commands

* increase test timeout time again
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature Request] Dotnet Host Should Support Programmatic Installation Architecture Scans
4 participants