Skip to content

Commit a9fdba4

Browse files
committed
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.
1 parent fdfb78f commit a9fdba4

File tree

1 file changed

+22
-2
lines changed

1 file changed

+22
-2
lines changed

vscode-dotnet-runtime-library/src/Acquisition/DotnetConditionValidator.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,14 @@ Please set the PATH to a dotnet host that matches the architecture ${requirement
125125

126126
const findSDKsCommand = CommandExecutor.makeCommand(`"${existingPath}"`, ['--list-sdks', '--arch', requestedArchitecture]);
127127

128-
const sdkInfo = await (this.executor!).execute(findSDKsCommand, { dotnetInstallToolCacheTtlMs: DOTNET_INFORMATION_CACHE_DURATION_MS }, false).then((result) =>
128+
const sdkInfo = await (this.executor!).execute(findSDKsCommand, { dotnetInstallToolCacheTtlMs: DOTNET_INFORMATION_CACHE_DURATION_MS }, false).then(async (result) =>
129129
{
130130
if (result.status !== '0')
131131
{
132132
return [];
133133
}
134+
135+
const hostSupportsArchFlag = await this.hostSupportsArchFlag(existingPath, result.stdout);
134136
const sdks = result.stdout.split('\n').map((line) => line.trim()).filter((line) => (line?.length ?? 0) > 0);
135137
const sdkInfos: IDotnetListInfo[] = sdks.map((sdk) =>
136138
{
@@ -149,6 +151,22 @@ Please set the PATH to a dotnet host that matches the architecture ${requirement
149151
return sdkInfo;
150152
}
151153

154+
private async hostSupportsArchFlag(dotnetExecutablePath: string, listDotnetInstallsStdout: string): Promise<boolean>
155+
{
156+
// https://github.com/dotnet/runtime/pull/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.
157+
// However, --arch gets ignored if the host does not support it. The output is also identical with or without --arch.
158+
// 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.
159+
160+
// 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.
161+
// We don't want to slow down the current common case for people without .NET 10 by adding another process spawn check.
162+
// 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.
163+
const hostMaySupportArchFlag = listDotnetInstallsStdout.includes("10.0") || Date.now() >= new Date('2026-03-01').getTime();
164+
// Use runtimes instead of sdks, as sdks will always have a runtime, and runtime search can be cached across both mode calls.
165+
const findInvalidCommand = CommandExecutor.makeCommand(`"${dotnetExecutablePath}"`, ['--list-runtimes', '--arch', 'invalid-arch']);
166+
const hostSupportsArchFlag = hostMaySupportArchFlag ? (await (this.executor!).execute(findInvalidCommand, { dotnetInstallToolCacheTtlMs: DOTNET_INFORMATION_CACHE_DURATION_MS }, false)).status !== '0' : false;
167+
return hostSupportsArchFlag;
168+
}
169+
152170
public stringVersionMeetsRequirement(availableVersion: string, requestedVersion: string, requirement: IDotnetFindPathContext): boolean
153171
{
154172
const availableMajor = Number(versionUtils.getMajor(availableVersion, this.workerContext.eventStream, this.workerContext));
@@ -298,12 +316,14 @@ Please set the PATH to a dotnet host that matches the architecture ${requirement
298316
const aspnetCoreString = 'Microsoft.AspNetCore.App';
299317
const runtimeString = 'Microsoft.NETCore.App';
300318

301-
const runtimeInfo = await (this.executor!).execute(findRuntimesCommand, { dotnetInstallToolCacheTtlMs: DOTNET_INFORMATION_CACHE_DURATION_MS }, false).then((result) =>
319+
const runtimeInfo = await (this.executor!).execute(findRuntimesCommand, { dotnetInstallToolCacheTtlMs: DOTNET_INFORMATION_CACHE_DURATION_MS }, false).then(async (result) =>
302320
{
303321
if (result.status !== '0')
304322
{
305323
return [];
306324
}
325+
326+
const hostSupportsArchFlag = await this.hostSupportsArchFlag(existingPath, result.stdout);
307327
const runtimes = result.stdout.split('\n').map((line) => line.trim()).filter((line) => (line?.length ?? 0) > 0);
308328
const runtimeInfos: IDotnetListInfo[] = runtimes.map((runtime) =>
309329
{

0 commit comments

Comments
 (0)