run method
Run this declaration as the calling script's command-line interface.
Options only affect this invocation. Expected failures print a diagnostic and set exitCode to 64 for invalid arguments or 1 for build failures; this method does not terminate the process. Use build to handle errors directly. Selecting Wasm alone does not access the native runtime.
Implementation
Future<void> run(List<String> arguments) async {
final parser = ArgParser()
..addFlag('help', abbr: 'h', negatable: false, help: 'Show usage.')
..addFlag(
'watch',
negatable: false,
help: 'Rebuild when Dart sources or package assets change.',
)
..addOption(
'target',
allowed: ['wasm', 'native', 'both'],
help: 'Select backends for this build. Both retains the declared root.',
)
..addOption(
'output',
abbr: 'o',
help: 'Override the output directory for this build.',
);
try {
final options = parser.parse(arguments);
if (options.rest.isNotEmpty) {
throw FormatException(
'Unexpected arguments: ${options.rest.join(' ')}',
);
}
if (options.flag('help')) {
final script = path.relative(Platform.script.toFilePath());
stdout.writeln('Usage: dart run $script [options]\n\n${parser.usage}');
return;
}
final override = options.option('target');
final root = switch (override) {
'wasm' => BuildTarget.wasm,
'native' => BuildTarget.native,
_ => target,
};
final selected = switch (override) {
'both' => BuildTarget.values.toSet(),
'wasm' || 'native' => {root},
_ => targets,
};
final destination = options.option('output');
if (destination != null && destination.isEmpty) {
throw const FormatException('Output directory must not be empty.');
}
final directory = destination == null ? output : Directory(destination);
Future<void> buildOnce() async {
final result = await _build(
directory,
root,
selected,
override == 'wasm' ? null : nativeRuntime,
override == 'wasm' || override == 'native' ? false : wasmFallback,
);
stdout.writeln('Built ${result.path}');
}
if (!options.flag('watch')) {
await buildOnce();
return;
}
final stop = StreamController<void>();
final signals = [
for (final signal in [
ProcessSignal.sigint,
if (!Platform.isWindows) ProcessSignal.sigterm,
])
signal.watch().listen((_) => stop.add(null)),
];
try {
await watchBuild(
library: library,
output: directory,
packagesPath: libraryPackagesPath(packagesPath, external),
assets: assets.values,
stop: stop.stream,
build: () async {
try {
await buildOnce();
exitCode = 0;
} catch (error) {
if (!_report(error)) rethrow;
}
},
);
} finally {
for (final signal in signals) {
await signal.cancel();
}
await stop.close();
}
} catch (error) {
if (!_report(error)) rethrow;
}
}