Skip to content

Commit c940ac8

Browse files
authored
[native_assets_builder] return build dependencies (#107)
Closes: #105 Added expectations to the existing tests for: (1) normal build, (2) cached build, and (3) build after a failing build. This change breaks the programmatic API, so (1) I've bumped the version to 0.2.0, and (2) will roll this into the Dart SDK manually. (To minimize rolling, we might as well address #106 as well right after.)
1 parent 63daab8 commit c940ac8

File tree

18 files changed

+211
-102
lines changed

18 files changed

+211
-102
lines changed

pkgs/native_assets_builder/CHANGELOG.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
## 0.1.1-wip
1+
## 0.2.0-wip
22

3+
- **Breaking change** `NativeAssetsBuildRunner`s method now return an object
4+
([#105](https://github.com/dart-lang/native/issues/105)).
35
- Use an `out/` sub directory for building native assets
46
([#98](https://github.com/dart-lang/native/issues/98)).
57
- Check asset ids on having having a package uri with the owning package
68
([#96](https://github.com/dart-lang/native/issues/96)).
7-
- `NativeAssetsBuildRunner` can now support multiple calls
9+
- `NativeAssetsBuildRunner` now supports multiple calls
810
([#102](https://github.com/dart-lang/native/issues/102)).
911

1012
## 0.1.0

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

Lines changed: 74 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,13 @@ class NativeAssetsBuildRunner {
2727
required this.dartExecutable,
2828
});
2929

30-
final _metadata = <Target, DependencyMetadata>{};
31-
3230
/// [workingDirectory] is expected to contain `.dart_tool`.
3331
///
3432
/// This method is invoked by launchers such as dartdev (for `dart run`) and
3533
/// flutter_tools (for `flutter run` and `flutter build`).
3634
///
3735
/// Completes the future with an error if the build fails.
38-
Future<List<Asset>> build({
36+
Future<BuildResult> build({
3937
required LinkModePreference linkModePreference,
4038
required Target target,
4139
required Uri workingDirectory,
@@ -45,7 +43,6 @@ class NativeAssetsBuildRunner {
4543
int? targetAndroidNdkApi,
4644
required bool includeParentEnvironment,
4745
}) async {
48-
_metadata.clear();
4946
final packageLayout =
5047
await PackageLayout.fromRootPackageRoot(workingDirectory);
5148
final packagesWithNativeAssets =
@@ -56,12 +53,14 @@ class NativeAssetsBuildRunner {
5653
dartExecutable: Uri.file(Platform.resolvedExecutable),
5754
);
5855
final plan = planner.plan();
59-
final assetList = <Asset>[];
56+
final assets = <Asset>[];
57+
final dependencies = <Uri>[];
58+
final metadata = <String, Metadata>{};
6059
for (final package in plan) {
6160
final dependencyMetadata = _metadataForPackage(
6261
packageGraph: planner.packageGraph,
6362
packageName: package.name,
64-
targetMetadata: _metadata[target],
63+
targetMetadata: metadata,
6564
);
6665
final config = await _cliConfig(
6766
packageRoot: packageLayout.packageRoot(package.name),
@@ -74,16 +73,23 @@ class NativeAssetsBuildRunner {
7473
targetIOSSdk: targetIOSSdk,
7574
targetAndroidNdkApi: targetAndroidNdkApi,
7675
);
77-
final assets = await _buildPackageCached(
76+
final (packageAssets, packageDependencies, packageMetadata) =
77+
await _buildPackageCached(
7878
config,
7979
packageLayout.packageConfigUri,
8080
workingDirectory,
8181
includeParentEnvironment,
8282
);
83-
validateAssetsPackage(assets, package.name);
84-
assetList.addAll(assets);
83+
assets.addAll(packageAssets);
84+
dependencies.addAll(packageDependencies);
85+
if (packageMetadata != null) {
86+
metadata[config.packageName] = packageMetadata;
87+
}
8588
}
86-
return assetList;
89+
return _BuildResultImpl(
90+
assets: assets,
91+
dependencies: dependencies..sort(_uriCompare),
92+
);
8793
}
8894

8995
/// [workingDirectory] is expected to contain `.dart_tool`.
@@ -92,7 +98,7 @@ class NativeAssetsBuildRunner {
9298
/// flutter_tools (for `flutter run` and `flutter build`).
9399
///
94100
/// Completes the future with an error if the build fails.
95-
Future<List<Asset>> dryRun({
101+
Future<DryRunResult> dryRun({
96102
required LinkModePreference linkModePreference,
97103
required OS targetOs,
98104
required Uri workingDirectory,
@@ -108,7 +114,7 @@ class NativeAssetsBuildRunner {
108114
dartExecutable: Uri.file(Platform.resolvedExecutable),
109115
);
110116
final plan = planner.plan();
111-
final assetList = <Asset>[];
117+
final assets = <Asset>[];
112118
for (final package in plan) {
113119
final config = await _cliConfigDryRun(
114120
packageName: package.name,
@@ -117,19 +123,21 @@ class NativeAssetsBuildRunner {
117123
linkMode: linkModePreference,
118124
buildParentDir: packageLayout.dartToolNativeAssetsBuilder,
119125
);
120-
final assets = await _buildPackage(
126+
final (packageAssets, _, _) = await _buildPackage(
121127
config,
122128
packageLayout.packageConfigUri,
123129
workingDirectory,
124130
includeParentEnvironment,
125131
dryRun: true,
126132
);
127-
assetList.addAll(assets);
133+
assets.addAll(packageAssets);
128134
}
129-
return assetList;
135+
return _DryRunResultImpl(
136+
assets: assets,
137+
);
130138
}
131139

132-
Future<List<Asset>> _buildPackageCached(
140+
Future<(List<Asset>, List<Uri>, Metadata?)> _buildPackageCached(
133141
BuildConfig config,
134142
Uri packageConfigUri,
135143
Uri workingDirectory,
@@ -152,12 +160,13 @@ class NativeAssetsBuildRunner {
152160
'Last build on $lastBuilt, last input change on $lastChange.');
153161
// All build flags go into [outDir]. Therefore we do not have to check
154162
// here whether the config is equal.
155-
156-
setMetadata(config.target, packageName, buildOutput?.metadata);
157-
return buildOutput!.assets;
163+
final assets = buildOutput!.assets;
164+
final dependencies = buildOutput.dependencies.dependencies;
165+
final metadata = buildOutput.metadata;
166+
return (assets, dependencies, metadata);
158167
}
159168

160-
return _buildPackage(
169+
return await _buildPackage(
161170
config,
162171
packageConfigUri,
163172
workingDirectory,
@@ -166,7 +175,7 @@ class NativeAssetsBuildRunner {
166175
);
167176
}
168177

169-
Future<List<Asset>> _buildPackage(
178+
Future<(List<Asset>, List<Uri>, Metadata?)> _buildPackage(
170179
BuildConfig config,
171180
Uri packageConfigUri,
172181
Uri workingDirectory,
@@ -198,18 +207,11 @@ class NativeAssetsBuildRunner {
198207
throwOnUnexpectedExitCode: true,
199208
);
200209
final buildOutput = await BuildOutput.readFromFile(outDir: outDir);
201-
if (!dryRun) {
202-
setMetadata(config.target, config.packageName, buildOutput?.metadata);
203-
}
204-
return buildOutput?.assets ?? [];
205-
}
206-
207-
void setMetadata(Target target, String packageName, Metadata? metadata) {
208-
if (metadata == null) {
209-
return;
210-
}
211-
_metadata[target] ??= {};
212-
_metadata[target]![packageName] = metadata;
210+
final assets = buildOutput?.assets ?? [];
211+
validateAssetsPackage(assets, config.packageName);
212+
final dependencies = buildOutput?.dependencies.dependencies ?? [];
213+
final metadata = dryRun ? null : buildOutput?.metadata;
214+
return (assets, dependencies, metadata);
213215
}
214216

215217
static Future<BuildConfig> _cliConfig({
@@ -306,6 +308,43 @@ class NativeAssetsBuildRunner {
306308
}
307309
}
308310

311+
/// The result from a [NativeAssetsBuildRunner.dryRun].
312+
abstract interface class DryRunResult {
313+
/// The native assets for all [Target]s for the build or dry run.
314+
List<Asset> get assets;
315+
}
316+
317+
final class _DryRunResultImpl implements DryRunResult {
318+
@override
319+
final List<Asset> assets;
320+
321+
_DryRunResultImpl({required this.assets});
322+
}
323+
324+
/// The result from a [NativeAssetsBuildRunner.build].
325+
abstract class BuildResult implements DryRunResult {
326+
/// All the files used for building the native assets of all packages.
327+
///
328+
/// This aggregated list can be used to determine whether the
329+
/// [NativeAssetsBuildRunner] needs to be invoked again. The
330+
/// [NativeAssetsBuildRunner] determines per package with native assets
331+
/// if it needs to run the build again.
332+
List<Uri> get dependencies;
333+
}
334+
335+
final class _BuildResultImpl implements BuildResult {
336+
@override
337+
final List<Asset> assets;
338+
339+
@override
340+
final List<Uri> dependencies;
341+
342+
_BuildResultImpl({
343+
required this.assets,
344+
required this.dependencies,
345+
});
346+
}
347+
309348
extension on DateTime {
310349
DateTime roundDownToSeconds() =>
311350
DateTime.fromMillisecondsSinceEpoch(millisecondsSinceEpoch -
@@ -316,3 +355,5 @@ extension on BuildConfig {
316355
String get packageName =>
317356
packageRoot.pathSegments.lastWhere((e) => e.isNotEmpty);
318357
}
358+
359+
int _uriCompare(Uri u1, Uri u2) => u1.toString().compareTo(u2.toString());

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

77
environment:

pkgs/native_assets_builder/test/build_runner/build_dependencies_test.dart

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,29 @@ void main() async {
2626
// Trigger a build, should invoke build for libraries with native assets.
2727
{
2828
final logMessages = <String>[];
29-
final assets = await build(packageUri, logger, dartExecutable,
29+
final result = await build(packageUri, logger, dartExecutable,
3030
capturedLogs: logMessages);
3131
expect(
32-
logMessages.join('\n'),
33-
stringContainsInOrder([
32+
logMessages.join('\n'),
33+
stringContainsInOrder(
34+
[
3435
'native_add${Platform.pathSeparator}build.dart',
3536
'native_subtract${Platform.pathSeparator}build.dart'
36-
]));
37-
expect(assets.length, 2);
37+
],
38+
),
39+
);
40+
expect(result.assets.length, 2);
41+
expect(
42+
result.dependencies,
43+
[
44+
tempUri.resolve('native_add/').resolve('build.dart'),
45+
tempUri.resolve('native_add/').resolve('src/native_add.c'),
46+
tempUri.resolve('native_subtract/').resolve('build.dart'),
47+
tempUri
48+
.resolve('native_subtract/')
49+
.resolve('src/native_subtract.c'),
50+
],
51+
);
3852
}
3953
});
4054
});

pkgs/native_assets_builder/test/build_runner/build_runner_asset_id_test.dart

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
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/native_assets_cli.dart';
65
import 'package:test/test.dart';
76

87
import '../helpers.dart';
@@ -23,13 +22,12 @@ void main() async {
2322

2423
{
2524
var buildFailed = false;
26-
final assets = await build(packageUri, logger, dartExecutable)
27-
.onError((error, stackTrace) {
25+
try {
26+
await build(packageUri, logger, dartExecutable);
27+
} catch (error) {
2828
buildFailed = true;
29-
return [];
30-
});
29+
}
3130
expect(buildFailed, true);
32-
expect(assets, <Asset>[]);
3331
}
3432
});
3533
});

pkgs/native_assets_builder/test/build_runner/build_runner_caching_test.dart

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,40 @@ void main() async {
2424

2525
{
2626
final logMessages = <String>[];
27-
await build(packageUri, logger, dartExecutable,
27+
final result = await build(packageUri, logger, dartExecutable,
2828
capturedLogs: logMessages);
2929
expect(
30-
logMessages.join('\n'),
31-
stringContainsInOrder(
32-
['native_add${Platform.pathSeparator}build.dart']));
30+
logMessages.join('\n'),
31+
contains('native_add${Platform.pathSeparator}build.dart'),
32+
);
33+
expect(
34+
result.dependencies,
35+
[
36+
packageUri.resolve('build.dart'),
37+
packageUri.resolve('src/native_add.c'),
38+
],
39+
);
3340
}
3441

3542
{
3643
final logMessages = <String>[];
37-
await build(packageUri, logger, dartExecutable,
44+
final result = await build(packageUri, logger, dartExecutable,
3845
capturedLogs: logMessages);
39-
expect(logMessages.join('\n'),
40-
stringContainsInOrder(['Skipping build for native_add']));
4146
expect(
42-
false,
43-
logMessages
44-
.join('\n')
45-
.contains('native_add${Platform.pathSeparator}build.dart'));
47+
logMessages.join('\n'),
48+
contains('Skipping build for native_add'),
49+
);
50+
expect(
51+
logMessages.join('\n'),
52+
isNot(contains('native_add${Platform.pathSeparator}build.dart')),
53+
);
54+
expect(
55+
result.dependencies,
56+
[
57+
packageUri.resolve('build.dart'),
58+
packageUri.resolve('src/native_add.c'),
59+
],
60+
);
4661
}
4762
});
4863
});
@@ -58,8 +73,8 @@ void main() async {
5873
);
5974

6075
{
61-
final assets = await build(packageUri, logger, dartExecutable);
62-
await expectSymbols(asset: assets.single, symbols: ['add']);
76+
final result = await build(packageUri, logger, dartExecutable);
77+
await expectSymbols(asset: result.assets.single, symbols: ['add']);
6378
}
6479

6580
await copyTestProjects(
@@ -68,8 +83,11 @@ void main() async {
6883
);
6984

7085
{
71-
final assets = await build(packageUri, logger, dartExecutable);
72-
await expectSymbols(asset: assets.single, symbols: ['add', 'subtract']);
86+
final result = await build(packageUri, logger, dartExecutable);
87+
await expectSymbols(
88+
asset: result.assets.single,
89+
symbols: ['add', 'subtract'],
90+
);
7391
}
7492
});
7593
});
@@ -82,17 +100,18 @@ void main() async {
82100
await runPubGet(workingDirectory: packageUri, logger: logger);
83101

84102
{
85-
final assets = await build(packageUri, logger, dartExecutable);
86-
await expectSymbols(asset: assets.single, symbols: ['add']);
103+
final result = await build(packageUri, logger, dartExecutable);
104+
await expectSymbols(asset: result.assets.single, symbols: ['add']);
87105
}
88106

89107
await copyTestProjects(
90108
sourceUri: testDataUri.resolve('native_add_add_source/'),
91109
targetUri: packageUri);
92110

93111
{
94-
final assets = await build(packageUri, logger, dartExecutable);
95-
await expectSymbols(asset: assets.single, symbols: ['add', 'multiply']);
112+
final result = await build(packageUri, logger, dartExecutable);
113+
await expectSymbols(
114+
asset: result.assets.single, symbols: ['add', 'multiply']);
96115
}
97116
});
98117
});

0 commit comments

Comments
 (0)