in build_runner/lib/src/build_script_generate/bootstrap.dart [29:124]
Future<int> generateAndRun(
List<String> args, {
Logger? logger,
Future<String> Function() generateBuildScript = generateBuildScript,
void Function(Object error, StackTrace stackTrace) handleUncaughtError =
_defaultHandleUncaughtError,
}) async {
logger ??= _logger;
ReceivePort? exitPort;
ReceivePort? errorPort;
ReceivePort? messagePort;
StreamSubscription? errorListener;
int? scriptExitCode;
var tryCount = 0;
var succeeded = false;
while (tryCount < 2 && !succeeded) {
tryCount++;
exitPort?.close();
errorPort?.close();
messagePort?.close();
await errorListener?.cancel();
try {
var buildScript = File(scriptLocation);
var oldContents = '';
if (buildScript.existsSync()) {
oldContents = buildScript.readAsStringSync();
}
var newContents = await generateBuildScript();
// Only trigger a build script update if necessary.
if (newContents != oldContents) {
buildScript
..createSync(recursive: true)
..writeAsStringSync(newContents);
}
} on CannotBuildException {
return ExitCode.config.code;
}
scriptExitCode = await _createKernelIfNeeded(logger);
if (scriptExitCode != 0) return scriptExitCode!;
exitPort = ReceivePort();
errorPort = ReceivePort();
messagePort = ReceivePort();
errorListener = errorPort.listen((e) {
final error = e[0] as Object? ?? NullThrownError();
final trace = Trace.parse(e[1] as String).terse;
handleUncaughtError(error, trace);
if (scriptExitCode == 0) scriptExitCode = 1;
});
try {
await Isolate.spawnUri(Uri.file(p.absolute(scriptKernelLocation)), args,
messagePort.sendPort,
errorsAreFatal: true,
onExit: exitPort.sendPort,
onError: errorPort.sendPort);
succeeded = true;
} on IsolateSpawnException catch (e) {
if (tryCount > 1) {
logger.severe(
'Failed to spawn build script after retry. '
'This is likely due to a misconfigured builder definition. '
'See the generated script at $scriptLocation to find errors.',
e);
messagePort.sendPort.send(ExitCode.config.code);
exitPort.sendPort.send(null);
} else {
logger.warning(
'Error spawning build script isolate, this is likely due to a Dart '
'SDK update. Deleting precompiled script and retrying...');
}
await File(scriptKernelLocation).rename(scriptKernelCachedLocation);
}
}
StreamSubscription? exitCodeListener;
exitCodeListener = messagePort!.listen((isolateExitCode) {
if (isolateExitCode is int) {
scriptExitCode = isolateExitCode;
} else {
throw StateError(
'Bad response from isolate, expected an exit code but got '
'$isolateExitCode');
}
exitCodeListener!.cancel();
exitCodeListener = null;
});
await exitPort?.first;
await errorListener?.cancel();
await exitCodeListener?.cancel();
return scriptExitCode ?? 1;
}