Skip to content

Commit

Permalink
[native_toolchain_c] Support MSVC arm64 toolchain
Browse files Browse the repository at this point in the history
  • Loading branch information
pbo-linaro committed Oct 30, 2023
1 parent 762b4da commit 239a815
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 4 deletions.
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.3.1

- Added MSVC arm64 toolchain.

## 0.3.0

- Bump `package:native_assets_cli` to 0.3.0.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ class CompilerResolver {
switch (targetArch) {
case Architecture.ia32:
return clIA32;
case Architecture.arm64:
return clArm64;
case Architecture.x64:
return cl;
}
Expand Down Expand Up @@ -172,6 +174,8 @@ class CompilerResolver {
switch (targetArchitecture) {
case Architecture.ia32:
return libIA32;
case Architecture.arm64:
return libArm64;
case Architecture.x64:
return lib;
}
Expand Down
53 changes: 50 additions & 3 deletions pkgs/native_toolchain_c/lib/src/native_toolchain/msvc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,17 @@ Tool vcvars(ToolInstance toolInstance) {
final tool = toolInstance.tool;
assert(tool == cl || tool == link || tool == lib);
final vcDir = toolInstance.uri.resolve('../../../../../../');
final fileName = toolInstance.uri.toFilePath().contains('x86')
? 'vcvars32.bat'
: 'vcvars64.bat';
final fileName;
if (toolInstance.uri.toFilePath().contains('\\x86\\')) {
fileName = 'vcvars32.bat';
} else if (toolInstance.uri.toFilePath().contains('\\arm64\\')) {
// vcvarsarm64 only works on native windows-arm64. In case of cross
// compilation, it's better to stick to cross toolchain, which works under
// emulation on windows-arm64.
fileName = 'vcvarsamd64_arm64.bat';
} else {
fileName = 'vcvars64.bat';
}
final batchScript = vcDir.resolve('Auxiliary/Build/$fileName');
return Tool(
name: fileName,
Expand Down Expand Up @@ -96,6 +104,18 @@ final Tool vcvars32 = Tool(
),
);

final Tool vcvarsarm64 = Tool(
// vcvarsarm64 only works on native windows-arm64. In case of cross
// compilation, it's better to stick to cross toolchain, which works under
// emulation on windows-arm64.
name: 'vcvarsamd64_arm64.bat',
defaultResolver: RelativeToolResolver(
toolName: 'vcvarsamd64_arm64.bat',
wrappedResolver: visualStudio.defaultResolver!,
relativePath: Uri(path: './VC/Auxiliary/Build/vcvarsamd64_arm64.bat'),
),
);

final Tool vcvarsall = Tool(
name: 'vcvarsall.bat',
defaultResolver: RelativeToolResolver(
Expand Down Expand Up @@ -134,6 +154,16 @@ final Tool clIA32 = _msvcTool(
hostArchitecture: Target.current.architecture,
);

/// The C/C++ Optimizing Compiler main executable.
///
/// For targeting arm64.
final Tool clArm64 = _msvcTool(
name: 'cl',
versionArguments: [],
targetArchitecture: Architecture.arm64,
hostArchitecture: Target.current.architecture,
);

final Tool lib = _msvcTool(
name: 'lib',
targetArchitecture: Architecture.x64,
Expand All @@ -150,6 +180,14 @@ final Tool libIA32 = _msvcTool(
resolveVersion: false,
);

final Tool libArm64 = _msvcTool(
name: 'lib',
targetArchitecture: Architecture.arm64,
hostArchitecture: Target.current.architecture,
// https://github.com/dart-lang/native/issues/18
resolveVersion: false,
);

final Tool link = _msvcTool(
name: 'link',
versionArguments: ['/help'],
Expand All @@ -166,6 +204,14 @@ final Tool linkIA32 = _msvcTool(
hostArchitecture: Target.current.architecture,
);

final Tool linkArm64 = _msvcTool(
name: 'link',
versionArguments: ['/help'],
versionExitCode: 1100,
targetArchitecture: Architecture.arm64,
hostArchitecture: Target.current.architecture,
);

final Tool dumpbin = _msvcTool(
name: 'dumpbin',
targetArchitecture: Architecture.x64,
Expand All @@ -175,6 +221,7 @@ final Tool dumpbin = _msvcTool(
const _msvcArchNames = {
Architecture.ia32: 'x86',
Architecture.x64: 'x64',
Architecture.arm64: 'arm64',
};

Tool _msvcTool({
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.3.0
version: 0.3.1
repository: https://github.com/dart-lang/native/tree/main/pkgs/native_toolchain_c

topics:
Expand Down
42 changes: 42 additions & 0 deletions pkgs/native_toolchain_c/test/native_toolchain/msvc_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ void main() {
expect(instances.isNotEmpty, true);
});

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

test('lib', () async {
final instances = await lib.defaultResolver!.resolve(logger: logger);
expect(instances.isNotEmpty, true);
Expand All @@ -58,6 +63,11 @@ void main() {
expect(instances.isNotEmpty, true);
});

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

test('link', () async {
final instances = await link.defaultResolver!.resolve(logger: logger);
expect(instances.isNotEmpty, true);
Expand All @@ -68,6 +78,11 @@ void main() {
expect(instances.isNotEmpty, true);
});

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

test('dumpbin', () async {
final instances = await dumpbin.defaultResolver!.resolve(logger: logger);
expect(instances.isNotEmpty, true);
Expand All @@ -82,6 +97,7 @@ void main() {
.resolve(logger: logger);
expect(instances.isNotEmpty, true);
final instance = instances.first;
expect(instance.tool, vcvars32);
final env = await envFromBat(instance.uri);
expect(env['INCLUDE'] != null, true);
expect(env['WindowsSdkDir'] != null, true); // stdio.h
Expand All @@ -96,6 +112,22 @@ void main() {
.resolve(logger: logger);
expect(instances.isNotEmpty, true);
final instance = instances.first;
expect(instance.tool, vcvars64);
final env = await envFromBat(instance.uri);
expect(env['INCLUDE'] != null, true);
expect(env['WindowsSdkDir'] != null, true); // stdio.h
});

test('vcvarsarm64 from cl.exe', () async {
final clInstances = await clArm64.defaultResolver!.resolve(logger: logger);
expect(clInstances.isNotEmpty, true);

final instances = await vcvars(clInstances.first)
.defaultResolver!
.resolve(logger: logger);
expect(instances.isNotEmpty, true);
final instance = instances.first;
expect(instance.tool, vcvarsarm64);
final env = await envFromBat(instance.uri);
expect(env['INCLUDE'] != null, true);
expect(env['WindowsSdkDir'] != null, true); // stdio.h
Expand All @@ -119,6 +151,16 @@ void main() {
expect(env['WindowsSdkDir'] != null, true); // stdio.h
});

test('vcvarsarm64', () async {
final instances =
await vcvarsarm64.defaultResolver!.resolve(logger: logger);
expect(instances.isNotEmpty, true);
final instance = instances.first;
final env = await envFromBat(instance.uri);
expect(env['INCLUDE'] != null, true);
expect(env['WindowsSdkDir'] != null, true); // stdio.h
});

test('vcvarsall', () async {
final instances = await vcvarsall.defaultResolver!.resolve(logger: logger);
expect(instances.isNotEmpty, true);
Expand Down

0 comments on commit 239a815

Please sign in to comment.