Skip to content

Commit 8a1f836

Browse files
authored
[native_assets_cli] Unify Metadata with Assets (#2164)
1 parent 481af77 commit 8a1f836

File tree

50 files changed

+814
-144
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+814
-144
lines changed

.github/workflows/native.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,12 @@ jobs:
108108
- run: dart pub get -C test_data/native_dynamic_linking/
109109
if: ${{ matrix.package == 'native_assets_builder' }}
110110

111+
- run: dart pub get -C test_data/reusable_dynamic_library/
112+
if: ${{ matrix.package == 'native_assets_builder' }}
113+
114+
- run: dart pub get -C test_data/reuse_dynamic_library/
115+
if: ${{ matrix.package == 'native_assets_builder' }}
116+
111117
- run: dart pub get -C test_data/no_hook/
112118
if: ${{ matrix.package == 'native_assets_builder' }}
113119

pkgs/native_assets_builder/CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
## 0.13.1-wip
1+
## 0.14.0-wip
22

3-
- Nothing yet.
3+
- Bump `package:native_assets_cli` to 0.14.0.
4+
- Route assets from build hook to build hook with `ToBuild` `Routing`.
45

56
## 0.13.0
67

pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,22 +91,33 @@ class NativeAssetsBuildRunner {
9191
if (buildPlan == null) return null;
9292

9393
var hookResult = HookResult();
94+
95+
/// Key is packageName.
9496
final globalMetadata = <String, Metadata>{};
97+
98+
/// Key is packageName.
99+
final globalAssetsForBuild = <String, List<EncodedAsset>>{};
95100
for (final package in buildPlan) {
96-
final metadata = <String, Metadata>{};
97-
_metadataForPackage(
98-
packageGraph: packageGraph!,
101+
final metadata =
102+
_metadataForPackage(
103+
packageGraph: packageGraph!,
104+
packageName: package.name,
105+
targetMetadata: globalMetadata,
106+
) ??
107+
{};
108+
final assetsForBuild = _assetsForBuildForPackage(
109+
packageGraph: packageGraph,
99110
packageName: package.name,
100-
targetMetadata: globalMetadata,
101-
)?.forEach((key, value) => metadata[key] = value);
111+
globalAssetsForBuild: globalAssetsForBuild,
112+
);
102113

103114
final inputBuilder = BuildInputBuilder();
104115

105116
for (final e in extensions) {
106117
e.setupBuildInput(inputBuilder);
107118
}
108119
inputBuilder.config.setupBuild(linkingEnabled: linkingEnabled);
109-
inputBuilder.setupBuildInput(metadata: metadata);
120+
inputBuilder.setupBuildInput(metadata: metadata, assets: assetsForBuild);
110121

111122
final (buildDirUri, outDirUri, outDirSharedUri) = await _setupDirectories(
112123
Hook.build,
@@ -152,6 +163,8 @@ class NativeAssetsBuildRunner {
152163
final (hookOutput, hookDeps) = result;
153164
hookResult = hookResult.copyAdd(hookOutput, hookDeps);
154165
globalMetadata[package.name] = (hookOutput as BuildOutput).metadata;
166+
globalAssetsForBuild[package.name] =
167+
hookOutput.assets.encodedAssetsForBuild;
155168
}
156169

157170
// We only perform application wide validation in the final result of
@@ -732,6 +745,23 @@ ${compileResult.stdout}
732745
};
733746
}
734747

748+
/// Returns only the assets output as assetForBuild by the packages that are
749+
/// the direct dependencies of [packageName].
750+
Map<String, List<EncodedAsset>>? _assetsForBuildForPackage({
751+
required PackageGraph packageGraph,
752+
required String packageName,
753+
Map<String, List<EncodedAsset>>? globalAssetsForBuild,
754+
}) {
755+
if (globalAssetsForBuild == null) {
756+
return null;
757+
}
758+
final dependencies = packageGraph.neighborsOf(packageName).toSet();
759+
return {
760+
for (final entry in globalAssetsForBuild.entries)
761+
if (dependencies.contains(entry.key)) entry.key: entry.value,
762+
};
763+
}
764+
735765
Future<ValidationErrors> _validate(
736766
HookInput input,
737767
HookOutput output,

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 build hooks.
4-
version: 0.13.1-wip
4+
version: 0.14.0-wip
55
repository: https://github.com/dart-lang/native/tree/main/pkgs/native_assets_builder
66

77
publish_to: none
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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+
@OnPlatform({'mac-os': Timeout.factor(2), 'windows': Timeout.factor(10)})
6+
library;
7+
8+
import 'package:test/test.dart';
9+
10+
import '../build_runner/helpers.dart';
11+
import '../helpers.dart';
12+
13+
void main() async {
14+
const name = 'reuse_dynamic_library';
15+
16+
test(
17+
'$name build',
18+
() => inTempDir((tempUri) async {
19+
await copyTestProjects(targetUri: tempUri);
20+
final packageUri = tempUri.resolve('$name/');
21+
22+
await runPubGet(workingDirectory: packageUri, logger: logger);
23+
24+
final logMessages = <String>[];
25+
final result =
26+
(await build(
27+
packageUri,
28+
logger,
29+
dartExecutable,
30+
capturedLogs: logMessages,
31+
buildAssetTypes: [BuildAssetType.code],
32+
))!;
33+
34+
expect(result.encodedAssets.length, 2);
35+
}),
36+
);
37+
}

pkgs/native_assets_builder/test_data/add_asset_link/hook/build.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ void main(List<String> arguments) async {
2626
input: input,
2727
output: output,
2828
logger: logger,
29-
linkInPackage: 'add_asset_link',
29+
routing: const [ToLinkHook('add_asset_link')],
3030
);
3131
});
3232
}

