blob: d5d8df291127d3a8cdc442ae94ceeea3e74f910e [file] [log] [blame]
// 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.
/// Library defining the `native_assets.yaml` format for embedding in a Dart
/// kernel file.
///
/// The `native_assets.yaml` embedded in a kernel file has a different format
/// from the assets passed in the `build_output.json` from individual native
/// assets builds. This library defines the format of the former so that it
/// can be reused in `package:dartdev` and `package:flutter_tools`.
///
/// The format should be consistent with `pkg/vm/lib/native_assets/` in the
/// Dart SDK.
library;
import 'dart:convert';
import 'target.dart';
class KernelAssets {
final List<KernelAsset> _assets;
KernelAssets([Iterable<KernelAsset>? assets]) : _assets = [...?assets];
String toNativeAssetsFile() {
final assetsPerTarget = <Target, List<KernelAsset>>{};
for (final asset in _assets) {
final assets = assetsPerTarget[asset.target] ?? [];
assets.add(asset);
assetsPerTarget[asset.target] = assets;
}
final jsonContents = {
'format-version': [1, 0, 0],
'native-assets': {
for (final entry in assetsPerTarget.entries)
entry.key.toString(): {
for (final e in entry.value) e.id: e.path.toJson(),
},
},
};
return const JsonEncoder.withIndent(' ').convert(jsonContents);
}
}
class KernelAsset {
final String id;
final Target target;
final KernelAssetPath path;
KernelAsset({required this.id, required this.target, required this.path});
}
abstract class KernelAssetPath {
List<String> toJson();
}
/// Asset at absolute path [uri] on the target device where Dart is run.
class KernelAssetAbsolutePath implements KernelAssetPath {
final Uri uri;
KernelAssetAbsolutePath(this.uri);
static const _pathTypeValue = 'absolute';
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is KernelAssetAbsolutePath && other.uri == uri);
@override
int get hashCode => uri.hashCode;
@override
List<String> toJson() => [_pathTypeValue, uri.toFilePath()];
}
/// Asset at relative path [uri], relative to the 'dart file' executed.
///
/// The 'dart file' executed can be one of the following:
///
/// 1. The `.dart` file when executing `dart path/to/script.dart`.
/// 2. The `.kernel` file when executing from a kernel file.
/// 3. The `.aotsnapshot` file when executing from an AOT snapshot with the Dart
/// AOT runtime.
/// 4. The executable when executing a Dart app compiled with `dart compile exe`
/// to a single file.
///
/// Note when writing your own embedder, make sure the `Dart_CreateIsolateGroup`
/// or similar calls set up the `script_uri` parameter correctly to ensure
/// relative path resolution works.
class KernelAssetRelativePath implements KernelAssetPath {
final Uri uri;
KernelAssetRelativePath(this.uri);
static const _pathTypeValue = 'relative';
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is KernelAssetRelativePath && other.uri == uri);
@override
int get hashCode => uri.hashCode;
@override
List<String> toJson() => [_pathTypeValue, uri.toFilePath()];
}
/// Asset is available on the system `PATH`.
///
/// [uri] only contains a file name.
class KernelAssetSystemPath implements KernelAssetPath {
final Uri uri;
KernelAssetSystemPath(this.uri);
static const _pathTypeValue = 'system';
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is KernelAssetSystemPath && other.uri == uri);
@override
int get hashCode => uri.hashCode;
@override
String toString() => 'KernelAssetAbsolutePath($uri)';
@override
List<String> toJson() => [_pathTypeValue, uri.toFilePath()];
}
/// Asset is loaded in the process and symbols are available through
/// `DynamicLibrary.process()`.
class KernelAssetInProcess implements KernelAssetPath {
KernelAssetInProcess._();
static final KernelAssetInProcess _singleton = KernelAssetInProcess._();
factory KernelAssetInProcess() => _singleton;
static const _pathTypeValue = 'process';
@override
List<String> toJson() => [_pathTypeValue];
}
/// Asset is embedded in executable and symbols are available through
/// `DynamicLibrary.executable()`.
class KernelAssetInExecutable implements KernelAssetPath {
KernelAssetInExecutable._();
static final KernelAssetInExecutable _singleton = KernelAssetInExecutable._();
factory KernelAssetInExecutable() => _singleton;
static const _pathTypeValue = 'executable';
@override
List<String> toJson() => [_pathTypeValue];
}