| // Copyright (c) 2024, 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. |
| |
| /// @docImport 'package:hooks/hooks.dart'; |
| /// @docImport 'src/code_assets/code_asset.dart'; |
| /// @docImport 'src/code_assets/config.dart'; |
| |
| /// This package provides the API for code assets to be used with |
| /// [`package:hooks`](https://pub.dev/packages/hooks). |
| /// |
| /// A [CodeAsset] is an asset containing executable code which respects the |
| /// native application binary interface (ABI). These assets are bundled with a |
| /// Dart or Flutter application. They can be produced by compiling C, C++, |
| /// Objective-C, Rust, or Go code for example. |
| /// |
| /// This package is used in a build hook (`hook/build.dart`) or link hook |
| /// (`hook/link.dart`) to inform the Dart and Flutter SDKs about the code assets |
| /// that need to be bundled with an application. |
| /// |
| /// A [CodeAsset] can be added to the [BuildOutputBuilder] in a build hook as |
| /// follows: |
| /// |
| /// <!-- file://./../example/api/code_assets_snippet.dart --> |
| /// ```dart |
| /// import 'package:code_assets/code_assets.dart'; |
| /// import 'package:hooks/hooks.dart'; |
| /// |
| /// void main(List<String> args) async { |
| /// await build(args, (input, output) async { |
| /// if (input.config.buildCodeAssets) { |
| /// final packageName = input.packageName; |
| /// final assetPathInPackage = input.packageRoot.resolve('...'); |
| /// final assetPathDownload = input.outputDirectoryShared.resolve('...'); |
| /// |
| /// output.assets.code.add( |
| /// CodeAsset( |
| /// package: packageName, |
| /// name: '...', |
| /// linkMode: DynamicLoadingBundled(), |
| /// file: assetPathInPackage, |
| /// ), |
| /// ); |
| /// } |
| /// }); |
| /// } |
| /// ``` |
| /// |
| /// When compiling C, C++ or Objective-C code from source, consider using |
| /// [`package:native_toolchain_c`](https://pub.dev/packages/native_toolchain_c) |
| /// with a build hook and a link hook. First, define the C library |
| /// specification in a shared file: |
| /// |
| /// <!-- file://./../example/sqlite/lib/src/c_library.dart --> |
| /// ```dart |
| /// import 'package:native_toolchain_c/native_toolchain_c.dart'; |
| /// |
| /// /// The C build specification for the sqlite library. |
| /// /// |
| /// /// It is used by the build and link hooks in the `hook/` directory. |
| /// final cLibrary = CLibrary( |
| /// name: 'sqlite3', |
| /// assetName: 'src/third_party/sqlite3.g.dart', |
| /// sources: ['third_party/sqlite/sqlite3.c'], |
| /// ); |
| /// ``` |
| /// |
| /// Next, compile the library in the build hook: |
| /// |
| /// <!-- file://./../example/sqlite/hook/build.dart --> |
| /// ```dart |
| /// import 'package:code_assets/code_assets.dart'; |
| /// import 'package:hooks/hooks.dart'; |
| /// import 'package:sqlite/src/c_library.dart'; |
| /// |
| /// void main(List<String> args) async { |
| /// await build(args, (input, output) async { |
| /// if (input.config.buildCodeAssets) { |
| /// await cLibrary.build( |
| /// input: input, |
| /// output: output, |
| /// defines: { |
| /// if (input.config.code.targetOS == OS.windows) |
| /// // Ensure symbols are exported in dll. |
| /// 'SQLITE_API': '__declspec(dllexport)', |
| /// }, |
| /// ); |
| /// } |
| /// }); |
| /// } |
| /// ``` |
| /// |
| /// Finally, tree-shake and link the library in the link hook: |
| /// |
| /// <!-- file://./../example/sqlite/hook/link.dart --> |
| /// ```dart |
| /// import 'package:hooks/hooks.dart'; |
| /// import 'package:native_toolchain_c/native_toolchain_c.dart'; |
| /// import 'package:record_use/record_use.dart'; |
| /// import 'package:sqlite/src/c_library.dart'; |
| /// import 'package:sqlite/src/third_party/record_use_mapping.dart'; |
| /// |
| /// void main(List<String> arguments) async { |
| /// await link(arguments, (input, output) async { |
| /// await cLibrary.link( |
| /// input: input, |
| /// output: output, |
| /// linkerOptions: LinkerOptions.treeshake( |
| /// symbolsToKeep: input.recordedUses?.calls.keys.cast<Method>().map( |
| /// (e) => recordUseMapping[e.name]!, |
| /// ), |
| /// ), |
| /// ); |
| /// }); |
| /// } |
| /// ``` |
| /// |
| /// See the full example in [example/sqlite/](../example/sqlite/). |
| /// |
| /// When interfacing with system libraries, the API in this package is enough: |
| /// |
| /// <!-- file://./../example/host_name/hook/build.dart --> |
| /// ```dart |
| /// import 'package:code_assets/code_assets.dart'; |
| /// import 'package:hooks/hooks.dart'; |
| /// |
| /// void main(List<String> args) async { |
| /// await build(args, (input, output) async { |
| /// if (input.config.buildCodeAssets) { |
| /// switch (input.config.code.targetOS) { |
| /// case OS.android || OS.iOS || OS.linux || OS.macOS: |
| /// output.assets.code.add( |
| /// CodeAsset( |
| /// package: 'host_name', |
| /// name: 'src/third_party/unix.dart', |
| /// linkMode: LookupInProcess(), |
| /// ), |
| /// ); |
| /// case OS.windows: |
| /// output.assets.code.add( |
| /// CodeAsset( |
| /// package: 'host_name', |
| /// name: 'src/third_party/windows.dart', |
| /// linkMode: DynamicLoadingSystem(Uri.file('ws2_32.dll')), |
| /// ), |
| /// ); |
| /// case final os: |
| /// throw UnsupportedError('Unsupported OS: ${os.name}.'); |
| /// } |
| /// } |
| /// }); |
| /// } |
| /// ``` |
| /// |
| /// The [CodeConfig] nested in the [HookInput] gives access to configuration |
| /// specifically for compiling code assets. For example [CodeConfig.targetOS] |
| /// and [CodeConfig.targetArchitecture] give access to the target OS and |
| /// architecture that the code assets are compiled for: |
| /// |
| /// <!-- file://./../example/api/code_config_snippet.dart --> |
| /// ```dart |
| /// import 'package:code_assets/code_assets.dart'; |
| /// import 'package:hooks/hooks.dart'; |
| /// |
| /// void main(List<String> args) async { |
| /// await build(args, (input, output) async { |
| /// if (input.config.buildCodeAssets) { |
| /// final codeConfig = input.config.code; |
| /// final targetOS = codeConfig.targetOS; |
| /// final targetArchitecture = codeConfig.targetArchitecture; |
| /// |
| /// // Add some code assets. |
| /// } |
| /// }); |
| /// } |
| /// ``` |
| /// |
| /// For more information about build and link hooks see |
| /// [dart.dev/tools/hooks](https://dart.dev/tools/hooks). |
| library; |
| |
| export 'src/code_assets/architecture.dart' show Architecture; |
| export 'src/code_assets/c_compiler_config.dart' |
| show CCompilerConfig, DeveloperCommandPrompt, WindowsCCompilerConfig; |
| export 'src/code_assets/code_asset.dart' |
| show CodeAsset, EncodedCodeAsset, OSLibraryNaming; |
| export 'src/code_assets/config.dart' |
| show |
| AndroidCodeConfig, |
| BuildOutputAssetsBuilderCode, |
| BuildOutputCodeAssetBuilder, |
| BuildOutputCodeAssets, |
| CodeConfig, |
| HookConfigCodeConfig, |
| IOSCodeConfig, |
| LinkInputCodeAssets, |
| LinkOutputAssetsBuilderCode, |
| LinkOutputCodeAssetBuilder, |
| LinkOutputCodeAssets, |
| MacOSCodeConfig; |
| export 'src/code_assets/extension.dart'; |
| export 'src/code_assets/ios_sdk.dart' show IOSSdk; |
| export 'src/code_assets/link_mode.dart' |
| show |
| DynamicLoadingBundled, |
| DynamicLoadingSystem, |
| LinkMode, |
| LookupInExecutable, |
| LookupInProcess, |
| StaticLinking; |
| export 'src/code_assets/link_mode_preference.dart' show LinkModePreference; |
| export 'src/code_assets/os.dart' show OS; |
| export 'src/code_assets/sanitizer.dart' show Sanitizer; |
| export 'src/code_assets/testing.dart' show testCodeBuildHook; |