Skip to content

Commit 279094d

Browse files
authored
[native_toolchain_c] Support MSVC arm64 toolchain (#167)
1 parent 9629a55 commit 279094d

File tree

5 files changed

+107
-6
lines changed

5 files changed

+107
-6
lines changed

pkgs/native_toolchain_c/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.3.1
2+
3+
- Added MSVC arm64 toolchain.
4+
15
## 0.3.0
26

37
- Bump `package:native_assets_cli` to 0.3.0.

pkgs/native_toolchain_c/lib/src/cbuilder/compiler_resolver.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ class CompilerResolver {
8585
switch (targetArch) {
8686
case Architecture.ia32:
8787
return clIA32;
88+
case Architecture.arm64:
89+
return clArm64;
8890
case Architecture.x64:
8991
return cl;
9092
}
@@ -172,6 +174,8 @@ class CompilerResolver {
172174
switch (targetArchitecture) {
173175
case Architecture.ia32:
174176
return libIA32;
177+
case Architecture.arm64:
178+
return libArm64;
175179
case Architecture.x64:
176180
return lib;
177181
}

pkgs/native_toolchain_c/lib/src/native_toolchain/msvc.dart

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,19 @@ Tool vcvars(ToolInstance toolInstance) {
6363
final tool = toolInstance.tool;
6464
assert(tool == cl || tool == link || tool == lib);
6565
final vcDir = toolInstance.uri.resolve('../../../../../../');
66-
final fileName = toolInstance.uri.toFilePath().contains('x86')
67-
? 'vcvars32.bat'
68-
: 'vcvars64.bat';
66+
final String fileName;
67+
if (toolInstance.uri.toFilePath().contains('\\x86\\')) {
68+
fileName = 'vcvars32.bat';
69+
} else if (toolInstance.uri.toFilePath().contains('\\arm64\\')) {
70+
// TODO(https://github.com/dart-lang/native/issues/170): Support native
71+
// windows-arm64 MSVC toolchain.
72+
// vcvarsarm64 only works on native windows-arm64. In case of cross
73+
// compilation, it's better to stick to cross toolchain, which works under
74+
// emulation on windows-arm64.
75+
fileName = 'vcvarsamd64_arm64.bat';
76+
} else {
77+
fileName = 'vcvars64.bat';
78+
}
6979
final batchScript = vcDir.resolve('Auxiliary/Build/$fileName');
7080
return Tool(
7181
name: fileName,
@@ -96,6 +106,20 @@ final Tool vcvars32 = Tool(
96106
),
97107
);
98108

109+
final Tool vcvarsarm64 = Tool(
110+
// TODO(https://github.com/dart-lang/native/issues/170): Support native
111+
// windows-arm64 MSVC toolchain.
112+
// vcvarsarm64 only works on native windows-arm64. In case of cross
113+
// compilation, it's better to stick to cross toolchain, which works under
114+
// emulation on windows-arm64.
115+
name: 'vcvarsamd64_arm64.bat',
116+
defaultResolver: RelativeToolResolver(
117+
toolName: 'vcvarsamd64_arm64.bat',
118+
wrappedResolver: visualStudio.defaultResolver!,
119+
relativePath: Uri(path: './VC/Auxiliary/Build/vcvarsamd64_arm64.bat'),
120+
),
121+
);
122+
99123
final Tool vcvarsall = Tool(
100124
name: 'vcvarsall.bat',
101125
defaultResolver: RelativeToolResolver(
@@ -116,7 +140,7 @@ final Tool vsDevCmd = Tool(
116140

117141
/// The C/C++ Optimizing Compiler main executable.
118142
///
119-
/// For targeting x64.
143+
/// For targeting [Architecture.x64].
120144
final Tool cl = _msvcTool(
121145
name: 'cl',
122146
versionArguments: [],
@@ -126,14 +150,24 @@ final Tool cl = _msvcTool(
126150

127151
/// The C/C++ Optimizing Compiler main executable.
128152
///
129-
/// For targeting ia32.
153+
/// For targeting [Architecture.ia32].
130154
final Tool clIA32 = _msvcTool(
131155
name: 'cl',
132156
versionArguments: [],
133157
targetArchitecture: Architecture.ia32,
134158
hostArchitecture: Target.current.architecture,
135159
);
136160

161+
/// The C/C++ Optimizing Compiler main executable.
162+
///
163+
/// For targeting [Architecture.arm64].
164+
final Tool clArm64 = _msvcTool(
165+
name: 'cl',
166+
versionArguments: [],
167+
targetArchitecture: Architecture.arm64,
168+
hostArchitecture: Target.current.architecture,
169+
);
170+
137171
final Tool lib = _msvcTool(
138172
name: 'lib',
139173
targetArchitecture: Architecture.x64,
@@ -150,6 +184,14 @@ final Tool libIA32 = _msvcTool(
150184
resolveVersion: false,
151185
);
152186

187+
final Tool libArm64 = _msvcTool(
188+
name: 'lib',
189+
targetArchitecture: Architecture.arm64,
190+
hostArchitecture: Target.current.architecture,
191+
// https://github.com/dart-lang/native/issues/18
192+
resolveVersion: false,
193+
);
194+
153195
final Tool link = _msvcTool(
154196
name: 'link',
155197
versionArguments: ['/help'],
@@ -166,6 +208,14 @@ final Tool linkIA32 = _msvcTool(
166208
hostArchitecture: Target.current.architecture,
167209
);
168210

211+
final Tool linkArm64 = _msvcTool(
212+
name: 'link',
213+
versionArguments: ['/help'],
214+
versionExitCode: 1100,
215+
targetArchitecture: Architecture.arm64,
216+
hostArchitecture: Target.current.architecture,
217+
);
218+
169219
final Tool dumpbin = _msvcTool(
170220
name: 'dumpbin',
171221
targetArchitecture: Architecture.x64,
@@ -175,6 +225,7 @@ final Tool dumpbin = _msvcTool(
175225
const _msvcArchNames = {
176226
Architecture.ia32: 'x86',
177227
Architecture.x64: 'x64',
228+
Architecture.arm64: 'arm64',
178229
};
179230

180231
Tool _msvcTool({

pkgs/native_toolchain_c/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: native_toolchain_c
22
description: >-
33
A library to invoke the native C compiler installed on the host machine.
4-
version: 0.3.0
4+
version: 0.3.1
55
repository: https://github.com/dart-lang/native/tree/main/pkgs/native_toolchain_c
66

77
topics:

pkgs/native_toolchain_c/test/native_toolchain/msvc_test.dart

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ void main() {
4848
expect(instances.isNotEmpty, true);
4949
});
5050

51+
test('clArm64', () async {
52+
final instances = await clArm64.defaultResolver!.resolve(logger: logger);
53+
expect(instances.isNotEmpty, true);
54+
});
55+
5156
test('lib', () async {
5257
final instances = await lib.defaultResolver!.resolve(logger: logger);
5358
expect(instances.isNotEmpty, true);
@@ -58,6 +63,11 @@ void main() {
5863
expect(instances.isNotEmpty, true);
5964
});
6065

66+
test('libArm64', () async {
67+
final instances = await libArm64.defaultResolver!.resolve(logger: logger);
68+
expect(instances.isNotEmpty, true);
69+
});
70+
6171
test('link', () async {
6272
final instances = await link.defaultResolver!.resolve(logger: logger);
6373
expect(instances.isNotEmpty, true);
@@ -68,6 +78,11 @@ void main() {
6878
expect(instances.isNotEmpty, true);
6979
});
7080

81+
test('linkArm64', () async {
82+
final instances = await linkArm64.defaultResolver!.resolve(logger: logger);
83+
expect(instances.isNotEmpty, true);
84+
});
85+
7186
test('dumpbin', () async {
7287
final instances = await dumpbin.defaultResolver!.resolve(logger: logger);
7388
expect(instances.isNotEmpty, true);
@@ -82,6 +97,7 @@ void main() {
8297
.resolve(logger: logger);
8398
expect(instances.isNotEmpty, true);
8499
final instance = instances.first;
100+
expect(instance.tool, vcvars32);
85101
final env = await envFromBat(instance.uri);
86102
expect(env['INCLUDE'] != null, true);
87103
expect(env['WindowsSdkDir'] != null, true); // stdio.h
@@ -96,6 +112,22 @@ void main() {
96112
.resolve(logger: logger);
97113
expect(instances.isNotEmpty, true);
98114
final instance = instances.first;
115+
expect(instance.tool, vcvars64);
116+
final env = await envFromBat(instance.uri);
117+
expect(env['INCLUDE'] != null, true);
118+
expect(env['WindowsSdkDir'] != null, true); // stdio.h
119+
});
120+
121+
test('vcvarsarm64 from cl.exe', () async {
122+
final clInstances = await clArm64.defaultResolver!.resolve(logger: logger);
123+
expect(clInstances.isNotEmpty, true);
124+
125+
final instances = await vcvars(clInstances.first)
126+
.defaultResolver!
127+
.resolve(logger: logger);
128+
expect(instances.isNotEmpty, true);
129+
final instance = instances.first;
130+
expect(instance.tool, vcvarsarm64);
99131
final env = await envFromBat(instance.uri);
100132
expect(env['INCLUDE'] != null, true);
101133
expect(env['WindowsSdkDir'] != null, true); // stdio.h
@@ -119,6 +151,16 @@ void main() {
119151
expect(env['WindowsSdkDir'] != null, true); // stdio.h
120152
});
121153

154+
test('vcvarsarm64', () async {
155+
final instances =
156+
await vcvarsarm64.defaultResolver!.resolve(logger: logger);
157+
expect(instances.isNotEmpty, true);
158+
final instance = instances.first;
159+
final env = await envFromBat(instance.uri);
160+
expect(env['INCLUDE'] != null, true);
161+
expect(env['WindowsSdkDir'] != null, true); // stdio.h
162+
});
163+
122164
test('vcvarsall', () async {
123165
final instances = await vcvarsall.defaultResolver!.resolve(logger: logger);
124166
expect(instances.isNotEmpty, true);

0 commit comments

Comments
 (0)