@@ -27,15 +27,13 @@ class NativeAssetsBuildRunner {
27
27
required this .dartExecutable,
28
28
});
29
29
30
- final _metadata = < Target , DependencyMetadata > {};
31
-
32
30
/// [workingDirectory] is expected to contain `.dart_tool` .
33
31
///
34
32
/// This method is invoked by launchers such as dartdev (for `dart run` ) and
35
33
/// flutter_tools (for `flutter run` and `flutter build` ).
36
34
///
37
35
/// Completes the future with an error if the build fails.
38
- Future <List < Asset > > build ({
36
+ Future <BuildResult > build ({
39
37
required LinkModePreference linkModePreference,
40
38
required Target target,
41
39
required Uri workingDirectory,
@@ -45,7 +43,6 @@ class NativeAssetsBuildRunner {
45
43
int ? targetAndroidNdkApi,
46
44
required bool includeParentEnvironment,
47
45
}) async {
48
- _metadata.clear ();
49
46
final packageLayout =
50
47
await PackageLayout .fromRootPackageRoot (workingDirectory);
51
48
final packagesWithNativeAssets =
@@ -56,12 +53,14 @@ class NativeAssetsBuildRunner {
56
53
dartExecutable: Uri .file (Platform .resolvedExecutable),
57
54
);
58
55
final plan = planner.plan ();
59
- final assetList = < Asset > [];
56
+ final assets = < Asset > [];
57
+ final dependencies = < Uri > [];
58
+ final metadata = < String , Metadata > {};
60
59
for (final package in plan) {
61
60
final dependencyMetadata = _metadataForPackage (
62
61
packageGraph: planner.packageGraph,
63
62
packageName: package.name,
64
- targetMetadata: _metadata[target] ,
63
+ targetMetadata: metadata ,
65
64
);
66
65
final config = await _cliConfig (
67
66
packageRoot: packageLayout.packageRoot (package.name),
@@ -74,16 +73,23 @@ class NativeAssetsBuildRunner {
74
73
targetIOSSdk: targetIOSSdk,
75
74
targetAndroidNdkApi: targetAndroidNdkApi,
76
75
);
77
- final assets = await _buildPackageCached (
76
+ final (packageAssets, packageDependencies, packageMetadata) =
77
+ await _buildPackageCached (
78
78
config,
79
79
packageLayout.packageConfigUri,
80
80
workingDirectory,
81
81
includeParentEnvironment,
82
82
);
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
+ }
85
88
}
86
- return assetList;
89
+ return _BuildResultImpl (
90
+ assets: assets,
91
+ dependencies: dependencies..sort (_uriCompare),
92
+ );
87
93
}
88
94
89
95
/// [workingDirectory] is expected to contain `.dart_tool` .
@@ -92,7 +98,7 @@ class NativeAssetsBuildRunner {
92
98
/// flutter_tools (for `flutter run` and `flutter build` ).
93
99
///
94
100
/// Completes the future with an error if the build fails.
95
- Future <List < Asset > > dryRun ({
101
+ Future <DryRunResult > dryRun ({
96
102
required LinkModePreference linkModePreference,
97
103
required OS targetOs,
98
104
required Uri workingDirectory,
@@ -108,7 +114,7 @@ class NativeAssetsBuildRunner {
108
114
dartExecutable: Uri .file (Platform .resolvedExecutable),
109
115
);
110
116
final plan = planner.plan ();
111
- final assetList = < Asset > [];
117
+ final assets = < Asset > [];
112
118
for (final package in plan) {
113
119
final config = await _cliConfigDryRun (
114
120
packageName: package.name,
@@ -117,19 +123,21 @@ class NativeAssetsBuildRunner {
117
123
linkMode: linkModePreference,
118
124
buildParentDir: packageLayout.dartToolNativeAssetsBuilder,
119
125
);
120
- final assets = await _buildPackage (
126
+ final (packageAssets, _, _) = await _buildPackage (
121
127
config,
122
128
packageLayout.packageConfigUri,
123
129
workingDirectory,
124
130
includeParentEnvironment,
125
131
dryRun: true ,
126
132
);
127
- assetList .addAll (assets );
133
+ assets .addAll (packageAssets );
128
134
}
129
- return assetList;
135
+ return _DryRunResultImpl (
136
+ assets: assets,
137
+ );
130
138
}
131
139
132
- Future <List <Asset >> _buildPackageCached (
140
+ Future <( List <Asset >, List < Uri >, Metadata ?) > _buildPackageCached (
133
141
BuildConfig config,
134
142
Uri packageConfigUri,
135
143
Uri workingDirectory,
@@ -152,12 +160,13 @@ class NativeAssetsBuildRunner {
152
160
'Last build on $lastBuilt , last input change on $lastChange .' );
153
161
// All build flags go into [outDir]. Therefore we do not have to check
154
162
// 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);
158
167
}
159
168
160
- return _buildPackage (
169
+ return await _buildPackage (
161
170
config,
162
171
packageConfigUri,
163
172
workingDirectory,
@@ -166,7 +175,7 @@ class NativeAssetsBuildRunner {
166
175
);
167
176
}
168
177
169
- Future <List <Asset >> _buildPackage (
178
+ Future <( List <Asset >, List < Uri >, Metadata ?) > _buildPackage (
170
179
BuildConfig config,
171
180
Uri packageConfigUri,
172
181
Uri workingDirectory,
@@ -198,18 +207,11 @@ class NativeAssetsBuildRunner {
198
207
throwOnUnexpectedExitCode: true ,
199
208
);
200
209
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);
213
215
}
214
216
215
217
static Future <BuildConfig > _cliConfig ({
@@ -306,6 +308,43 @@ class NativeAssetsBuildRunner {
306
308
}
307
309
}
308
310
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
+
309
348
extension on DateTime {
310
349
DateTime roundDownToSeconds () =>
311
350
DateTime .fromMillisecondsSinceEpoch (millisecondsSinceEpoch -
@@ -316,3 +355,5 @@ extension on BuildConfig {
316
355
String get packageName =>
317
356
packageRoot.pathSegments.lastWhere ((e) => e.isNotEmpty);
318
357
}
358
+
359
+ int _uriCompare (Uri u1, Uri u2) => u1.toString ().compareTo (u2.toString ());
0 commit comments