Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pkgs/native_toolchain_c/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.18.1

- Fix [native_toolchain_c failing with MSSSMS installed](https://github.com/dart-lang/native/issues/3327) by requiring vswhere to only show output that includes the necessary build tools

## 0.18.0

- Made `CLinker.run` `Logger` argument optional. It now defaults to a logger
Expand Down
11 changes: 10 additions & 1 deletion pkgs/native_toolchain_c/lib/src/native_toolchain/msvc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,16 @@ class VisualStudioResolver implements ToolResolver {
for (final vswhereInstance in vswhereInstances.take(1)) {
final vswhereResult = await runProcess(
executable: vswhereInstance.uri,
arguments: ['-format', 'json', '-utf8', '-latest', '-products', '*'],
arguments: const [
'-format',
'json',
'-utf8',
'-latest',
'-products',
'*',
'-requires',
'Microsoft.VisualStudio.Component.VC.Tools.x86.x64',

@dcharkes dcharkes Apr 28, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is only for if the target is Architecture.x64. For Architecture.arm64 it should be Microsoft.VisualStudio.Component.VC.Tools.ARM64. But, VisualStudioResolver doesn't take a target architecture, we're trying to find one visual studio.

So maybe a better fix is to first try 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', then add all instances with parseVswhere and then do the same with Microsoft.VisualStudio.Component.VC.Tools.ARM64.

We should probably try to run a CI on runs-on: windows-11-arm in .github/workflows/native.yaml to cover the CI. (But we can do that as a separate PR.)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I agree, given that the actual choosing is done in the caller, we should return all of the possible instances and implement choosing logic for the architecture somewhere here perhaps?

https://github.com/Chaos02/native/blob/812bd1bd6376f0f898627a11ea4c935fe3a544c4/pkgs/native_toolchain_c/lib/src/native_toolchain/msvc.dart#L228-L257

or maybe even here?

https://github.com/Chaos02/native/blob/fix/native-toolchain-c-vswhere-requires-3327-clean/pkgs/native_toolchain_c/lib/src/native_toolchain/msvc.dart#L41-L127

I'll suggest something, let me know if it sounds good to you

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

],
logger: logger,
);
final instances = parseVswhere(vswhereResult.stdout, logger);
Expand Down
2 changes: 1 addition & 1 deletion pkgs/native_toolchain_c/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: native_toolchain_c
description: >-
A library to invoke the native C compiler installed on the host machine.
version: 0.18.0
version: 0.18.1
repository: https://github.com/dart-lang/native/tree/main/pkgs/native_toolchain_c

topics:
Expand Down
50 changes: 38 additions & 12 deletions pkgs/native_toolchain_c/test/native_toolchain/msvc_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
@OnPlatform({'windows': Timeout.factor(10)})
library;

import 'dart:convert';
import 'dart:io';

import 'package:native_toolchain_c/src/native_toolchain/msvc.dart';
Expand Down Expand Up @@ -37,19 +38,44 @@ void main() {
expect(instances.isNotEmpty, true);
});

test('cl', () async {
final instances = await cl.defaultResolver!.resolve(systemContext);
expect(instances.isNotEmpty, true);
});

test('clIA32', () async {
final instances = await clIA32.defaultResolver!.resolve(systemContext);
expect(instances.isNotEmpty, true);
});
test('parseVswhere handles mixed installations', () async {
final tempUri = await tempDirForTest();
final ssmsDir = Directory.fromUri(
tempUri.resolve('Microsoft SQL Server Management Studio 22/Release'),
);
final visualStudioDir = Directory.fromUri(
tempUri.resolve('Microsoft Visual Studio/18/Community'),
);
await ssmsDir.create(recursive: true);
await visualStudioDir.create(recursive: true);

final instances = VisualStudioResolver().parseVswhere(
jsonEncode([
{
'installationName': 'SSMS/22.5.0+11709.299',
'installationPath': ssmsDir.path,
'installationVersion': '22.5.11709.299',
'productId': 'Microsoft.VisualStudio.Product.Ssms',
'displayName': 'SQL Server Management Studio 22',
},
{
'installationName': 'VisualStudio/18.5.1+11716.220',
'installationPath': visualStudioDir.path,
'installationVersion': '18.5.11716.220',
'productId': 'Microsoft.VisualStudio.Product.Community',
'displayName': 'Visual Studio Community 2026',
},
{
'installationName': 'Incomplete entry',
'productId': 'Microsoft.VisualStudio.Product.Incomplete',
},
]),
);

test('clArm64', () async {
final instances = await clArm64.defaultResolver!.resolve(systemContext);
expect(instances.isNotEmpty, true);
expect(instances, hasLength(2));
expect(instances.first.uri, ssmsDir.uri);
expect(instances.last.uri, visualStudioDir.uri);
expect(instances.map((instance) => instance.version!.major), [22, 18]);
});

test('lib', () async {
Expand Down
Loading