From fbed4da7996a26971dd9a1f598c8a6a4cf4688f3 Mon Sep 17 00:00:00 2001 From: hiroyukitamura Date: Wed, 20 May 2026 16:09:48 +0300 Subject: [PATCH 1/3] [vector_graphics_compiler] Use Abi.current() for engine-artifact lookup On Linux ARM64 hosts, asset bundling fails with `Could not locate libpathops at .../engine/linux-x64/libpath_ops.so`. Flutter ships the engine binary at `.../engine/linux-arm64/...`, but _initialize_path_ops_io.dart and _initialize_tessellator_io.dart hardcode `'linux-x64'` on Linux. Switch the Linux branch to pick `'linux-arm64'` when Abi.current() == Abi.linuxArm64, otherwise keep `'linux-x64'`. Behavior on existing hosts is unchanged. Fixes flutter/flutter#158865. --- packages/vector_graphics_compiler/CHANGELOG.md | 7 +++++++ .../lib/src/_initialize_path_ops_io.dart | 4 +++- .../lib/src/_initialize_tessellator_io.dart | 4 +++- packages/vector_graphics_compiler/pubspec.yaml | 2 +- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/vector_graphics_compiler/CHANGELOG.md b/packages/vector_graphics_compiler/CHANGELOG.md index f246e4d0b0db..75979d49146c 100644 --- a/packages/vector_graphics_compiler/CHANGELOG.md +++ b/packages/vector_graphics_compiler/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.2.6 + +* Fixes `linux-arm64` host support by selecting the Flutter engine + artifact directory from `Abi.current()` instead of a hardcoded + `linux-x64`. The same fix applies to the tessellator loader. + Resolves flutter/flutter#158865. + ## 1.2.5 * Updates allowed version range of `xml` to include up to 7.0.1. diff --git a/packages/vector_graphics_compiler/lib/src/_initialize_path_ops_io.dart b/packages/vector_graphics_compiler/lib/src/_initialize_path_ops_io.dart index ba0301b5308a..290b7ced9db1 100644 --- a/packages/vector_graphics_compiler/lib/src/_initialize_path_ops_io.dart +++ b/packages/vector_graphics_compiler/lib/src/_initialize_path_ops_io.dart @@ -4,7 +4,9 @@ // ignore_for_file: avoid_print +import 'dart:ffi' show Abi; import 'dart:io'; + import 'svg/path_ops.dart'; /// Look up the location of the pathops from flutter's artifact cache. @@ -28,7 +30,7 @@ bool initializePathOpsFromFlutterCache() { platform = 'darwin-x64'; executable = 'libpath_ops.dylib'; } else if (Platform.isLinux) { - platform = 'linux-x64'; + platform = Abi.current() == Abi.linuxArm64 ? 'linux-arm64' : 'linux-x64'; executable = 'libpath_ops.so'; } else { print('path_ops not supported on ${Platform.localeName}'); diff --git a/packages/vector_graphics_compiler/lib/src/_initialize_tessellator_io.dart b/packages/vector_graphics_compiler/lib/src/_initialize_tessellator_io.dart index 735f633687da..34dae8db4a32 100644 --- a/packages/vector_graphics_compiler/lib/src/_initialize_tessellator_io.dart +++ b/packages/vector_graphics_compiler/lib/src/_initialize_tessellator_io.dart @@ -4,7 +4,9 @@ // ignore_for_file: avoid_print +import 'dart:ffi' show Abi; import 'dart:io'; + import 'svg/tessellator.dart'; /// Look up the location of the tessellator from flutter's artifact cache. @@ -28,7 +30,7 @@ bool initializeTessellatorFromFlutterCache() { platform = 'darwin-x64'; executable = 'libtessellator.dylib'; } else if (Platform.isLinux) { - platform = 'linux-x64'; + platform = Abi.current() == Abi.linuxArm64 ? 'linux-arm64' : 'linux-x64'; executable = 'libtessellator.so'; } else { print('Tesselation not supported on ${Platform.localeName}'); diff --git a/packages/vector_graphics_compiler/pubspec.yaml b/packages/vector_graphics_compiler/pubspec.yaml index 31dbd1909577..db216b088853 100644 --- a/packages/vector_graphics_compiler/pubspec.yaml +++ b/packages/vector_graphics_compiler/pubspec.yaml @@ -2,7 +2,7 @@ name: vector_graphics_compiler description: A compiler to convert SVGs to the binary format used by `package:vector_graphics`. repository: https://github.com/flutter/packages/tree/main/packages/vector_graphics_compiler issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+vector_graphics%22 -version: 1.2.5 +version: 1.2.6 executables: vector_graphics_compiler: From d8f0ce5a527890bf598d379aca475d9cd8f14ab8 Mon Sep 17 00:00:00 2001 From: hiroyukitamura Date: Tue, 2 Jun 2026 23:08:13 +0300 Subject: [PATCH 2/3] [vector_graphics_compiler] Extract engineArtifactSubpath helper with tests Moves engine-artifact directory/file selection out of the per-loader if/else blocks into a pure engineArtifactSubpath(...) helper keyed on Abi. Unit tests cover every supported host ABI, the linux-arm64 fix, and the unsupported-host branch. Hosts that Flutter does not ship engine artifacts for (linuxIA32, linuxArm, linuxRiscv32, linuxRiscv64, windowsIA32) now report "not supported" instead of producing a non-loadable linux-x64/windows-x64 path. windowsArm64 still falls back to windows-x64 to match the original x64-emulation behavior. --- .../lib/src/_initialize_path_ops_io.dart | 22 ++--- .../lib/src/_initialize_tessellator_io.dart | 23 ++--- .../lib/src/engine_artifact.dart | 22 +++++ .../test/engine_artifact_test.dart | 94 +++++++++++++++++++ 4 files changed, 134 insertions(+), 27 deletions(-) create mode 100644 packages/vector_graphics_compiler/lib/src/engine_artifact.dart create mode 100644 packages/vector_graphics_compiler/test/engine_artifact_test.dart diff --git a/packages/vector_graphics_compiler/lib/src/_initialize_path_ops_io.dart b/packages/vector_graphics_compiler/lib/src/_initialize_path_ops_io.dart index 290b7ced9db1..e6a2160feb7a 100644 --- a/packages/vector_graphics_compiler/lib/src/_initialize_path_ops_io.dart +++ b/packages/vector_graphics_compiler/lib/src/_initialize_path_ops_io.dart @@ -7,6 +7,7 @@ import 'dart:ffi' show Abi; import 'dart:io'; +import 'engine_artifact.dart'; import 'svg/path_ops.dart'; /// Look up the location of the pathops from flutter's artifact cache. @@ -21,22 +22,17 @@ bool initializePathOpsFromFlutterCache() { return false; } - final String platform; - final String executable; - if (Platform.isWindows) { - platform = 'windows-x64'; - executable = 'path_ops.dll'; - } else if (Platform.isMacOS) { - platform = 'darwin-x64'; - executable = 'libpath_ops.dylib'; - } else if (Platform.isLinux) { - platform = Abi.current() == Abi.linuxArm64 ? 'linux-arm64' : 'linux-x64'; - executable = 'libpath_ops.so'; - } else { + final String? subpath = engineArtifactSubpath( + windowsFile: 'path_ops.dll', + macOSFile: 'libpath_ops.dylib', + linuxFile: 'libpath_ops.so', + abi: Abi.current(), + ); + if (subpath == null) { print('path_ops not supported on ${Platform.localeName}'); return false; } - final pathops = '${cacheRoot.path}/artifacts/engine/$platform/$executable'; + final pathops = '${cacheRoot.path}/artifacts/engine/$subpath'; if (!File(pathops).existsSync()) { print('Could not locate libpathops at $pathops.'); print('Ensure you are on a supported version of flutter and then run '); diff --git a/packages/vector_graphics_compiler/lib/src/_initialize_tessellator_io.dart b/packages/vector_graphics_compiler/lib/src/_initialize_tessellator_io.dart index 34dae8db4a32..f930176c9ec1 100644 --- a/packages/vector_graphics_compiler/lib/src/_initialize_tessellator_io.dart +++ b/packages/vector_graphics_compiler/lib/src/_initialize_tessellator_io.dart @@ -7,6 +7,7 @@ import 'dart:ffi' show Abi; import 'dart:io'; +import 'engine_artifact.dart'; import 'svg/tessellator.dart'; /// Look up the location of the tessellator from flutter's artifact cache. @@ -21,23 +22,17 @@ bool initializeTessellatorFromFlutterCache() { return false; } - final String platform; - final String executable; - if (Platform.isWindows) { - platform = 'windows-x64'; - executable = 'libtessellator.dll'; - } else if (Platform.isMacOS) { - platform = 'darwin-x64'; - executable = 'libtessellator.dylib'; - } else if (Platform.isLinux) { - platform = Abi.current() == Abi.linuxArm64 ? 'linux-arm64' : 'linux-x64'; - executable = 'libtessellator.so'; - } else { + final String? subpath = engineArtifactSubpath( + windowsFile: 'libtessellator.dll', + macOSFile: 'libtessellator.dylib', + linuxFile: 'libtessellator.so', + abi: Abi.current(), + ); + if (subpath == null) { print('Tesselation not supported on ${Platform.localeName}'); return false; } - final tessellator = - '${cacheRoot.path}/artifacts/engine/$platform/$executable'; + final tessellator = '${cacheRoot.path}/artifacts/engine/$subpath'; if (!File(tessellator).existsSync()) { print('Could not locate libtessellator at $tessellator.'); print('Ensure you are on a supported version of flutter and then run '); diff --git a/packages/vector_graphics_compiler/lib/src/engine_artifact.dart b/packages/vector_graphics_compiler/lib/src/engine_artifact.dart new file mode 100644 index 000000000000..1a304aeec9ed --- /dev/null +++ b/packages/vector_graphics_compiler/lib/src/engine_artifact.dart @@ -0,0 +1,22 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:ffi' show Abi; + +/// Returns the engine-artifact subpath (`/`) for [abi], +/// or `null` if the host is unsupported. +String? engineArtifactSubpath({ + required String windowsFile, + required String macOSFile, + required String linuxFile, + required Abi abi, +}) { + return switch (abi) { + Abi.windowsX64 || Abi.windowsArm64 => 'windows-x64/$windowsFile', + Abi.macosX64 || Abi.macosArm64 => 'darwin-x64/$macOSFile', + Abi.linuxX64 => 'linux-x64/$linuxFile', + Abi.linuxArm64 => 'linux-arm64/$linuxFile', + _ => null, + }; +} diff --git a/packages/vector_graphics_compiler/test/engine_artifact_test.dart b/packages/vector_graphics_compiler/test/engine_artifact_test.dart new file mode 100644 index 000000000000..03c43bb8202f --- /dev/null +++ b/packages/vector_graphics_compiler/test/engine_artifact_test.dart @@ -0,0 +1,94 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:ffi'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:vector_graphics_compiler/src/engine_artifact.dart'; + +void main() { + String? pathOps(Abi abi) => engineArtifactSubpath( + windowsFile: 'path_ops.dll', + macOSFile: 'libpath_ops.dylib', + linuxFile: 'libpath_ops.so', + abi: abi, + ); + + String? tessellator(Abi abi) => engineArtifactSubpath( + windowsFile: 'libtessellator.dll', + macOSFile: 'libtessellator.dylib', + linuxFile: 'libtessellator.so', + abi: abi, + ); + + group('engineArtifactSubpath', () { + group('Windows', () { + test('windowsX64 -> windows-x64/', () { + expect(pathOps(Abi.windowsX64), 'windows-x64/path_ops.dll'); + expect(tessellator(Abi.windowsX64), 'windows-x64/libtessellator.dll'); + }); + + test('windowsArm64 falls back to windows-x64 (x64 emulation)', () { + expect(pathOps(Abi.windowsArm64), 'windows-x64/path_ops.dll'); + }); + }); + + group('macOS', () { + test('macosX64 -> darwin-x64/', () { + expect(pathOps(Abi.macosX64), 'darwin-x64/libpath_ops.dylib'); + expect(tessellator(Abi.macosX64), 'darwin-x64/libtessellator.dylib'); + }); + + test('macosArm64 -> darwin-x64/', () { + expect(pathOps(Abi.macosArm64), 'darwin-x64/libpath_ops.dylib'); + }); + }); + + group('Linux', () { + test('linuxX64 -> linux-x64/', () { + expect(pathOps(Abi.linuxX64), 'linux-x64/libpath_ops.so'); + expect(tessellator(Abi.linuxX64), 'linux-x64/libtessellator.so'); + }); + + test('linuxArm64 -> linux-arm64/', () { + expect(pathOps(Abi.linuxArm64), 'linux-arm64/libpath_ops.so'); + expect(tessellator(Abi.linuxArm64), 'linux-arm64/libtessellator.so'); + }); + }); + + group('unsupported hosts return null', () { + test('android', () { + expect(pathOps(Abi.androidArm64), isNull); + }); + + test('iOS', () { + expect(pathOps(Abi.iosArm64), isNull); + }); + + test('fuchsia', () { + expect(pathOps(Abi.fuchsiaArm64), isNull); + }); + + test('linuxArm (32-bit)', () { + expect(pathOps(Abi.linuxArm), isNull); + }); + + test('linuxIA32', () { + expect(pathOps(Abi.linuxIA32), isNull); + }); + + test('linuxRiscv32', () { + expect(pathOps(Abi.linuxRiscv32), isNull); + }); + + test('linuxRiscv64', () { + expect(pathOps(Abi.linuxRiscv64), isNull); + }); + + test('windowsIA32', () { + expect(pathOps(Abi.windowsIA32), isNull); + }); + }); + }); +} From c2e5a543eb8b0f017d80cc78caa58957772fe462 Mon Sep 17 00:00:00 2001 From: hiroyukitamura Date: Tue, 2 Jun 2026 23:08:26 +0300 Subject: [PATCH 3/3] [vector_graphics_compiler] Print Abi in unsupported-host error The "not supported on" message in the path_ops and tessellator loaders used Platform.localeName (e.g. "en_US"), which identifies the user's locale rather than the host. Switch to Abi.current() so the printed value (e.g. "Abi.linuxRiscv64") actually identifies the unsupported host. --- .../lib/src/_initialize_path_ops_io.dart | 2 +- .../lib/src/_initialize_tessellator_io.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/vector_graphics_compiler/lib/src/_initialize_path_ops_io.dart b/packages/vector_graphics_compiler/lib/src/_initialize_path_ops_io.dart index e6a2160feb7a..badd0060d80e 100644 --- a/packages/vector_graphics_compiler/lib/src/_initialize_path_ops_io.dart +++ b/packages/vector_graphics_compiler/lib/src/_initialize_path_ops_io.dart @@ -29,7 +29,7 @@ bool initializePathOpsFromFlutterCache() { abi: Abi.current(), ); if (subpath == null) { - print('path_ops not supported on ${Platform.localeName}'); + print('path_ops not supported on ${Abi.current()}'); return false; } final pathops = '${cacheRoot.path}/artifacts/engine/$subpath'; diff --git a/packages/vector_graphics_compiler/lib/src/_initialize_tessellator_io.dart b/packages/vector_graphics_compiler/lib/src/_initialize_tessellator_io.dart index f930176c9ec1..9b138a21ddd5 100644 --- a/packages/vector_graphics_compiler/lib/src/_initialize_tessellator_io.dart +++ b/packages/vector_graphics_compiler/lib/src/_initialize_tessellator_io.dart @@ -29,7 +29,7 @@ bool initializeTessellatorFromFlutterCache() { abi: Abi.current(), ); if (subpath == null) { - print('Tesselation not supported on ${Platform.localeName}'); + print('Tesselation not supported on ${Abi.current()}'); return false; } final tessellator = '${cacheRoot.path}/artifacts/engine/$subpath';