@@ -55,40 +55,51 @@ class NativeAssetsBuildRunner {
55
55
final plan = planner.plan ();
56
56
final assets = < Asset > [];
57
57
final dependencies = < Uri > [];
58
+ final errors = < NativeAssetsBuilderError > [];
58
59
final metadata = < String , Metadata > {};
59
- for (final package in plan) {
60
- final dependencyMetadata = _metadataForPackage (
61
- packageGraph: planner.packageGraph,
62
- packageName: package.name,
63
- targetMetadata: metadata,
64
- );
65
- final config = await _cliConfig (
66
- packageRoot: packageLayout.packageRoot (package.name),
67
- target: target,
68
- buildMode: buildMode,
69
- linkMode: linkModePreference,
70
- buildParentDir: packageLayout.dartToolNativeAssetsBuilder,
71
- dependencyMetadata: dependencyMetadata,
72
- cCompilerConfig: cCompilerConfig,
73
- targetIOSSdk: targetIOSSdk,
74
- targetAndroidNdkApi: targetAndroidNdkApi,
75
- );
76
- final (packageAssets, packageDependencies, packageMetadata) =
77
- await _buildPackageCached (
78
- config,
79
- packageLayout.packageConfigUri,
80
- workingDirectory,
81
- includeParentEnvironment,
82
- );
83
- assets.addAll (packageAssets);
84
- dependencies.addAll (packageDependencies);
85
- if (packageMetadata != null ) {
86
- metadata[config.packageName] = packageMetadata;
60
+ if (plan.errors.isNotEmpty) {
61
+ errors.addAll (plan.errors);
62
+ } else {
63
+ for (final package in plan.packages) {
64
+ final dependencyMetadata = _metadataForPackage (
65
+ packageGraph: planner.packageGraph,
66
+ packageName: package.name,
67
+ targetMetadata: metadata,
68
+ );
69
+ final config = await _cliConfig (
70
+ packageRoot: packageLayout.packageRoot (package.name),
71
+ target: target,
72
+ buildMode: buildMode,
73
+ linkMode: linkModePreference,
74
+ buildParentDir: packageLayout.dartToolNativeAssetsBuilder,
75
+ dependencyMetadata: dependencyMetadata,
76
+ cCompilerConfig: cCompilerConfig,
77
+ targetIOSSdk: targetIOSSdk,
78
+ targetAndroidNdkApi: targetAndroidNdkApi,
79
+ );
80
+ final (
81
+ packageAssets,
82
+ packageDependencies,
83
+ packageMetadata,
84
+ packageErrors
85
+ ) = await _buildPackageCached (
86
+ config,
87
+ packageLayout.packageConfigUri,
88
+ workingDirectory,
89
+ includeParentEnvironment,
90
+ );
91
+ assets.addAll (packageAssets);
92
+ dependencies.addAll (packageDependencies);
93
+ errors.addAll (packageErrors);
94
+ if (packageMetadata != null ) {
95
+ metadata[config.packageName] = packageMetadata;
96
+ }
87
97
}
88
98
}
89
99
return _BuildResultImpl (
90
100
assets: assets,
91
101
dependencies: dependencies..sort (_uriCompare),
102
+ errors: errors,
92
103
);
93
104
}
94
105
@@ -115,29 +126,37 @@ class NativeAssetsBuildRunner {
115
126
);
116
127
final plan = planner.plan ();
117
128
final assets = < Asset > [];
118
- for (final package in plan) {
119
- final config = await _cliConfigDryRun (
120
- packageName: package.name,
121
- packageRoot: packageLayout.packageRoot (package.name),
122
- targetOs: targetOs,
123
- linkMode: linkModePreference,
124
- buildParentDir: packageLayout.dartToolNativeAssetsBuilder,
125
- );
126
- final (packageAssets, _, _) = await _buildPackage (
127
- config,
128
- packageLayout.packageConfigUri,
129
- workingDirectory,
130
- includeParentEnvironment,
131
- dryRun: true ,
132
- );
133
- assets.addAll (packageAssets);
129
+ final errors = < NativeAssetsBuilderError > [];
130
+ if (plan.errors.isNotEmpty) {
131
+ errors.addAll (plan.errors);
132
+ } else {
133
+ for (final package in plan.packages) {
134
+ final config = await _cliConfigDryRun (
135
+ packageName: package.name,
136
+ packageRoot: packageLayout.packageRoot (package.name),
137
+ targetOs: targetOs,
138
+ linkMode: linkModePreference,
139
+ buildParentDir: packageLayout.dartToolNativeAssetsBuilder,
140
+ );
141
+ final (packageAssets, _, _, packageErrors) = await _buildPackage (
142
+ config,
143
+ packageLayout.packageConfigUri,
144
+ workingDirectory,
145
+ includeParentEnvironment,
146
+ dryRun: true ,
147
+ );
148
+ assets.addAll (packageAssets);
149
+ errors.addAll (packageErrors);
150
+ }
134
151
}
135
152
return _DryRunResultImpl (
136
153
assets: assets,
154
+ errors: errors,
137
155
);
138
156
}
139
157
140
- Future <(List <Asset >, List <Uri >, Metadata ?)> _buildPackageCached (
158
+ Future <(List <Asset >, List <Uri >, Metadata ?, List <NativeAssetsBuilderError >)>
159
+ _buildPackageCached (
141
160
BuildConfig config,
142
161
Uri packageConfigUri,
143
162
Uri workingDirectory,
@@ -163,7 +182,7 @@ class NativeAssetsBuildRunner {
163
182
final assets = buildOutput! .assets;
164
183
final dependencies = buildOutput.dependencies.dependencies;
165
184
final metadata = buildOutput.metadata;
166
- return (assets, dependencies, metadata);
185
+ return (assets, dependencies, metadata, < NativeAssetsBuilderError > [] );
167
186
}
168
187
169
188
return await _buildPackage (
@@ -175,7 +194,8 @@ class NativeAssetsBuildRunner {
175
194
);
176
195
}
177
196
178
- Future <(List <Asset >, List <Uri >, Metadata ?)> _buildPackage (
197
+ Future <(List <Asset >, List <Uri >, Metadata ?, List <NativeAssetsBuilderError >)>
198
+ _buildPackage (
179
199
BuildConfig config,
180
200
Uri packageConfigUri,
181
201
Uri workingDirectory,
@@ -193,25 +213,82 @@ class NativeAssetsBuildRunner {
193
213
// Ensure we'll never read outdated build results.
194
214
await buildOutputFile.delete ();
195
215
}
196
- await runProcess (
216
+ final arguments = [
217
+ '--packages=${packageConfigUri .toFilePath ()}' ,
218
+ buildDotDart.toFilePath (),
219
+ '--config=${configFile .toFilePath ()}' ,
220
+ ];
221
+ final result = await runProcess (
197
222
workingDirectory: workingDirectory,
198
223
executable: dartExecutable,
199
- arguments: [
200
- '--packages=${packageConfigUri .toFilePath ()}' ,
201
- buildDotDart.toFilePath (),
202
- '--config=${configFile .toFilePath ()}' ,
203
- ],
224
+ arguments: arguments,
204
225
logger: logger,
205
226
includeParentEnvironment: includeParentEnvironment,
206
- expectedExitCode: 0 ,
207
- throwOnUnexpectedExitCode: true ,
208
227
);
209
- final buildOutput = await BuildOutput .readFromFile (outDir: outDir);
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);
228
+ final errors = < NativeAssetsBuilderError > [];
229
+ if (result.exitCode != 0 ) {
230
+ final printWorkingDir = workingDirectory != Directory .current.uri;
231
+ final commandString = [
232
+ if (printWorkingDir) '(cd ${workingDirectory .toFilePath ()};' ,
233
+ dartExecutable.toFilePath (),
234
+ ...arguments.map ((a) => a.contains (' ' ) ? "'$a '" : a),
235
+ if (printWorkingDir) ')' ,
236
+ ].join (' ' );
237
+ errors.add (NativeAssetsBuilderError (
238
+ package: config.packageName,
239
+ '''Building native assets failed.
240
+ build.dart returned with exit code: ${result .exitCode }.
241
+ To reproduce run:
242
+ $commandString
243
+ stderr:
244
+ ${result .stderr }
245
+ stdout:
246
+ ${result .stdout }
247
+ ''' ,
248
+ ));
249
+ }
250
+
251
+ try {
252
+ final buildOutput = await BuildOutput .readFromFile (outDir: outDir);
253
+ final assets = buildOutput? .assets ?? [];
254
+ errors.addAll (validateAssetsPackage (assets, config.packageName));
255
+ final dependencies = buildOutput? .dependencies.dependencies ?? [];
256
+ final metadata = dryRun ? null : buildOutput? .metadata;
257
+ return (assets, dependencies, metadata, errors);
258
+ } on FormatException catch (e) {
259
+ return (
260
+ < Asset > [],
261
+ < Uri > [],
262
+ null ,
263
+ [
264
+ NativeAssetsBuilderError (
265
+ package: config.packageName,
266
+ '''Building native assets failed.
267
+ build_output.yaml contained a format error.
268
+ ${e .message }
269
+ ''' ,
270
+ ),
271
+ ],
272
+ );
273
+ // TODO(https://github.com/dart-lang/native/issues/109): Stop throwing
274
+ // type errors in native_assets_cli, release a new version of that package
275
+ // and then remove this.
276
+ // ignore: avoid_catching_errors
277
+ } on TypeError {
278
+ return (
279
+ < Asset > [],
280
+ < Uri > [],
281
+ null ,
282
+ [
283
+ NativeAssetsBuilderError (
284
+ package: config.packageName,
285
+ '''Building native assets failed.
286
+ build_output.yaml contained a format error.
287
+ ''' ,
288
+ ),
289
+ ],
290
+ );
291
+ }
215
292
}
216
293
217
294
static Future <BuildConfig > _cliConfig ({
@@ -292,33 +369,44 @@ class NativeAssetsBuildRunner {
292
369
};
293
370
}
294
371
295
- void validateAssetsPackage (List <Asset > assets, String packageName) {
372
+ List <NativeAssetsBuilderError > validateAssetsPackage (
373
+ List <Asset > assets, String packageName) {
296
374
final invalidAssetIds = assets
297
375
.map ((a) => a.name)
298
376
.where ((n) => ! n.startsWith ('package:$packageName /' ))
299
377
.toSet ()
300
378
.toList ()
301
379
..sort ();
302
- if (invalidAssetIds.isNotEmpty) {
303
- throw FormatException (
304
- '`package:$packageName ` declares the following assets which do not '
305
- 'start with `package:$packageName /`: ${invalidAssetIds .join (', ' )}.' ,
306
- );
307
- }
380
+ return [
381
+ if (invalidAssetIds.isNotEmpty)
382
+ NativeAssetsBuilderError (
383
+ '`package:$packageName ` declares the following assets which do not '
384
+ 'start with `package:$packageName /`: ${invalidAssetIds .join (', ' )}.' ,
385
+ ),
386
+ ];
308
387
}
309
388
}
310
389
311
390
/// The result from a [NativeAssetsBuildRunner.dryRun] .
312
391
abstract interface class DryRunResult {
313
392
/// The native assets for all [Target] s for the build or dry run.
314
393
List <Asset > get assets;
394
+
395
+ /// Any errors
396
+ List <NativeAssetsBuilderError > get errors;
315
397
}
316
398
317
399
final class _DryRunResultImpl implements DryRunResult {
318
400
@override
319
401
final List <Asset > assets;
320
402
321
- _DryRunResultImpl ({required this .assets});
403
+ @override
404
+ final List <NativeAssetsBuilderError > errors;
405
+
406
+ _DryRunResultImpl ({
407
+ required this .assets,
408
+ required this .errors,
409
+ });
322
410
}
323
411
324
412
/// The result from a [NativeAssetsBuildRunner.build] .
@@ -339,9 +427,25 @@ final class _BuildResultImpl implements BuildResult {
339
427
@override
340
428
final List <Uri > dependencies;
341
429
430
+ @override
431
+ final List <NativeAssetsBuilderError > errors;
432
+
342
433
_BuildResultImpl ({
343
434
required this .assets,
344
435
required this .dependencies,
436
+ required this .errors,
437
+ });
438
+ }
439
+
440
+ final class NativeAssetsBuilderError {
441
+ final String message;
442
+
443
+ /// The package that was being built that caused an error.
444
+ final String ? package;
445
+
446
+ NativeAssetsBuilderError (
447
+ this .message, {
448
+ this .package,
345
449
});
346
450
}
347
451
0 commit comments