| // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import 'dart:async'; |
| import 'dart:io'; |
| |
| import 'package:build/build.dart'; |
| import 'package:build_runner/src/generate/terminator.dart'; |
| import 'package:build_runner_core/build_runner_core.dart'; |
| import 'package:logging/logging.dart'; |
| import 'package:shelf/shelf.dart'; |
| import 'package:watcher/watcher.dart'; |
| |
| import '../logging/std_io_logging.dart'; |
| import '../package_graph/build_config_overrides.dart'; |
| import '../server/server.dart'; |
| import 'watch_impl.dart' as watch_impl; |
| |
| /// Runs all of the BuilderApplications in [builders] once. |
| /// |
| /// By default, the user will be prompted to delete any files which already |
| /// exist but were not generated by this specific build script. The |
| /// [deleteFilesByDefault] option can be set to `true` to skip this prompt. |
| /// |
| /// A [packageGraph] may be supplied, otherwise one will be constructed using |
| /// [PackageGraph.forThisPackage]. The default functionality assumes you are |
| /// running in the root directory of a package, with both a `pubspec.yaml` and |
| /// `.packages` file present. |
| /// |
| /// A [reader] and [writer] may also be supplied, which can read/write assets |
| /// to arbitrary locations or file systems. By default they will write directly |
| /// to the root package directory, and will use the [packageGraph] to know where |
| /// to read files from. |
| /// |
| /// Logging may be customized by passing a custom [logLevel] below which logs |
| /// will be ignored, as well as an [onLog] handler which defaults to [print]. |
| /// |
| /// The [terminateEventStream] is a stream which can send termination events. |
| /// By default the [ProcessSignal.sigint] stream is used. In this mode, it |
| /// will simply consume the first event and allow the build to continue. |
| /// Multiple termination events will cause a normal shutdown. |
| /// |
| /// If [outputSymlinksOnly] is `true`, then the merged output directories will |
| /// contain only symlinks, which is much faster but not generally suitable for |
| /// deployment. |
| /// |
| /// If [verbose] is `true` then verbose logging will be enabled. This changes |
| /// the default [logLevel] to [Level.ALL] and removes stack frame folding, among |
| /// other things. |
| Future<BuildResult> build(List<BuilderApplication> builders, |
| {bool deleteFilesByDefault, |
| bool assumeTty, |
| String configKey, |
| PackageGraph packageGraph, |
| RunnerAssetReader reader, |
| RunnerAssetWriter writer, |
| Resolvers resolvers, |
| Level logLevel, |
| void Function(LogRecord) onLog, |
| Stream terminateEventStream, |
| bool enableLowResourcesMode, |
| Set<BuildDirectory> buildDirs, |
| bool outputSymlinksOnly, |
| bool trackPerformance, |
| bool skipBuildScriptCheck, |
| bool verbose, |
| bool isReleaseBuild, |
| Map<String, Map<String, dynamic>> builderConfigOverrides, |
| String logPerformanceDir, |
| Set<BuildFilter> buildFilters}) async { |
| builderConfigOverrides ??= const {}; |
| packageGraph ??= PackageGraph.forThisPackage(); |
| var environment = OverrideableEnvironment( |
| IOEnvironment( |
| packageGraph, |
| assumeTty: assumeTty, |
| outputSymlinksOnly: outputSymlinksOnly, |
| ), |
| reader: reader, |
| writer: writer, |
| onLog: onLog ?? stdIOLogListener(assumeTty: assumeTty, verbose: verbose)); |
| var logSubscription = |
| LogSubscription(environment, verbose: verbose, logLevel: logLevel); |
| var options = await BuildOptions.create( |
| logSubscription, |
| deleteFilesByDefault: deleteFilesByDefault, |
| packageGraph: packageGraph, |
| skipBuildScriptCheck: skipBuildScriptCheck, |
| overrideBuildConfig: |
| await findBuildConfigOverrides(packageGraph, configKey), |
| enableLowResourcesMode: enableLowResourcesMode, |
| trackPerformance: trackPerformance, |
| logPerformanceDir: logPerformanceDir, |
| resolvers: resolvers, |
| ); |
| var terminator = Terminator(terminateEventStream); |
| try { |
| var build = await BuildRunner.create( |
| options, |
| environment, |
| builders, |
| builderConfigOverrides, |
| isReleaseBuild: isReleaseBuild ?? false, |
| ); |
| var result = |
| await build.run({}, buildDirs: buildDirs, buildFilters: buildFilters); |
| await build?.beforeExit(); |
| return result; |
| } finally { |
| await terminator.cancel(); |
| await options.logListener.cancel(); |
| } |
| } |
| |
| /// Same as [build], except it watches the file system and re-runs builds |
| /// automatically. |
| /// |
| /// Call [ServeHandler.handlerFor] to create a [Handler] for use with |
| /// `package:shelf`. Requests for assets will be blocked while builds are |
| /// running then served with the latest version of the asset. Only source and |
| /// generated assets can be served through this handler. |
| /// |
| /// The [debounceDelay] controls how often builds will run. As long as files |
| /// keep changing with less than that amount of time apart, builds will be put |
| /// off. |
| /// |
| /// The [directoryWatcherFactory] allows you to inject a way of creating custom |
| /// `DirectoryWatcher`s. By default a normal `DirectoryWatcher` will be used. |
| /// |
| /// The [terminateEventStream] is a stream which can send termination events. |
| /// By default the [ProcessSignal.sigint] stream is used. In this mode, the |
| /// first event will allow any ongoing builds to finish, and then the program |
| /// will complete normally. Subsequent events are not handled (and will |
| /// typically cause a shutdown). |
| Future<ServeHandler> watch(List<BuilderApplication> builders, |
| {bool deleteFilesByDefault, |
| bool assumeTty, |
| String configKey, |
| PackageGraph packageGraph, |
| RunnerAssetReader reader, |
| RunnerAssetWriter writer, |
| Resolvers resolvers, |
| Level logLevel, |
| void Function(LogRecord) onLog, |
| Duration debounceDelay, |
| DirectoryWatcher Function(String) directoryWatcherFactory, |
| Stream terminateEventStream, |
| bool enableLowResourcesMode, |
| Set<BuildDirectory> buildDirs, |
| bool outputSymlinksOnly, |
| bool trackPerformance, |
| bool skipBuildScriptCheck, |
| bool verbose, |
| bool isReleaseBuild, |
| Map<String, Map<String, dynamic>> builderConfigOverrides, |
| String logPerformanceDir, |
| Set<BuildFilter> buildFilters}) => |
| watch_impl.watch( |
| builders, |
| assumeTty: assumeTty, |
| deleteFilesByDefault: deleteFilesByDefault, |
| configKey: configKey, |
| packageGraph: packageGraph, |
| reader: reader, |
| writer: writer, |
| resolvers: resolvers, |
| logLevel: logLevel, |
| onLog: onLog, |
| debounceDelay: debounceDelay, |
| directoryWatcherFactory: directoryWatcherFactory, |
| terminateEventStream: terminateEventStream, |
| enableLowResourcesMode: enableLowResourcesMode, |
| buildDirs: buildDirs, |
| outputSymlinksOnly: outputSymlinksOnly, |
| trackPerformance: trackPerformance, |
| skipBuildScriptCheck: skipBuildScriptCheck, |
| verbose: verbose, |
| builderConfigOverrides: builderConfigOverrides, |
| isReleaseBuild: isReleaseBuild, |
| logPerformanceDir: logPerformanceDir, |
| buildFilters: buildFilters, |
| ); |