Skip to content

Commit ef40a65

Browse files
committed
Revert "Remove resources from protocol"
This reverts commit d91a17a.
1 parent d91a17a commit ef40a65

File tree

11 files changed

+150
-12
lines changed

11 files changed

+150
-12
lines changed

pkgs/native_assets_builder/test_data/treeshaking_native_assets/hook/link.dart

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ const packageName = 'treeshaking_native_assets';
1010

1111
void main(List<String> arguments) async {
1212
await link(arguments, (config, output) async {
13-
final List<String>? usedSymbols = [];
13+
final usedSymbols = config.treeshakingInformation
14+
?.map((resource) => resource.metadata.toString());
1415
final dynamicLibrary = config.assets.firstWhere((asset) =>
1516
asset.id == 'package:$packageName/src/${packageName}_bindings.dart');
1617
final staticLibrary = config.assets

pkgs/native_assets_cli/example/link/package_with_assets/hook/link.dart

+6-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ import 'package:native_assets_cli/native_assets_cli.dart';
66

77
void main(List<String> args) async {
88
await link(args, (config, output) async {
9-
final dataAssets = config.assets.whereType<DataAsset>();
10-
output.addAssets(dataAssets);
9+
final assetsWithResource = config.assets.whereType<DataAsset>().where(
10+
(asset) =>
11+
config.treeshakingInformation
12+
?.any((resource) => resource.metadata == asset.name) ??
13+
true);
14+
output.addAssets(assetsWithResource);
1115
});
1216
}

pkgs/native_assets_cli/lib/native_assets_cli.dart

+1
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ export 'src/api/link.dart';
2828
export 'src/api/link_config.dart' show LinkConfig;
2929
export 'src/api/link_mode_preference.dart' show LinkModePreference;
3030
export 'src/api/os.dart' show OS;
31+
export 'src/api/resource.dart';

pkgs/native_assets_cli/lib/native_assets_cli_internal.dart

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export 'src/api/ios_sdk.dart' show IOSSdkImpl;
3636
export 'src/api/link_config.dart' show LinkConfigImpl;
3737
export 'src/api/link_mode_preference.dart' show LinkModePreferenceImpl;
3838
export 'src/api/os.dart' show OSImpl;
39+
export 'src/api/resource.dart';
3940
export 'src/model/dependencies.dart';
4041
export 'src/model/hook.dart';
4142
export 'src/model/metadata.dart';

pkgs/native_assets_cli/lib/src/api/link.dart

+10-3
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,22 @@ import 'link_config.dart';
1515
/// through [LinkConfig.assets]. They will only be bundled with the final
1616
/// application if included in the [LinkOutput].
1717
///
18+
/// As the linking runs after kernel compilation, you can use treeshaking
19+
/// information provided through [LinkConfig.treeshakingInformation] to decide
20+
/// which assets to include. The resources are only collected in AOT mode,
21+
/// therefore the field is null in JIT mode.
22+
///
1823
///
1924
/// ```dart
2025
/// import 'package:native_assets_cli/native_assets_cli.dart';
2126
///
2227
/// void main(List<String> args) async {
2328
/// await link(args, (config, output) async {
24-
/// final dataAssets = config.assets
25-
/// .whereType<DataAsset>();
26-
/// output.addAssets(dataAssets);
29+
/// final assetsWithResource = config.assets
30+
/// .whereType<DataAsset>()
31+
/// .where((asset) => config.resources
32+
/// .any((resource) => resource.metadata == asset.name));
33+
/// output.addAssets(assetsWithResource);
2734
/// });
2835
/// }
2936
/// ```

pkgs/native_assets_cli/lib/src/api/link_config.dart

+16-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import 'package:collection/collection.dart';
1010
import 'package:pub_semver/pub_semver.dart';
1111

1212
import '../model/hook.dart';
13+
import '../model/resource_identifiers.dart';
1314
import '../utils/map.dart';
1415
import 'architecture.dart';
1516
import 'asset.dart';
@@ -19,18 +20,28 @@ import 'hook_config.dart';
1920
import 'ios_sdk.dart';
2021
import 'link_mode_preference.dart';
2122
import 'os.dart';
23+
import 'resource.dart';
2224

2325
part '../model/link_config.dart';
2426

2527
/// The configuration for a link hook (`hook/link.dart`) invocation.
2628
///
2729
/// It consists of a subset of the fields from the [BuildConfig] already passed
28-
/// to the build hook and the [assets] from the build step.
30+
/// to the build hook, the [assets] from the build step, and the
31+
/// [treeshakingInformation] generated during the kernel compilation.
2932
abstract class LinkConfig implements HookConfig {
3033
/// The list of assets to be linked. These are the assets generated by a
3134
/// `build.dart` script destined for this packages `link.dart`.
3235
Iterable<Asset> get assets;
3336

37+
/// A collection of methods annotated with `@ResourceIdentifier`, which are
38+
/// called in the tree-shaken Dart code. This information can be used to
39+
/// dispose unused [assets].
40+
///
41+
/// This is `null` in JIT mode, where no resources are collected, or in a dry
42+
/// run.
43+
Iterable<Resource>? get treeshakingInformation;
44+
3445
/// Generate the [LinkConfig] from the input arguments to the linking script.
3546
factory LinkConfig.fromArguments(List<String> arguments) =>
3647
LinkConfigImpl.fromArguments(arguments);
@@ -47,12 +58,14 @@ abstract class LinkConfig implements HookConfig {
4758
List<String>? supportedAssetTypes,
4859
int? targetAndroidNdkApi,
4960
required Iterable<Asset> assets,
61+
Uri? resourceIdentifierUri,
5062
required LinkModePreference linkModePreference,
5163
bool? dryRun,
5264
Version? version,
5365
}) =>
5466
LinkConfigImpl(
5567
assets: assets.cast(),
68+
resourceIdentifierUri: resourceIdentifierUri,
5669
outputDirectory: outputDirectory,
5770
packageName: packageName,
5871
packageRoot: packageRoot,
@@ -75,11 +88,13 @@ abstract class LinkConfig implements HookConfig {
7588
required OS targetOS,
7689
List<String>? supportedAssetTypes,
7790
required Iterable<Asset> assets,
91+
Uri? resourceIdentifierUri,
7892
required LinkModePreference linkModePreference,
7993
Version? version,
8094
}) =>
8195
LinkConfigImpl.dryRun(
8296
assets: assets.cast(),
97+
resourceIdentifierUri: resourceIdentifierUri,
8398
outputDirectory: outputDirectory,
8499
packageName: packageName,
85100
packageRoot: packageRoot,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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+
/// Identifies a call site of a static method annotated with the
6+
/// `ResourceIdentifier` annotation. It consists of the [name] of the
7+
/// method, and the [metadata] used in the constructor of the annotation.
8+
///
9+
/// Example:
10+
/// ```dart
11+
/// @ResourceAnnotation('add_func')
12+
/// static external add(int i, int j);
13+
/// ```
14+
/// will result in the `Resource` object:
15+
/// ```dart
16+
/// Resource(name: 'add', metadata: 'add_func')
17+
/// ```
18+
///
19+
/// See also
20+
/// https://pub.dev/documentation/meta/latest/meta/ResourceIdentifier-class.html
21+
/// .
22+
class Resource {
23+
/// The name of the method which was called.
24+
final String name;
25+
26+
/// The metadata used in the annotation constructor on this method.
27+
final Object? metadata;
28+
29+
Resource({required this.name, required this.metadata});
30+
31+
@override
32+
bool operator ==(Object other) {
33+
if (identical(this, other)) return true;
34+
35+
return other is Resource &&
36+
other.name == name &&
37+
other.metadata == metadata;
38+
}
39+
40+
@override
41+
int get hashCode => name.hashCode ^ metadata.hashCode;
42+
43+
@override
44+
String toString() => 'Resource(name: $name, metadata: $metadata)';
45+
}

pkgs/native_assets_cli/lib/src/model/link_config.dart

+23-4
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,16 @@
44

55
part of '../api/link_config.dart';
66

7+
List<Resource>? fromIdentifiers(ResourceIdentifiers resourceIdentifiers) =>
8+
resourceIdentifiers.identifiers
9+
.map((e) => Resource(name: e.name, metadata: e.id))
10+
.toList();
11+
712
/// The input to the linking script.
813
///
9-
/// It consists of the fields inherited from the [HookConfig] and the [assets]
10-
/// from the build step.
14+
/// It consists of the fields inherited from the [HookConfig], the [assets] from
15+
/// the build step, and the [treeshakingInformation] generated during the kernel
16+
/// compilation.
1117
class LinkConfigImpl extends HookConfigImpl implements LinkConfig {
1218
static const resourceIdentifierKey = 'resource_identifiers';
1319

@@ -16,8 +22,17 @@ class LinkConfigImpl extends HookConfigImpl implements LinkConfig {
1622
@override
1723
final Iterable<AssetImpl> assets;
1824

19-
// TODO: Placeholder for the resources.json file URL. We don't want to change
20-
// native_assets_builder when implementing the parsing.
25+
Iterable<Resource>? _treeshakingInformation;
26+
27+
@override
28+
Iterable<Resource>? get treeshakingInformation {
29+
if (_resourceIdentifierUri != null && _treeshakingInformation == null) {
30+
_treeshakingInformation = fromIdentifiers(
31+
ResourceIdentifiers.fromFile(_resourceIdentifierUri.toFilePath()));
32+
}
33+
return _treeshakingInformation;
34+
}
35+
2136
final Uri? _resourceIdentifierUri;
2237

2338
LinkConfigImpl({
@@ -54,6 +69,10 @@ class LinkConfigImpl extends HookConfigImpl implements LinkConfig {
5469
required super.linkModePreference,
5570
required super.targetOS,
5671
}) : _resourceIdentifierUri = resourceIdentifierUri,
72+
_treeshakingInformation = resourceIdentifierUri != null
73+
? fromIdentifiers(ResourceIdentifiers.fromFile(
74+
resourceIdentifierUri.toFilePath()))
75+
: null,
5776
super.dryRun(
5877
hook: Hook.link,
5978
version: version ?? HookConfigImpl.latestVersion,

pkgs/native_assets_cli/test/api/resource_data.dart

+6
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,14 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'package:native_assets_cli/src/api/resource.dart';
56
import 'package:native_assets_cli/src/model/resource_identifiers.dart';
67

8+
final resourceList = [
9+
Resource(name: 'methodName1', metadata: 'someMetadata'),
10+
Resource(name: 'methodName2', metadata: 'someOtherMetadata'),
11+
];
12+
713
const resourceFile = '''{
814
"_comment": "Resources referenced by annotated resource identifiers",
915
"AppTag": "TBD",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
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+
import 'package:native_assets_cli/src/api/link_config.dart';
6+
import 'package:test/test.dart';
7+
8+
import 'resource_data.dart';
9+
10+
void main() {
11+
test('Parse resource identifiers', () {
12+
expect(fromIdentifiers(resourceIdentifiers), resourceList);
13+
});
14+
}

pkgs/native_assets_cli/test/model/link_config_test.dart

+26-1
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'dart:convert';
56
import 'dart:io';
67

78
import 'package:native_assets_cli/native_assets_cli.dart';
89
import 'package:native_assets_cli/native_assets_cli_internal.dart';
910
import 'package:native_assets_cli/src/api/asset.dart';
1011
import 'package:test/test.dart';
1112

13+
import '../api/resource_data.dart';
14+
1215
void main() async {
1316
late Uri tempUri;
1417
late Uri outDirUri;
@@ -56,7 +59,8 @@ void main() async {
5659
fakeVcVars = tempUri.resolve('vcvarsall.bat');
5760
await File.fromUri(fakeVcVars).create();
5861
resources = tempUri.resolve('resources.json');
59-
File.fromUri(resources).createSync();
62+
final file = File.fromUri(resources)..createSync();
63+
file.writeAsStringSync(jsonEncode(resourceIdentifiers));
6064
});
6165

6266
tearDown(() async {
@@ -111,6 +115,8 @@ void main() async {
111115
true);
112116
expect(config1.cCompiler != config2.cCompiler, true);
113117
expect(config1.assets != config2.assets, true);
118+
expect(
119+
config1.treeshakingInformation != config2.treeshakingInformation, true);
114120
});
115121

116122
test('LinkConfig fromConfig', () {
@@ -190,6 +196,25 @@ void main() async {
190196
final fromConfig = LinkConfigImpl.fromJson(configFile);
191197
expect(fromConfig, equals(buildConfig1));
192198
});
199+
test('LinkConfig fetch treeshaking information', () {
200+
final buildConfig1 = LinkConfigImpl(
201+
outputDirectory: outDirUri,
202+
packageName: packageName,
203+
packageRoot: packageRootUri,
204+
targetArchitecture: ArchitectureImpl.arm64,
205+
targetOS: OSImpl.iOS,
206+
targetIOSSdk: IOSSdkImpl.iPhoneOS,
207+
cCompiler: CCompilerConfigImpl(
208+
compiler: fakeClang,
209+
linker: fakeLd,
210+
),
211+
buildMode: BuildModeImpl.release,
212+
assets: assets,
213+
resourceIdentifierUri: resources,
214+
linkModePreference: LinkModePreferenceImpl.preferStatic,
215+
);
216+
expect(buildConfig1.treeshakingInformation, resourceList);
217+
});
193218

194219
test('LinkConfig toJson fromJson', () {
195220
final outDir = outDirUri;

0 commit comments

Comments
 (0)