[code_assets] Support custom target OS and Architecture
diff --git a/pkgs/code_assets/CHANGELOG.md b/pkgs/code_assets/CHANGELOG.md index 5cf7491..b63ce11 100644 --- a/pkgs/code_assets/CHANGELOG.md +++ b/pkgs/code_assets/CHANGELOG.md
@@ -1,3 +1,9 @@ +## 2.0.0-wip + +- **Breaking change**: Overrode `==` and `hashCode` in `OS`, `Architecture`, `Sanitizer`, and `LinkModePreference` to support custom targets. These objects can no longer be used as keys of `const` maps and sets. + - *Migration*: Use `final` (runtime) maps and sets instead of `const`, or use the string representations (e.g., `OS.name`, `Architecture.name`) as keys if `const` is required. +- Support custom target OS, architecture, and santizer in protocol extension. + ## 1.2.1 - Avoid throwing a null-assertion error/exception when `input.config.code` is
diff --git a/pkgs/code_assets/README.md b/pkgs/code_assets/README.md index 37e7eda..6177b0d 100644 --- a/pkgs/code_assets/README.md +++ b/pkgs/code_assets/README.md
@@ -113,5 +113,22 @@ See the full example in [example/host_name/](example/host_name/). +### Custom Operating Systems and Architectures + +SDK authors can define custom OSes and Architectures that they support in a helper package like: + +<!-- file://./../hooks_runner/test/build_runner/custom_os_arch_test.dart --> +```dart +extension CustomOS on OS { + static final ohos = OS.fromString('ohos'); +} + +extension CustomArchitecture on Architecture { + static final mips = Architecture.fromString('mips'); +} +``` + +The users of those SDKs can import this helper package to use the custom OSes and Architectures in their build hooks. + For more information see [dart.dev/tools/hooks](https://dart.dev/tools/hooks).
diff --git a/pkgs/code_assets/example/sqlite_prebuilt/hook/build.dart b/pkgs/code_assets/example/sqlite_prebuilt/hook/build.dart index 508de9f..db0abae 100644 --- a/pkgs/code_assets/example/sqlite_prebuilt/hook/build.dart +++ b/pkgs/code_assets/example/sqlite_prebuilt/hook/build.dart
@@ -39,7 +39,7 @@ }); } -const _windowsDownloadInfo = { +final _windowsDownloadInfo = { Architecture.arm64: ( url: 'https://sqlite.org/2025/sqlite-dll-win-arm64-3500400.zip', sha256: 'c4f3d245377f4ee2da5c08e882ecaff376b35a609198dc399dd8cec0add1ea43', @@ -50,7 +50,7 @@ ), }; -const _linuxPaths = { +final _linuxPaths = { Architecture.arm64: <String>[], Architecture.x64: ['/usr/lib/x86_64-linux-gnu/libsqlite3.so'], };
diff --git a/pkgs/code_assets/lib/src/code_assets/architecture.dart b/pkgs/code_assets/lib/src/code_assets/architecture.dart index 6fa35f0..5f082f2 100644 --- a/pkgs/code_assets/lib/src/code_assets/architecture.dart +++ b/pkgs/code_assets/lib/src/code_assets/architecture.dart
@@ -81,33 +81,27 @@ /// /// The name can be obtained from [Architecture.name] or /// [Architecture.toString]. - factory Architecture.fromString(String name) => - ArchitectureSyntaxExtension.fromSyntax(ArchitectureSyntax.fromJson(name)); + factory Architecture.fromString(String name) => values.firstWhere( + (e) => e.name == name, + orElse: () => Architecture._(name), + ); /// The current [Architecture]. static final Architecture current = _abiToArch[Abi.current()]!; + + @override + bool operator ==(Object other) => other is Architecture && other.name == name; + + @override + int get hashCode => name.hashCode; } /// Extension methods for [Architecture] to convert to and from the syntax. extension ArchitectureSyntaxExtension on Architecture { - static final _toSyntax = { - for (final item in Architecture.values) - item: ArchitectureSyntax.fromJson(item.name), - }; - - static final _fromSyntax = { - for (var entry in _toSyntax.entries) entry.value: entry.key, - }; - /// Converts this [Architecture] to its corresponding [ArchitectureSyntax]. - ArchitectureSyntax toSyntax() => _toSyntax[this]!; + ArchitectureSyntax toSyntax() => ArchitectureSyntax.fromJson(name); /// Converts an [ArchitectureSyntax] to its corresponding [Architecture]. static Architecture fromSyntax(ArchitectureSyntax syntax) => - switch (_fromSyntax[syntax]) { - null => throw FormatException( - 'The architecture "${syntax.name}" is not known', - ), - final arch => arch, - }; + Architecture.fromString(syntax.name); }
diff --git a/pkgs/code_assets/lib/src/code_assets/code_asset.dart b/pkgs/code_assets/lib/src/code_assets/code_asset.dart index 74bef09..53dd3e5 100644 --- a/pkgs/code_assets/lib/src/code_assets/code_asset.dart +++ b/pkgs/code_assets/lib/src/code_assets/code_asset.dart
@@ -189,7 +189,7 @@ } /// The default name prefix for dynamic libraries per [OS]. -const _dylibPrefix = { +final _dylibPrefix = { OS.android: 'lib', OS.fuchsia: 'lib', OS.iOS: 'lib', @@ -199,7 +199,7 @@ }; /// The default extension for dynamic libraries per [OS]. -const _dylibExtension = { +final _dylibExtension = { OS.android: 'so', OS.fuchsia: 'so', OS.iOS: 'dylib', @@ -209,10 +209,10 @@ }; /// The default name prefix for static libraries per [OS]. -const _staticlibPrefix = _dylibPrefix; +final _staticlibPrefix = _dylibPrefix; /// The default extension for static libraries per [OS]. -const _staticlibExtension = { +final _staticlibExtension = { OS.android: 'a', OS.fuchsia: 'a', OS.iOS: 'a', @@ -222,7 +222,7 @@ }; /// The default extension for executables per [OS]. -const _executableExtension = { +final _executableExtension = { OS.android: '', OS.fuchsia: '', OS.iOS: '',
diff --git a/pkgs/code_assets/lib/src/code_assets/os.dart b/pkgs/code_assets/lib/src/code_assets/os.dart index 6fd6b59..c427e3f 100644 --- a/pkgs/code_assets/lib/src/code_assets/os.dart +++ b/pkgs/code_assets/lib/src/code_assets/os.dart
@@ -40,7 +40,7 @@ static const List<OS> values = [android, fuchsia, iOS, linux, macOS, windows]; /// Typical cross compilation between OSes. - static const osCrossCompilationDefault = { + static final osCrossCompilationDefault = { OS.macOS: [OS.macOS, OS.iOS, OS.android], OS.linux: [OS.linux, OS.android], OS.windows: [OS.windows, OS.android], @@ -57,30 +57,25 @@ /// /// The name can be obtained from [OS.name] or [OS.toString]. factory OS.fromString(String name) => - OSSyntaxExtension.fromSyntax(OSSyntax.fromJson(name)); + values.firstWhere((e) => e.name == name, orElse: () => OS._(name)); /// The current [OS]. /// /// Consistent with the [Platform.version] string. static final OS current = OS.fromString(Platform.operatingSystem); + + @override + bool operator ==(Object other) => other is OS && other.name == name; + + @override + int get hashCode => name.hashCode; } /// Extension methods for [OS] to convert to and from the syntax model. extension OSSyntaxExtension on OS { - static final _toSyntax = { - for (final item in OS.values) item: OSSyntax.fromJson(item.name), - }; - - static final _fromSyntax = { - for (var entry in _toSyntax.entries) entry.value: entry.key, - }; - /// Converts this [OS] to its corresponding [OSSyntax]. - OSSyntax toSyntax() => _toSyntax[this]!; + OSSyntax toSyntax() => OSSyntax.fromJson(name); /// Converts an [OSSyntax] to its corresponding [OS]. - static OS fromSyntax(OSSyntax syntax) => switch (_fromSyntax[syntax]) { - null => throw FormatException('The OS "${syntax.name}" is not known'), - final e => e, - }; + static OS fromSyntax(OSSyntax syntax) => OS.fromString(syntax.name); }
diff --git a/pkgs/code_assets/lib/src/code_assets/sanitizer.dart b/pkgs/code_assets/lib/src/code_assets/sanitizer.dart index d64b9a2..57ff68e 100644 --- a/pkgs/code_assets/lib/src/code_assets/sanitizer.dart +++ b/pkgs/code_assets/lib/src/code_assets/sanitizer.dart
@@ -60,28 +60,21 @@ /// /// The name can be obtained from [Sanitizer.name] or [Sanitizer.toString]. factory Sanitizer.fromString(String name) => - SanitizerSyntaxExtension.fromSyntax(SanitizerSyntax.fromJson(name)); + values.firstWhere((e) => e.name == name, orElse: () => Sanitizer._(name)); + + @override + bool operator ==(Object other) => other is Sanitizer && other.name == name; + + @override + int get hashCode => name.hashCode; } /// Extension methods for [Sanitizer] to convert to and from the syntax model. extension SanitizerSyntaxExtension on Sanitizer { - static final _toSyntax = { - for (final item in Sanitizer.values) - item: SanitizerSyntax.fromJson(item.name), - }; - - static final _fromSyntax = { - for (var entry in _toSyntax.entries) entry.value: entry.key, - }; - /// Converts this [Sanitizer] to its corresponding [SanitizerSyntax]. - SanitizerSyntax toSyntax() => - _toSyntax[this] ?? SanitizerSyntax.fromJson(name); + SanitizerSyntax toSyntax() => SanitizerSyntax.fromJson(name); /// Converts an [SanitizerSyntax] to its corresponding [Sanitizer]. static Sanitizer fromSyntax(SanitizerSyntax syntax) => - switch (_fromSyntax[syntax]) { - null => Sanitizer._(syntax.name), - final e => e, - }; + Sanitizer.fromString(syntax.name); }
diff --git a/pkgs/code_assets/pubspec.yaml b/pkgs/code_assets/pubspec.yaml index 42c687a..8dfedb3 100644 --- a/pkgs/code_assets/pubspec.yaml +++ b/pkgs/code_assets/pubspec.yaml
@@ -3,7 +3,7 @@ This library contains the hook protocol specification for bundling native code with Dart packages. -version: 1.2.1 +version: 2.0.0-wip repository: https://github.com/dart-lang/native/tree/main/pkgs/code_assets
diff --git a/pkgs/code_assets/test/code_assets/config_test.dart b/pkgs/code_assets/test/code_assets/config_test.dart index 8c7cfe4..82f876a 100644 --- a/pkgs/code_assets/test/code_assets/config_test.dart +++ b/pkgs/code_assets/test/code_assets/config_test.dart
@@ -325,27 +325,24 @@ } }); - test('BuildInput.config.code: invalid architecture', () { + test('BuildInput.config.code: custom architecture', () { final input = inputJson(); traverseJson<Map<String, Object?>>(input, [ 'config', 'extensions', 'code_assets', - ])['target_architecture'] = 'invalid_architecture'; - expect( - () => BuildInput(input).config.code.targetArchitecture, - throwsFormatException, - ); + ])['target_architecture'] = 'mips'; + expect(BuildInput(input).config.code.targetArchitecture.name, 'mips'); }); - test('LinkInput.config.code: invalid os', () { + test('LinkInput.config.code: custom os', () { final input = inputJson(hookType: 'link'); traverseJson<Map<String, Object?>>(input, [ 'config', 'extensions', 'code_assets', - ])['target_os'] = 'invalid_os'; - expect(() => LinkInput(input).config.code.targetOS, throwsFormatException); + ])['target_os'] = 'ohos'; + expect(LinkInput(input).config.code.targetOS.name, 'ohos'); }); test('LinkInput.config.code.target_os invalid type', () {
diff --git a/pkgs/ffigen/CHANGELOG.md b/pkgs/ffigen/CHANGELOG.md index 6765fc3..75cd728 100644 --- a/pkgs/ffigen/CHANGELOG.md +++ b/pkgs/ffigen/CHANGELOG.md
@@ -1,8 +1,9 @@ -## 21.0.1-wip +## 21.1.0-wip - Bump `package:meta` dependency to `^1.19.0` and stop generating `experimental_member_use` lint ignore in generated bindings when `@RecordUse()` is used. +- Bump `package:code_assets` dependency to `^2.0.0`. ## 21.0.0
diff --git a/pkgs/ffigen/example/add/pubspec.yaml b/pkgs/ffigen/example/add/pubspec.yaml index 74488a7..c6b8ce4 100644 --- a/pkgs/ffigen/example/add/pubspec.yaml +++ b/pkgs/ffigen/example/add/pubspec.yaml
@@ -15,3 +15,13 @@ ffigen: path: '../../' test: ^1.25.15 + +dependency_overrides: + code_assets: + path: ../../../code_assets + hooks: + path: ../../../hooks + native_toolchain_c: + path: ../../../native_toolchain_c + record_use: + path: ../../../record_use
diff --git a/pkgs/ffigen/example/c_json/pubspec.yaml b/pkgs/ffigen/example/c_json/pubspec.yaml index e218628..c52b424 100644 --- a/pkgs/ffigen/example/c_json/pubspec.yaml +++ b/pkgs/ffigen/example/c_json/pubspec.yaml
@@ -15,3 +15,13 @@ dart_flutter_team_lints: ^3.5.2 ffigen: path: '../../' + +dependency_overrides: + code_assets: + path: ../../../code_assets + hooks: + path: ../../../hooks + native_toolchain_c: + path: ../../../native_toolchain_c + record_use: + path: ../../../record_use
diff --git a/pkgs/ffigen/example/ffinative/pubspec.yaml b/pkgs/ffigen/example/ffinative/pubspec.yaml index e3a1b3d..8506a05 100644 --- a/pkgs/ffigen/example/ffinative/pubspec.yaml +++ b/pkgs/ffigen/example/ffinative/pubspec.yaml
@@ -14,3 +14,13 @@ dart_flutter_team_lints: ^3.5.2 ffigen: path: '../../' + +dependency_overrides: + code_assets: + path: ../../../code_assets + hooks: + path: ../../../hooks + native_toolchain_c: + path: ../../../native_toolchain_c + record_use: + path: ../../../record_use
diff --git a/pkgs/ffigen/example/libclang-example/pubspec.yaml b/pkgs/ffigen/example/libclang-example/pubspec.yaml index c2a2e38..504526e 100644 --- a/pkgs/ffigen/example/libclang-example/pubspec.yaml +++ b/pkgs/ffigen/example/libclang-example/pubspec.yaml
@@ -14,3 +14,13 @@ dart_flutter_team_lints: ^3.5.2 ffigen: path: '../../' + +dependency_overrides: + code_assets: + path: ../../../code_assets + hooks: + path: ../../../hooks + native_toolchain_c: + path: ../../../native_toolchain_c + record_use: + path: ../../../record_use
diff --git a/pkgs/ffigen/example/objective_c/pubspec.yaml b/pkgs/ffigen/example/objective_c/pubspec.yaml index f8b72c2..81391cf 100644 --- a/pkgs/ffigen/example/objective_c/pubspec.yaml +++ b/pkgs/ffigen/example/objective_c/pubspec.yaml
@@ -19,5 +19,13 @@ path: ../../ dependency_overrides: + code_assets: + path: ../../../code_assets + hooks: + path: ../../../hooks + native_toolchain_c: + path: ../../../native_toolchain_c objective_c: path: ../../../objective_c/ + record_use: + path: ../../../record_use
diff --git a/pkgs/ffigen/example/shared_bindings/pubspec.yaml b/pkgs/ffigen/example/shared_bindings/pubspec.yaml index cc1256f..c6681f2 100644 --- a/pkgs/ffigen/example/shared_bindings/pubspec.yaml +++ b/pkgs/ffigen/example/shared_bindings/pubspec.yaml
@@ -16,3 +16,15 @@ dart_flutter_team_lints: ^3.5.2 ffigen: path: '../../' + +dependency_overrides: + code_assets: + path: ../../../code_assets + hooks: + path: ../../../hooks + native_toolchain_c: + path: ../../../native_toolchain_c + objective_c: + path: ../../../objective_c + record_use: + path: ../../../record_use
diff --git a/pkgs/ffigen/example/simple/pubspec.yaml b/pkgs/ffigen/example/simple/pubspec.yaml index 4b6df34..efcca57 100644 --- a/pkgs/ffigen/example/simple/pubspec.yaml +++ b/pkgs/ffigen/example/simple/pubspec.yaml
@@ -14,3 +14,13 @@ dart_flutter_team_lints: ^3.5.2 ffigen: path: '../../' + +dependency_overrides: + code_assets: + path: ../../../code_assets + hooks: + path: ../../../hooks + native_toolchain_c: + path: ../../../native_toolchain_c + record_use: + path: ../../../record_use
diff --git a/pkgs/ffigen/example/swift/pubspec.yaml b/pkgs/ffigen/example/swift/pubspec.yaml index 2ad0d9b..fc85465 100644 --- a/pkgs/ffigen/example/swift/pubspec.yaml +++ b/pkgs/ffigen/example/swift/pubspec.yaml
@@ -18,5 +18,13 @@ path: ../../ dependency_overrides: + code_assets: + path: ../../../code_assets + hooks: + path: ../../../hooks + native_toolchain_c: + path: ../../../native_toolchain_c objective_c: path: ../../../objective_c/ + record_use: + path: ../../../record_use
diff --git a/pkgs/ffigen/hook/build.dart b/pkgs/ffigen/hook/build.dart index 4c1f5b4..b310704 100644 --- a/pkgs/ffigen/hook/build.dart +++ b/pkgs/ffigen/hook/build.dart
@@ -221,12 +221,12 @@ return appleClangMacosTargetFlags[architecture]!; } -const appleClangMacosTargetFlags = { +final appleClangMacosTargetFlags = { Architecture.arm64: 'arm64-apple-darwin', Architecture.x64: 'x86_64-apple-darwin', }; -const appleClangIosTargetFlags = { +final appleClangIosTargetFlags = { Architecture.arm64: { IOSSdk.iPhoneOS: 'arm64-apple-ios', IOSSdk.iPhoneSimulator: 'arm64-apple-ios-simulator',
diff --git a/pkgs/ffigen/pubspec.yaml b/pkgs/ffigen/pubspec.yaml index b4891dc..19a6979 100644 --- a/pkgs/ffigen/pubspec.yaml +++ b/pkgs/ffigen/pubspec.yaml
@@ -3,7 +3,7 @@ # BSD-style license that can be found in the LICENSE file. name: ffigen -version: 21.0.1-wip +version: 21.1.0-wip description: > Generator for FFI bindings, using LibClang to parse C, Objective-C, and Swift files. @@ -21,7 +21,7 @@ dependencies: args: ^2.6.0 cli_util: ^0.4.2 - code_assets: ^1.1.0 + code_assets: ^2.0.0-wip collection: ^1.18.0 dart_style: ^3.0.0 ffi: ^2.0.1
diff --git a/pkgs/hooks/pubspec.yaml b/pkgs/hooks/pubspec.yaml index 7fc6871..25cec02 100644 --- a/pkgs/hooks/pubspec.yaml +++ b/pkgs/hooks/pubspec.yaml
@@ -30,7 +30,7 @@ dev_dependencies: args: ^2.6.0 - code_assets: ^1.0.0 # Used for running tests with real asset types. + code_assets: ^2.0.0-wip # Used for running tests with real asset types. dart_flutter_team_lints: ^3.5.2 data_assets: any # Used for running tests with real asset types. file_testing: ^3.0.2
diff --git a/pkgs/hooks_runner/CHANGELOG.md b/pkgs/hooks_runner/CHANGELOG.md index 3231f6e..400617c 100644 --- a/pkgs/hooks_runner/CHANGELOG.md +++ b/pkgs/hooks_runner/CHANGELOG.md
@@ -1,5 +1,6 @@ ## 1.6.0-wip +- Bump `package:code_assets` dependency to `^2.0.0`. - Fix record_use path changing caching issue. ## 1.5.0
diff --git a/pkgs/hooks_runner/lib/src/model/target.dart b/pkgs/hooks_runner/lib/src/model/target.dart index a485a46..9d14af3 100644 --- a/pkgs/hooks_runner/lib/src/model/target.dart +++ b/pkgs/hooks_runner/lib/src/model/target.dart
@@ -151,16 +151,20 @@ /// A list of supported target [Target]s from this host [os]. List<Target> supportedTargetTargets({ - Map<OS, List<OS>> osCrossCompilation = OS.osCrossCompilationDefault, - }) => Target.values - .where( - (target) => - // Only valid cross compilation. - osCrossCompilation[os]!.contains(target.os) && - // And no deprecated architectures. - target != Target.iOSArm, - ) - .sorted; + Map<OS, List<OS>>? osCrossCompilation, + }) { + final osCrossCompilation_ = + osCrossCompilation ?? OS.osCrossCompilationDefault; + return Target.values + .where( + (target) => + // Only valid cross compilation. + osCrossCompilation_[os]!.contains(target.os) && + // And no deprecated architectures. + target != Target.iOSArm, + ) + .sorted; + } } /// Common methods for manipulating iterables of [Target]s.
diff --git a/pkgs/hooks_runner/pubspec.yaml b/pkgs/hooks_runner/pubspec.yaml index f3a3ddb..b0c2c83 100644 --- a/pkgs/hooks_runner/pubspec.yaml +++ b/pkgs/hooks_runner/pubspec.yaml
@@ -12,7 +12,7 @@ sdk: '>=3.10.0 <4.0.0' dependencies: - code_assets: ^1.2.0 # Needed for OS for Target for KernelAssets. + code_assets: ^2.0.0-wip # Needed for OS for Target for KernelAssets. collection: ^1.19.1 crypto: ^3.0.6 file: ^7.0.1
diff --git a/pkgs/hooks_runner/test/build_runner/custom_os_arch_test.dart b/pkgs/hooks_runner/test/build_runner/custom_os_arch_test.dart new file mode 100644 index 0000000..ee3cee1 --- /dev/null +++ b/pkgs/hooks_runner/test/build_runner/custom_os_arch_test.dart
@@ -0,0 +1,83 @@ +// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io'; + +import 'package:code_assets/code_assets.dart'; +import 'package:file/local.dart' show LocalFileSystem; +import 'package:hooks_runner/hooks_runner.dart'; +import 'package:test/test.dart'; + +import '../helpers.dart'; +import 'helpers.dart'; + +const Timeout longTimeout = Timeout(Duration(minutes: 5)); + +void main() async { + test('build custom OS and architecture', timeout: longTimeout, () async { + await inTempDir((tempUri) async { + await copyTestProjects(targetUri: tempUri); + final packageUri = tempUri.resolve('custom_os_arch/'); + + // First, run `pub get` to resolve our dependencies. + await runPubGet(workingDirectory: packageUri, logger: logger); + + final packageLayout = await PackageLayout.fromWorkingDirectory( + const LocalFileSystem(), + packageUri, + 'custom_os_arch', + includeDevDependencies: false, + ); + + final buildRunner = NativeAssetsBuildRunner( + logger: logger, + dartExecutable: dartExecutable, + fileSystem: const LocalFileSystem(), + packageLayout: packageLayout, + ); + + final result = await buildRunner.build( + extensions: [ + CodeAssetExtension( + targetOS: CustomOS.ohos, + targetArchitecture: CustomArchitecture.mips, + linkModePreference: LinkModePreference.dynamic, + sanitizer: CustomSanitizer.mySanitizer, + ), + ], + linkingEnabled: false, + ); + + expect(result.isSuccess, isTrue); + final buildResult = result.success; + + expect(buildResult.encodedAssets.length, 1); + final codeAsset = buildResult.encodedAssets.first.asCodeAsset; + expect(codeAsset.id, 'package:custom_os_arch/my_asset'); + + expect(codeAsset.linkMode, isA<DynamicLoadingBundled>()); + + final fileContents = await File.fromUri(codeAsset.file!).readAsString(); + expect( + fileContents, + 'dummy: ohos, mips, my_sanitizer', + ); + }); + }); +} + +// snippet-start +extension CustomOS on OS { + static final ohos = OS.fromString('ohos'); +} + +extension CustomArchitecture on Architecture { + static final mips = Architecture.fromString('mips'); +} + +// snippet-end + +extension CustomSanitizer on Sanitizer { + static final mySanitizer = Sanitizer.fromString('my_sanitizer'); +}
diff --git a/pkgs/hooks_runner/test_data/custom_os_arch/hook/build.dart b/pkgs/hooks_runner/test_data/custom_os_arch/hook/build.dart new file mode 100644 index 0000000..5d0e127 --- /dev/null +++ b/pkgs/hooks_runner/test_data/custom_os_arch/hook/build.dart
@@ -0,0 +1,30 @@ +// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io'; + +import 'package:code_assets/code_assets.dart'; +import 'package:hooks/hooks.dart'; + +void main(List<String> arguments) async { + await build(arguments, (input, output) async { + final targetOS = input.config.code.targetOS; + final targetArch = input.config.code.targetArchitecture; + final sanitizer = input.config.code.sanitizer; + + final file = File.fromUri(input.outputDirectory.resolve('my_asset.so')); + await file.writeAsString( + 'dummy: $targetOS, $targetArch, $sanitizer', + ); + + output.assets.code.add( + CodeAsset( + package: 'custom_os_arch', + name: 'my_asset', + linkMode: DynamicLoadingBundled(), + file: file.uri, + ), + ); + }); +}
diff --git a/pkgs/hooks_runner/test_data/custom_os_arch/pubspec.yaml b/pkgs/hooks_runner/test_data/custom_os_arch/pubspec.yaml new file mode 100644 index 0000000..bbff61f --- /dev/null +++ b/pkgs/hooks_runner/test_data/custom_os_arch/pubspec.yaml
@@ -0,0 +1,14 @@ +name: custom_os_arch +description: A package to test custom OS and architecture settings. +version: 0.1.0 + +publish_to: none + +resolution: workspace + +environment: + sdk: '>=3.10.0 <4.0.0' + +dependencies: + code_assets: any + hooks: any
diff --git a/pkgs/hooks_runner/test_data/manifest.yaml b/pkgs/hooks_runner/test_data/manifest.yaml index 1f2180f..cfe3ab8 100644 --- a/pkgs/hooks_runner/test_data/manifest.yaml +++ b/pkgs/hooks_runner/test_data/manifest.yaml
@@ -23,6 +23,8 @@ - complex_link_helper/hook/build.dart - complex_link_helper/lib/complex_link_helper.dart - complex_link_helper/pubspec.yaml +- custom_os_arch/hook/build.dart +- custom_os_arch/pubspec.yaml - cyclic_link_package_1/hook/link.dart - cyclic_link_package_1/pubspec.yaml - cyclic_link_package_2/hook/link.dart
diff --git a/pkgs/native_toolchain_c/CHANGELOG.md b/pkgs/native_toolchain_c/CHANGELOG.md index e39828f..a79028c 100644 --- a/pkgs/native_toolchain_c/CHANGELOG.md +++ b/pkgs/native_toolchain_c/CHANGELOG.md
@@ -1,5 +1,6 @@ ## 0.19.3-wip +- Bump `package:code_assets` dependency to `^2.0.0`. - Fixed building with MSVC on Windows when a source, include, or output path contains a space (e.g. a user name with a space in the default pub cache location). The compiler and archiver are now invoked directly instead of @@ -14,7 +15,8 @@ ## 0.19.2 -- Fixed compatibility with newer Xcode versions when cross-compiling static libraries on macOS hosts targeting Android and Linux. +- Fixed compatibility with newer Xcode versions when cross-compiling static + libraries on macOS hosts targeting Android and Linux. ## 0.19.1
diff --git a/pkgs/native_toolchain_c/lib/src/cbuilder/run_cbuilder.dart b/pkgs/native_toolchain_c/lib/src/cbuilder/run_cbuilder.dart index d87233a..96ed274 100644 --- a/pkgs/native_toolchain_c/lib/src/cbuilder/run_cbuilder.dart +++ b/pkgs/native_toolchain_c/lib/src/cbuilder/run_cbuilder.dart
@@ -480,7 +480,7 @@ return '$baseName.obj'; } - static const androidNdkClangTargetFlags = { + static final androidNdkClangTargetFlags = { Architecture.arm: 'armv7a-linux-androideabi', Architecture.arm64: 'aarch64-linux-android', Architecture.ia32: 'i686-linux-android', @@ -488,12 +488,12 @@ Architecture.riscv64: 'riscv64-linux-android', }; - static const appleClangMacosTargetFlags = { + static final appleClangMacosTargetFlags = { Architecture.arm64: 'arm64-apple-darwin', Architecture.x64: 'x86_64-apple-darwin', }; - static const appleClangIosTargetFlags = { + static final appleClangIosTargetFlags = { Architecture.arm64: { IOSSdk.iPhoneOS: 'arm64-apple-ios', IOSSdk.iPhoneSimulator: 'arm64-apple-ios-simulator', @@ -501,19 +501,19 @@ Architecture.x64: {IOSSdk.iPhoneSimulator: 'x86_64-apple-ios-simulator'}, }; - static const clangWindowsTargetFlags = { + static final clangWindowsTargetFlags = { Architecture.arm64: 'arm64-pc-windows-msvc', Architecture.ia32: 'i386-pc-windows-msvc', Architecture.x64: 'x86_64-pc-windows-msvc', }; - static const clTargetFlags = { + static final clTargetFlags = { Architecture.arm64: 'ARM64', Architecture.ia32: 'X86', Architecture.x64: 'X64', }; - static const defaultCppLinkStdLib = { + static final defaultCppLinkStdLib = { OS.android: 'c++_shared', OS.fuchsia: 'c++', OS.iOS: 'c++', @@ -521,13 +521,13 @@ OS.macOS: 'c++', }; - static const _clangSanitizers = { + static final _clangSanitizers = { Sanitizer.asan: '-fsanitize=address', Sanitizer.msan: '-fsanitize=memory', Sanitizer.tsan: '-fsanitize=thread', }; - static const _msvcSanitizers = { + static final _msvcSanitizers = { Sanitizer.asan: '/fsanitize=address', }; }
diff --git a/pkgs/native_toolchain_c/lib/src/native_toolchain/msvc.dart b/pkgs/native_toolchain_c/lib/src/native_toolchain/msvc.dart index 8a1d20e..f22c6f2 100644 --- a/pkgs/native_toolchain_c/lib/src/native_toolchain/msvc.dart +++ b/pkgs/native_toolchain_c/lib/src/native_toolchain/msvc.dart
@@ -219,7 +219,7 @@ hostArchitecture: .current, ); -const _msvcArchNames = { +final _msvcArchNames = { Architecture.ia32: 'x86', Architecture.x64: 'x64', Architecture.arm64: 'arm64',
diff --git a/pkgs/native_toolchain_c/pubspec.yaml b/pkgs/native_toolchain_c/pubspec.yaml index 248df51..86dcfe6 100644 --- a/pkgs/native_toolchain_c/pubspec.yaml +++ b/pkgs/native_toolchain_c/pubspec.yaml
@@ -17,7 +17,7 @@ sdk: '>=3.10.0 <4.0.0' dependencies: - code_assets: ^1.2.0 + code_assets: ^2.0.0-wip glob: ^2.1.1 hooks: ^2.0.0 logging: ^1.3.0
diff --git a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_macos_host_test.dart b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_macos_host_test.dart index ed141fa..09511d6 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_macos_host_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_macos_host_test.dart
@@ -25,7 +25,7 @@ import '../helpers.dart'; // Dont include 'mach-o' or 'Mach-O', different spelling is used. -const objdumpFileFormat = { +final objdumpFileFormat = { (OS.macOS, Architecture.arm64): 'arm64', (OS.macOS, Architecture.x64): '64-bit x86-64', (OS.linux, Architecture.arm): 'elf32-littlearm',
diff --git a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_windows_host_test.dart b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_windows_host_test.dart index 6f644ed..8f08b17 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_windows_host_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_windows_host_test.dart
@@ -53,7 +53,7 @@ )).first.uri; }); - const dumpbinMachine = { + final dumpbinMachine = { Architecture.arm64: 'ARM64', Architecture.ia32: 'x86', Architecture.x64: 'x64',
diff --git a/pkgs/native_toolchain_c/test/helpers.dart b/pkgs/native_toolchain_c/test/helpers.dart index 2d84402..104b425 100644 --- a/pkgs/native_toolchain_c/test/helpers.dart +++ b/pkgs/native_toolchain_c/test/helpers.dart
@@ -186,7 +186,7 @@ return result.split('\n').firstWhere((e) => e.contains('Machine:')); } -const readElfMachine = { +final readElfMachine = { Architecture.arm: 'ARM', Architecture.arm64: 'AArch64', Architecture.ia32: 'Intel 80386', @@ -381,7 +381,7 @@ /// File-format strings used by the `objdump` tool for Android binaries that /// run on a given architecture. -const objdumpFileFormatAndroid = { +final objdumpFileFormatAndroid = { Architecture.arm: 'elf32-littlearm', Architecture.arm64: 'elf64-littleaarch64', Architecture.ia32: 'elf32-i386', @@ -389,18 +389,18 @@ Architecture.riscv64: 'elf64-littleriscv', }; -const objdumpFileFormatMacOS = { +final objdumpFileFormatMacOS = { Architecture.arm64: 'mach-o arm64', Architecture.x64: 'mach-o 64-bit x86-64', }; // Don't include 'mach-o' or 'Mach-O', different spelling is used. -const objdumpFileFormatIOS = { +final objdumpFileFormatIOS = { Architecture.arm64: 'arm64', Architecture.x64: '64-bit x86-64', }; -const objdumpFileFormatLinux = { +final objdumpFileFormatLinux = { Architecture.arm: 'elf32-littlearm', Architecture.arm64: 'elf64-littleaarch64', Architecture.ia32: 'elf32-i386', @@ -409,14 +409,14 @@ Architecture.riscv64: 'elf64-riscv64', }; -const targetOSToObjdumpFileFormat = { +final targetOSToObjdumpFileFormat = { OS.android: objdumpFileFormatAndroid, OS.macOS: objdumpFileFormatMacOS, OS.iOS: objdumpFileFormatMacOS, OS.linux: objdumpFileFormatLinux, }; -const dumpbinFileFormat = { +final dumpbinFileFormat = { Architecture.arm64: 'ARM64', Architecture.ia32: 'x86', Architecture.x64: 'x64',
diff --git a/pkgs/objective_c/CHANGELOG.md b/pkgs/objective_c/CHANGELOG.md index 66ccb0b..d9aaca2 100644 --- a/pkgs/objective_c/CHANGELOG.md +++ b/pkgs/objective_c/CHANGELOG.md
@@ -1,3 +1,7 @@ +## 9.4.2 + +- Bump `package:code_assets` dependency to `^2.0.0`. + ## 9.4.1 - Fix a [bug](https://github.com/flutter/flutter/issues/186794) related to
diff --git a/pkgs/objective_c/example/command_line/pubspec.yaml b/pkgs/objective_c/example/command_line/pubspec.yaml index fae3f21..1890859 100644 --- a/pkgs/objective_c/example/command_line/pubspec.yaml +++ b/pkgs/objective_c/example/command_line/pubspec.yaml
@@ -13,3 +13,13 @@ dev_dependencies: lints: ^6.0.0 test: ^1.27.0 + +dependency_overrides: + code_assets: + path: ../../../code_assets + hooks: + path: ../../../hooks + native_toolchain_c: + path: ../../../native_toolchain_c + record_use: + path: ../../../record_use
diff --git a/pkgs/objective_c/example/flutter_app/pubspec.yaml b/pkgs/objective_c/example/flutter_app/pubspec.yaml index a8dc3ec..326a294 100644 --- a/pkgs/objective_c/example/flutter_app/pubspec.yaml +++ b/pkgs/objective_c/example/flutter_app/pubspec.yaml
@@ -17,5 +17,17 @@ sdk: flutter flutter_lints: ^6.0.0 +dependency_overrides: + code_assets: + path: ../../../code_assets + hooks: + path: ../../../hooks + native_toolchain_c: + path: ../../../native_toolchain_c + record_use: + path: ../../../record_use + objective_c: + path: ../.. + flutter: uses-material-design: true
diff --git a/pkgs/objective_c/example/path_provider_example/ios/Flutter/Debug.xcconfig b/pkgs/objective_c/example/path_provider_example/ios/Flutter/Debug.xcconfig index 592ceee..ec97fc6 100644 --- a/pkgs/objective_c/example/path_provider_example/ios/Flutter/Debug.xcconfig +++ b/pkgs/objective_c/example/path_provider_example/ios/Flutter/Debug.xcconfig
@@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig"
diff --git a/pkgs/objective_c/example/path_provider_example/ios/Flutter/Release.xcconfig b/pkgs/objective_c/example/path_provider_example/ios/Flutter/Release.xcconfig index 592ceee..c4855bf 100644 --- a/pkgs/objective_c/example/path_provider_example/ios/Flutter/Release.xcconfig +++ b/pkgs/objective_c/example/path_provider_example/ios/Flutter/Release.xcconfig
@@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig"
diff --git a/pkgs/objective_c/example/path_provider_example/ios/Podfile b/pkgs/objective_c/example/path_provider_example/ios/Podfile new file mode 100644 index 0000000..620e46e --- /dev/null +++ b/pkgs/objective_c/example/path_provider_example/ios/Podfile
@@ -0,0 +1,43 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '13.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end
diff --git a/pkgs/objective_c/example/path_provider_example/pubspec.yaml b/pkgs/objective_c/example/path_provider_example/pubspec.yaml index 48c44f3..5200ef0 100644 --- a/pkgs/objective_c/example/path_provider_example/pubspec.yaml +++ b/pkgs/objective_c/example/path_provider_example/pubspec.yaml
@@ -19,6 +19,14 @@ flutter_lints: ^6.0.0 dependency_overrides: + code_assets: + path: ../../../code_assets + hooks: + path: ../../../hooks + native_toolchain_c: + path: ../../../native_toolchain_c + record_use: + path: ../../../record_use objective_c: path: ../..
diff --git a/pkgs/objective_c/hook/build.dart b/pkgs/objective_c/hook/build.dart index 280782f..646f7ad 100644 --- a/pkgs/objective_c/hook/build.dart +++ b/pkgs/objective_c/hook/build.dart
@@ -25,7 +25,7 @@ return; } - const supportedOSs = {OS.iOS, OS.macOS}; + final supportedOSs = {OS.iOS, OS.macOS}; final codeConfig = input.config.code; final os = codeConfig.targetOS; if (!supportedOSs.contains(os)) { @@ -217,12 +217,12 @@ return appleClangMacosTargetFlags[architecture]!; } -const appleClangMacosTargetFlags = { +final appleClangMacosTargetFlags = { Architecture.arm64: 'arm64-apple-darwin', Architecture.x64: 'x86_64-apple-darwin', }; -const appleClangIosTargetFlags = { +final appleClangIosTargetFlags = { Architecture.arm64: { IOSSdk.iPhoneOS: 'arm64-apple-ios', IOSSdk.iPhoneSimulator: 'arm64-apple-ios-simulator',
diff --git a/pkgs/objective_c/pubspec.yaml b/pkgs/objective_c/pubspec.yaml index aeefad9..84d2b62 100644 --- a/pkgs/objective_c/pubspec.yaml +++ b/pkgs/objective_c/pubspec.yaml
@@ -3,7 +3,7 @@ # BSD-style license that can be found in the LICENSE file. name: objective_c description: 'A library to access Objective C from Flutter that acts as a support library for package:ffigen.' -version: 9.4.1 +version: 9.4.2 repository: https://github.com/dart-lang/native/tree/main/pkgs/objective_c issue_tracker: https://github.com/dart-lang/native/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aobjective_c @@ -17,7 +17,7 @@ sdk: '>=3.10.0 <4.0.0' dependencies: - code_assets: ^1.1.0 + code_assets: ^2.0.0-wip collection: ^1.19.1 ffi: ^2.1.0 hooks: ^2.0.0 @@ -42,6 +42,8 @@ path: ../ffigen hooks: path: ../hooks + native_toolchain_c: + path: ../native_toolchain_c record_use: path: ../record_use
diff --git a/pkgs/swiftgen/example/pubspec.yaml b/pkgs/swiftgen/example/pubspec.yaml index 8daae28..d4c931c 100644 --- a/pkgs/swiftgen/example/pubspec.yaml +++ b/pkgs/swiftgen/example/pubspec.yaml
@@ -25,8 +25,14 @@ test: ^1.21.1 dependency_overrides: + code_assets: + path: ../../code_assets/ ffigen: path: ../../ffigen/ + hooks: + path: ../../hooks/ + native_toolchain_c: + path: ../../native_toolchain_c/ objective_c: path: ../../objective_c/ swift2objc:
diff --git a/pkgs/swiftgen/pubspec.yaml b/pkgs/swiftgen/pubspec.yaml index 033f36e..8df9bf2 100644 --- a/pkgs/swiftgen/pubspec.yaml +++ b/pkgs/swiftgen/pubspec.yaml
@@ -33,8 +33,14 @@ test: ^1.21.1 dependency_overrides: + code_assets: + path: ../code_assets/ ffigen: path: ../ffigen/ + hooks: + path: ../hooks/ + native_toolchain_c: + path: ../native_toolchain_c/ objective_c: path: ../objective_c/ swift2objc:
diff --git a/pubspec.yaml b/pubspec.yaml index 83b6fcf..2e82757 100644 --- a/pubspec.yaml +++ b/pubspec.yaml
@@ -37,6 +37,7 @@ - pkgs/hooks_runner/test_data/add_asset_link - pkgs/hooks_runner/test_data/complex_link - pkgs/hooks_runner/test_data/complex_link_helper + - pkgs/hooks_runner/test_data/custom_os_arch - pkgs/hooks_runner/test_data/cyclic_link_package_1 - pkgs/hooks_runner/test_data/cyclic_link_package_2 - pkgs/hooks_runner/test_data/cyclic_package_1
diff --git a/tool/ci.dart b/tool/ci.dart index fb184ca..b1d1d05 100644 --- a/tool/ci.dart +++ b/tool/ci.dart
@@ -190,7 +190,10 @@ final rootDir = Directory.fromUri(repositoryRoot.resolve('pkgs')); for (final entity in rootDir.listSync(recursive: true)) { if (entity is File && entity.path.endsWith('pubspec.yaml')) { - if (entity.path.split(Platform.pathSeparator).contains('.dart_tool')) { + final pathSegments = entity.path.split(Platform.pathSeparator); + if (pathSegments.contains('.dart_tool') || + pathSegments.contains('ephemeral')) { + // Can contain generated or symlinked pubspecs. continue; } packages.add(