Skip to content

Commit 0901a33

Browse files
authored
[native_assets_builder] Separate KernelAssets from Assets (#964)
There are multiple differences between the `native_assets.yaml` that is embedded in the kernel file and the `build_output.yaml -> assets`. * Based on the discussions on #955 and #946, it is clear that the `path` for assets should be in `Asset`, not in `AssetPath` for the file-path the asset has after the `build.dart` run. When the embedders (Flutter/Dart) embed the native assets mapping then the `path`s start representing the path on the system where the Dart/Flutter app is running. This should be embedded in the path-type there. * The kernel info does not contain link mode (currently), as static linking is not supported. It's not clear that if we support static linking whether any information should be embedded in the kernel info at all. * The native_assets.yaml for the kernel file is laid out for easy lookup at runtime (keyed on Target). * We want to change the `Asset`s to output OS and Architecture instead of Target. Therefore we should not share the data structure between `Asset`s and `KernelAsset`s (new name for the entries that are embedded via native_assets.yaml in a kernel file.) This means that `dartdev` and `flutter_tools` will have to start converting `Asset`s to `KernelAsset`s when making the `native_assets.yaml` file. Therefore this is a breaking change and will have to be rolled into Dart and flutter/flutter manually.
1 parent b1a0c2a commit 0901a33

File tree

6 files changed

+165
-111
lines changed

6 files changed

+165
-111
lines changed

pkgs/native_assets_builder/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
## 0.3.3-wip
1+
## 0.4.0-wip
22

3+
- **Breaking change**: Split out the `KernelAsset`s from normal `Asset`s.
34
- Bump `package:native_assets_cli` to path dependency.
45

56
## 0.3.2

pkgs/native_assets_builder/lib/native_assets_builder.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
export 'package:native_assets_builder/src/build_runner/build_runner.dart';
6-
export 'package:native_assets_builder/src/model/asset.dart';
6+
export 'package:native_assets_builder/src/model/kernel_assets.dart';
77
export 'package:native_assets_builder/src/package_layout/package_layout.dart';

pkgs/native_assets_builder/lib/src/model/asset.dart

Lines changed: 0 additions & 73 deletions
This file was deleted.
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// Library defining the `native_assets.yaml` format for embedding in a Dart
6+
/// kernel file.
7+
///
8+
/// The `native_assets.yaml` embedded in a kernel file has a different format
9+
/// from the assets passed in the `build_output.yaml` from individual native
10+
/// assets builds. This library defines the format of the former so that it
11+
/// can be reused in `package:dartdev` and `package:flutter_tools`.
12+
///
13+
/// The format should be consistent with `pkg/vm/lib/native_assets/` in the
14+
/// Dart SDK.
15+
library kernel_native_assets;
16+
17+
import 'package:native_assets_cli/native_assets_cli_internal.dart';
18+
19+
import '../utils/yaml.dart';
20+
21+
class KernelAssets {
22+
final List<KernelAsset> assets;
23+
24+
KernelAssets(this.assets);
25+
26+
String toNativeAssetsFile() {
27+
final assetsPerTarget = <Target, List<KernelAsset>>{};
28+
for (final asset in assets) {
29+
final assets = assetsPerTarget[asset.target] ?? [];
30+
assets.add(asset);
31+
assetsPerTarget[asset.target] = assets;
32+
}
33+
34+
final yamlContents = {
35+
'format-version': [1, 0, 0],
36+
'native-assets': {
37+
for (final entry in assetsPerTarget.entries)
38+
entry.key.toString(): {
39+
for (final e in entry.value) e.id: e.path.toYaml(),
40+
}
41+
},
42+
};
43+
44+
return yamlEncode(yamlContents);
45+
}
46+
}
47+
48+
class KernelAsset {
49+
final String id;
50+
final Target target;
51+
final KernelAssetPath path;
52+
53+
KernelAsset({
54+
required this.id,
55+
required this.target,
56+
required this.path,
57+
});
58+
}
59+
60+
abstract class KernelAssetPath {
61+
List<String> toYaml();
62+
}
63+
64+
/// Asset at absolute path [uri] on the target device where Dart is run.
65+
class KernelAssetAbsolutePath implements KernelAssetPath {
66+
final Uri uri;
67+
68+
KernelAssetAbsolutePath(this.uri);
69+
70+
static const _pathTypeValue = 'absolute';
71+
72+
@override
73+
List<String> toYaml() => [_pathTypeValue, uri.toFilePath()];
74+
}
75+
76+
/// Asset at relative path [uri], relative to the 'dart file' executed.
77+
///
78+
/// The 'dart file' executed can be one of the following:
79+
///
80+
/// 1. The `.dart` file when executing `dart path/to/script.dart`.
81+
/// 2. The `.kernel` file when executing from a kernel file.
82+
/// 3. The `.aotsnapshot` file when executing from an AOT snapshot with the Dart
83+
/// AOT runtime.
84+
/// 4. The executable when executing a Dart app compiled with `dart compile exe`
85+
/// to a single file.
86+
///
87+
/// Note when writing your own embedder, make sure the `Dart_CreateIsolateGroup`
88+
/// or similar calls set up the `script_uri` parameter correctly to ensure
89+
/// relative path resolution works.
90+
class KernelAssetRelativePath implements KernelAssetPath {
91+
final Uri uri;
92+
93+
KernelAssetRelativePath(this.uri);
94+
95+
static const _pathTypeValue = 'relative';
96+
97+
@override
98+
List<String> toYaml() => [_pathTypeValue, uri.toFilePath()];
99+
}
100+
101+
/// Asset is avaliable on the system `PATH`.
102+
///
103+
/// [uri] only contains a file name.
104+
class KernelAssetSystemPath implements KernelAssetPath {
105+
final Uri uri;
106+
107+
KernelAssetSystemPath(this.uri);
108+
109+
static const _pathTypeValue = 'system';
110+
111+
@override
112+
List<String> toYaml() => [_pathTypeValue, uri.toFilePath()];
113+
}
114+
115+
/// Asset is loaded in the process and symbols are available through
116+
/// `DynamicLibrary.process()`.
117+
class KernelAssetInProcess implements KernelAssetPath {
118+
KernelAssetInProcess._();
119+
120+
static final KernelAssetInProcess _singleton = KernelAssetInProcess._();
121+
122+
factory KernelAssetInProcess() => _singleton;
123+
124+
static const _pathTypeValue = 'process';
125+
126+
@override
127+
List<String> toYaml() => [_pathTypeValue];
128+
}
129+
130+
/// Asset is embedded in executable and symbols are available through
131+
/// `DynamicLibrary.executable()`.
132+
class KernelAssetInExecutable implements KernelAssetPath {
133+
KernelAssetInExecutable._();
134+
135+
static final KernelAssetInExecutable _singleton = KernelAssetInExecutable._();
136+
137+
factory KernelAssetInExecutable() => _singleton;
138+
139+
static const _pathTypeValue = 'executable';
140+
141+
@override
142+
List<String> toYaml() => [_pathTypeValue];
143+
}

pkgs/native_assets_builder/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: native_assets_builder
22
description: >-
33
This package is the backend that invokes top-level `build.dart` scripts.
4-
version: 0.3.3-wip
4+
version: 0.4.0-wip
55
repository: https://github.com/dart-lang/native/tree/main/pkgs/native_assets_builder
66

77
environment:

pkgs/native_assets_builder/test/model/asset_test.dart renamed to pkgs/native_assets_builder/test/model/kernel_assets_test.dart

Lines changed: 18 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@
44

55
// ignore_for_file: undefined_hidden_name
66

7-
import 'package:native_assets_builder/src/model/asset.dart';
8-
import 'package:native_assets_cli/native_assets_cli_internal.dart'
9-
hide AssetIterable, AssetRelativePath;
7+
import 'package:native_assets_builder/src/model/kernel_assets.dart';
8+
import 'package:native_assets_cli/native_assets_cli_internal.dart';
109
import 'package:test/test.dart';
1110

1211
void main() {
@@ -15,50 +14,43 @@ void main() {
1514
final foo3Uri = Uri(path: 'libfoo3.so');
1615
final barUri = Uri(path: 'path/to/libbar.a');
1716
final blaUri = Uri(path: 'path/with spaces/bla.dll');
18-
final assets = [
19-
Asset(
17+
final assets = KernelAssets([
18+
KernelAsset(
2019
id: 'foo',
21-
path: AssetAbsolutePath(fooUri),
20+
path: KernelAssetAbsolutePath(fooUri),
2221
target: Target.androidX64,
23-
linkMode: LinkMode.dynamic,
2422
),
25-
Asset(
23+
KernelAsset(
2624
id: 'foo2',
27-
path: AssetRelativePath(foo2Uri),
25+
path: KernelAssetRelativePath(foo2Uri),
2826
target: Target.androidX64,
29-
linkMode: LinkMode.dynamic,
3027
),
31-
Asset(
28+
KernelAsset(
3229
id: 'foo3',
33-
path: AssetSystemPath(foo3Uri),
30+
path: KernelAssetSystemPath(foo3Uri),
3431
target: Target.androidX64,
35-
linkMode: LinkMode.dynamic,
3632
),
37-
Asset(
33+
KernelAsset(
3834
id: 'foo4',
39-
path: AssetInExecutable(),
35+
path: KernelAssetInExecutable(),
4036
target: Target.androidX64,
41-
linkMode: LinkMode.dynamic,
4237
),
43-
Asset(
38+
KernelAsset(
4439
id: 'foo5',
45-
path: AssetInProcess(),
40+
path: KernelAssetInProcess(),
4641
target: Target.androidX64,
47-
linkMode: LinkMode.dynamic,
4842
),
49-
Asset(
43+
KernelAsset(
5044
id: 'bar',
51-
path: AssetAbsolutePath(barUri),
45+
path: KernelAssetAbsolutePath(barUri),
5246
target: Target.linuxArm64,
53-
linkMode: LinkMode.static,
5447
),
55-
Asset(
48+
KernelAsset(
5649
id: 'bla',
57-
path: AssetAbsolutePath(blaUri),
50+
path: KernelAssetAbsolutePath(blaUri),
5851
target: Target.windowsX64,
59-
linkMode: LinkMode.dynamic,
6052
),
61-
];
53+
]);
6254

6355
final assetsDartEncoding = '''format-version:
6456
- 1
@@ -92,13 +84,4 @@ native-assets:
9284
final fileContents = assets.toNativeAssetsFile();
9385
expect(fileContents, assetsDartEncoding);
9486
});
95-
96-
test('List<Asset> whereLinkMode', () async {
97-
final assets2 = assets.whereLinkMode(LinkMode.dynamic);
98-
expect(assets2.length, 6);
99-
});
100-
101-
test('satisfy coverage', () async {
102-
expect(() => assets[1].toYaml(), throwsUnimplementedError);
103-
});
10487
}

0 commit comments

Comments
 (0)