blob: 7c7fab90d3810dc87daed2dd976f5121f422a5cb [file]
// 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;