pkgs/native_assets_builder/test_data/complex_link/hook/build.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ void main(List<String> args) async {
2727

2828
output.assets.data.add(
2929
DataAsset(package: packageName, name: name, file: dataAsset.uri),
30-
linkInPackage: input.config.linkingEnabled ? packageName : null,
30+
routing:
31+
input.config.linkingEnabled
32+
? ToLinkHook(packageName)
33+
: const ToAppBundle(),
3134
);
3235
// TODO(https://github.com/dart-lang/native/issues/1208): Report
3336
// dependency on asset.

pkgs/native_assets_builder/test_data/complex_link_helper/hook/build.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@ void main(List<String> args) async {
2828
final forLinking = name.contains('2') || name.contains('3');
2929
output.assets.data.add(
3030
DataAsset(package: packageName, name: name, file: dataAsset.uri),
31-
linkInPackage:
32-
forLinking && input.config.linkingEnabled ? 'complex_link' : null,
31+
routing:
32+
forLinking && input.config.linkingEnabled
33+
? const ToLinkHook('complex_link')
34+
: const ToAppBundle(),
3335
);
3436
// TODO(https://github.com/dart-lang/native/issues/1208): Report
3537
// dependency on asset.

pkgs/native_assets_builder/test_data/drop_dylib_link/hook/build.dart

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,22 @@ void main(List<String> arguments) async {
1414
..onRecord.listen((record) {
1515
print('${record.level.name}: ${record.time}: ${record.message}');
1616
});
17-
final linkInPackage =
18-
input.config.linkingEnabled ? input.packageName : null;
17+
final routing =
18+
input.config.linkingEnabled
19+
? [ToLinkHook(input.packageName)]
20+
: [const ToAppBundle()];
1921
await CBuilder.library(
2022
name: 'add',
2123
assetName: 'dylib_add',
2224
sources: ['src/native_add.c'],
2325
linkModePreference: LinkModePreference.dynamic,
24-
).run(
25-
input: input,
26-
output: output,
27-
logger: logger,
28-
linkInPackage: linkInPackage,
29-
);
26+
).run(input: input, output: output, logger: logger, routing: routing);
3027

3128
await CBuilder.library(
3229
name: 'multiply',
3330
assetName: 'dylib_multiply',
3431
sources: ['src/native_multiply.c'],
3532
linkModePreference: LinkModePreference.dynamic,
36-
).run(
37-
input: input,
38-
output: output,
39-
logger: logger,
40-
linkInPackage: linkInPackage,
41-
);
33+
).run(input: input, output: output, logger: logger, routing: routing);
4234
});
4335
}

pkgs/native_assets_builder/test_data/fail_on_os_sdk_version_link/hook/build.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ void main(List<String> arguments) async {
1212
file: input.packageRoot.resolve('assets/data.json'),
1313
package: input.packageName,
1414
),
15-
linkInPackage:
16-
input.config.linkingEnabled ? 'fail_on_os_sdk_version_linker' : null,
15+
routing:
16+
input.config.linkingEnabled
17+
? const ToLinkHook('fail_on_os_sdk_version_linker')
18+
: const ToAppBundle(),
1719
);
1820
});
1921
}

pkgs/native_assets_builder/test_data/manifest.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,21 @@
112112
- relative_path/assets/test_asset.txt
113113
- relative_path/hook/build.dart
114114
- relative_path/pubspec.yaml
115+
- reusable_dynamic_library/ffigen.yaml
116+
- reusable_dynamic_library/hook/build.dart
117+
- reusable_dynamic_library/lib/add.dart
118+
- reusable_dynamic_library/lib/hook.dart
119+
- reusable_dynamic_library/pubspec.yaml
120+
- reusable_dynamic_library/src/add.c
121+
- reusable_dynamic_library/src/add.h
122+
- reusable_dynamic_library/test/add_test.dart
123+
- reuse_dynamic_library/ffigen.yaml
124+
- reuse_dynamic_library/hook/build.dart
125+
- reuse_dynamic_library/lib/my_add.dart
126+
- reuse_dynamic_library/pubspec.yaml
127+
- reuse_dynamic_library/src/my_add.c
128+
- reuse_dynamic_library/src/my_add.h
129+
- reuse_dynamic_library/test/add_test.dart
115130
- simple_data_asset/assets/test_asset.txt
116131
- simple_data_asset/bin/deep_modify_data_asset.dart.debug
117132
- simple_data_asset/bin/modify_data_asset.dart.debug

