runBuilder function

Future<void> runBuilder(
  1. Builder builder,
  2. Iterable<AssetId> inputs,
  3. AssetReader reader,
  4. AssetWriter writer,
  5. Resolvers? resolvers, {
  6. Logger? logger,
  7. ResourceManager? resourceManager,
  8. StageTracker stageTracker = NoOpStageTracker.instance,
  9. void reportUnusedAssetsForInput(
    1. AssetId input,
    2. Iterable<AssetId> assets
    )?,
  10. PackageConfig? packageConfig,
})

Run builder with each asset in inputs as the primary input.

Builds for all inputs are run asynchronously and ordering is not guaranteed. The log instance inside the builds will be scoped to logger which is defaulted to a Logger name 'runBuilder'.

If a resourceManager is provided it will be used and it will not be automatically disposed of (its up to the caller to dispose of it later). If one is not provided then one will be created and disposed at the end of this function call.

If reportUnusedAssetsForInput is provided then all calls to BuildStep.reportUnusedAssets in builder will be forwarded to this function with the associated primary input.

Implementation

Future<void> runBuilder(
  Builder builder,
  Iterable<AssetId> inputs,
  AssetReader reader,
  AssetWriter writer,
  Resolvers? resolvers, {
  Logger? logger,
  ResourceManager? resourceManager,
  StageTracker stageTracker = NoOpStageTracker.instance,
  void Function(AssetId input, Iterable<AssetId> assets)?
      reportUnusedAssetsForInput,
  PackageConfig? packageConfig,
}) async {
  var shouldDisposeResourceManager = resourceManager == null;
  final resources = resourceManager ?? ResourceManager();
  logger ??= Logger('runBuilder');

  PackageConfig? transformedConfig;

  Future<PackageConfig> loadPackageConfig() async {
    if (transformedConfig != null) return transformedConfig!;

    var config = packageConfig;
    if (config == null) {
      final uri = await Isolate.packageConfig;

      if (uri == null) {
        throw UnsupportedError(
            'Isolate running the build does not have a package config and no '
            'fallback has been provided');
      }

      config = await loadPackageConfigUri(uri);
    }

    return transformedConfig = config.transformToAssetUris();
  }

  //TODO(nbosch) check overlapping outputs?
  Future<void> buildForInput(AssetId input) async {
    var outputs = expectedOutputs(builder, input);
    if (outputs.isEmpty) return;
    var buildStep = BuildStepImpl(
        input, outputs, reader, writer, resolvers, resources, loadPackageConfig,
        stageTracker: stageTracker,
        reportUnusedAssets: reportUnusedAssetsForInput == null
            ? null
            : (assets) => reportUnusedAssetsForInput(input, assets));
    try {
      await builder.build(buildStep);
    } finally {
      await buildStep.complete();
    }
  }

  await scopeLogAsync(() => Future.wait(inputs.map(buildForInput)), logger);

  if (shouldDisposeResourceManager) {
    await resources.disposeAll();
    await resources.beforeExit();
  }
}