run method

Future<void> run(
  1. List<String> arguments
)

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;
  }
}