pkgs/native_assets_builder/test_data/native_add_duplicate/hook/build.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ void main(List<String> arguments) async {
3232
output.assets.code.add(
3333
tempBuildOutput.assets.code.single,
3434
// Send dylib to linking if linking is enabled.
35-
linkInPackage: input.config.linkingEnabled ? packageName : null,
35+
routing:
36+
input.config.linkingEnabled
37+
? ToLinkHook(packageName)
38+
: const ToAppBundle(),
3639
);
3740
output.addDependencies(tempBuildOutput.dependencies);
3841
});

pkgs/native_assets_builder/test_data/package_reading_metadata/hook/build.dart

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,21 @@
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-
// ignore_for_file: deprecated_member_use
6-
75
import 'package:native_assets_cli/native_assets_cli.dart';
86

97
void main(List<String> args) async {
108
await build(args, (input, _) async {
11-
final someValue = input.metadatum('package_with_metadata', 'some_key');
9+
final someValue = input.metadata['package_with_metadata']['some_key'];
1210
assert(someValue != null);
13-
final someInt = input.metadatum('package_with_metadata', 'some_int');
11+
final someInt = input.metadata['package_with_metadata']['some_int'];
1412
assert(someInt != null);
1513
print({'some_int': someInt, 'some_key': someValue});
14+
15+
// ignore: deprecated_member_use
16+
final someValueOld = input.metadatum('package_with_metadata', 'some_key');
17+
assert(someValueOld != null);
18+
// ignore: deprecated_member_use
19+
final someIntOld = input.metadatum('package_with_metadata', 'some_int');
20+
assert(someIntOld != null);
1621
});
1722
}

pkgs/native_assets_builder/test_data/package_with_metadata/hook/build.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:native_assets_cli/native_assets_cli.dart';
66

77
void main(List<String> arguments) async {
88
await build(arguments, (input, output) async {
9+
output.metadata.addAll({'some_key': 'some_value', 'some_int': 3});
910
// ignore: deprecated_member_use
1011
output.addMetadata({'some_key': 'some_value', 'some_int': 3});
1112
});
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
An example of a package with a dynamic library that can be linked against in
2+
a dependent package.
3+
4+
## Usage
5+
6+
Run tests with `dart --enable-experiment=native-assets test`.
7+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Run with `flutter pub run ffigen --config ffigen.yaml`.
2+
name: AddBindings
3+
description: |
4+
Bindings for `src/add.h`.
5+
6+
Regenerate bindings with `flutter pub run ffigen --config ffigen.yaml`.
7+
output: 'lib/add.dart'
8+
headers:
9+
entry-points:
10+
- 'src/add.h'
11+
include-directives:
12+
- 'src/add.h'
13+
preamble: |
14+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
15+
// for details. All rights reserved. Use of this source code is governed by a
16+
// BSD-style license that can be found in the LICENSE file.
17+
comments:
18+
style: any
19+
length: full
20+
ffi-native:
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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:logging/logging.dart';
6+
import 'package:native_assets_cli/native_assets_cli.dart';
7+
import 'package:native_toolchain_c/native_toolchain_c.dart';
8+
9+
void main(List<String> args) async {
10+
await build(args, (input, output) async {
11+
final logger =
12+
Logger('')
13+
..level = Level.ALL
14+
..onRecord.listen((record) => print(record.message));
15+
16+
final builder = CBuilder.library(
17+
name: 'add',
18+
assetName: 'add.dart',
19+
sources: ['src/add.c'],
20+
buildMode: BuildMode.debug,
21+
);
22+
23+
await builder.run(
24+
input: input,
25+
output: output,
26+
logger: logger,
27+
routing: const [
28+
// Bundle the dylib in the app, someone might use it.
29+
ToAppBundle(),
30+
// Enable other packages to link to the dylib.
31+
ToBuildHooks(),
32+
],
33+
);
34+
35+
// Enable other packages to find the headers.
36+
output.metadata['include'] = input.packageRoot.resolve('src/').toFilePath();
37+
});
38+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright (c) 2025, 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+
// AUTO GENERATED FILE, DO NOT EDIT.
6+
//
7+
// Generated by `package:ffigen`.
8+
// ignore_for_file: type=lint
9+
import 'dart:ffi' as ffi;
10+
11+
@ffi.Native<ffi.Int32 Function(ffi.Int32, ffi.Int32)>(symbol: 'add')
12+
external int add(int a, int b);

0 commit comments

Comments
 (0)