From a6eeed27934a66a03847c6e16f8676b6f4425bce Mon Sep 17 00:00:00 2001 From: David Morgan Date: Mon, 11 Aug 2025 18:22:30 +0200 Subject: [PATCH 1/3] Documentation revamp. --- README.md | 84 +---- build/CHANGELOG.md | 1 + build/README.md | 164 +++------- build_config/CHANGELOG.md | 1 + build_config/README.md | 145 ++++++++- build_runner/CHANGELOG.md | 1 + build_runner/README.md | 375 ++++++++++------------ build_test/CHANGELOG.md | 1 + build_test/README.md | 116 ++----- build_web_compilers/CHANGELOG.md | 4 + build_web_compilers/README.md | 104 +----- build_web_compilers/pubspec.yaml | 2 +- docs/builder_author_faq.md | 115 ------- docs/faq.md | 454 --------------------------- docs/getting_started.md | 116 ------- docs/images/example_build.png | Bin 52314 -> 0 bytes docs/images/idea_schema_config.png | Bin 38422 -> 0 bytes docs/measuring_performance.md | 99 ------ docs/partial_builds.md | 81 ----- docs/windows_faq.md | 34 -- docs/writing_a_builder.md | 141 --------- docs/writing_an_aggregate_builder.md | 226 ------------- 22 files changed, 395 insertions(+), 1869 deletions(-) delete mode 100644 docs/builder_author_faq.md delete mode 100644 docs/faq.md delete mode 100644 docs/getting_started.md delete mode 100644 docs/images/example_build.png delete mode 100644 docs/images/idea_schema_config.png delete mode 100644 docs/measuring_performance.md delete mode 100644 docs/partial_builds.md delete mode 100644 docs/windows_faq.md delete mode 100644 docs/writing_a_builder.md delete mode 100644 docs/writing_an_aggregate_builder.md diff --git a/README.md b/README.md index c66d30c1d3..cdcf1b7b76 100644 --- a/README.md +++ b/README.md @@ -1,77 +1,13 @@ -[![Dart CI](https://github.com/dart-lang/build/actions/workflows/dart.yml/badge.svg)](https://github.com/dart-lang/build/actions/workflows/dart.yml) +_Questions? Suggestions? Found a bug? Please +[file an issue](https://github.com/dart-lang/build/issues) or + [start a discussion](https://github.com/dart-lang/build/discussions)._ -These packages provide libraries for generating, compiling and serving Dart code. +Code generation for Flutter and Dart packages. -[Getting started with build_runner](https://github.com/dart-lang/build/blob/master/docs/getting_started.md) +See the +[build_runner package documentation](https://pub.dev/packages/build_runner) +for how to use `build_runner` builders in your package to add serialization, +data classes, data binding, dependency injection, mocking and more. -[General FAQ](https://github.com/dart-lang/build/blob/master/docs/faq.md) - -[Windows FAQ](https://github.com/dart-lang/build/blob/master/docs/windows_faq.md) - -[FAQ for Builder authors](https://github.com/dart-lang/build/blob/master/docs/builder_author_faq.md). - -[Additional Docs](https://github.com/dart-lang/build/blob/master/docs/) - -## [build](https://github.com/dart-lang/build/blob/master/build/README.md) - -Defines the interfaces for creating a `Builder` which is a way of doing codegen -that is compatible across build systems (pub, bazel, standalone runner). - -For packages doing code generation this should generally be the only package -against which there is a public dependency. Packages may have a dev_dependency on -one or more of the other packages. - -## [build_config](https://github.com/dart-lang/build/blob/master/build_config/README.md) - -Support for parsing `build.yaml` files. Used by `build_runner`. - -## [build_modules](https://github.com/dart-lang/build/blob/master/build_modules/README.md) - -Support for discovering the sub-modules within packages and creating summaries -of those modules. Used by `build_web_compilers` but should not be used directly -by most users. - -## [build_resolvers](https://github.com/dart-lang/build/blob/master/build_resolvers/README.md) - -An implementation of the `Resolver` interface to use the analyzer during build -steps. - -## [build_runner](https://github.com/dart-lang/build/blob/master/build_runner/README.md) - -Provides utilities to enact builds and a way to automatically run builds based -on configuration. - -This package should generally be a dev_dependency as it is used to run -standalone builds. The only exception would be wrapping the `build` and `watch` -methods with some other package. - -## [build_test](https://github.com/dart-lang/build/blob/master/build_test/README.md) - -Stub implementations for classes in `Build` and some utilities for running -instances of builds and checking their outputs. - -This package generally only be a dev_dependency as it introduces a dependency on -package:test. The exception to that would be if you were creating another -testing-only package that wraps this one. - -## [build_web_compilers](https://github.com/dart-lang/build/blob/master/build_web_compilers/README.md) - -Provides the `dart2js` and `dartdevc` support for your package. To use this -package you should add it as a dev_dependency. - -If you are using the automated build scripts, your project will automatically -start being compiled with dartdevc, and you can start developing with chrome -without any configuration. - - - -## Examples - -The [example](https://github.com/dart-lang/build/tree/master/example) -directory has an example of a build with custom builders which generate outputs -into both the source tree and a hidden generated directory. Try a build with -`dart run build_runner build -o web:deploy` to see what the output looks like. - -Most projects should not need custom builders. +See the [build package documentation](https://pub.dev/packages/build) to create +your own builder. \ No newline at end of file diff --git a/build/CHANGELOG.md b/build/CHANGELOG.md index 15114b77ee..4fa3b10c17 100644 --- a/build/CHANGELOG.md +++ b/build/CHANGELOG.md @@ -1,6 +1,7 @@ ## 3.0.2-wip - Use `build_runner_core` 9.3.0. +- Documentation revamp. ## 3.0.1 diff --git a/build/README.md b/build/README.md index d79b3f109f..9a7f062689 100644 --- a/build/README.md +++ b/build/README.md @@ -1,46 +1,50 @@ -Defines the basic pieces of how a build happens and how they interact. +_Questions? Suggestions? Found a bug? Please +[file an issue](https://github.com/dart-lang/build/issues) or + [start a discussion](https://github.com/dart-lang/build/discussions)._ -## [`Builder`][dartdoc:Builder] +Package for writing code generators, called _builders_, that run with +[build_runner](https://pub.dev/packages/build_runner). -The business logic for code generation. Most consumers of the `build` package -will create custom implementations of `Builder`. +- [See also: source_gen](#see-also-source_gen) +- [The `Builder` interface](#the-builder-interface) + - [Using the analyzer](#using-the-analyzer) +- [Examples](#examples) -## [`BuildStep`][dartdoc:BuildStep] +## See also: source_gen -The way a `Builder` interacts with the outside world. Defines the unit of work -and allows reading/writing files and resolving Dart source code. +The [source_gen](https://pub.dev/packages/source_gen) package provides helpers +for writing common types of builder, for example builders that are triggered by +a particular annotation. -## [`Resolver`][dartdoc:Resolver] class +Most builders should use `source_gen`, but it's still useful to learn about the +underlying `Builder` interface that `source_gen` plugs into. -An interface into the dart [analyzer][pub:analyzer] to allow resolution of code -that needs static analysis and/or code generation. +## The `Builder` interface -## Implementing your own Builders - -A `Builder` gets invoked one by one on it's inputs, and may read other files and -output new files based on those inputs. - -The basic API looks like this: +A builder implements the +[Builder](https://pub.dev/documentation/build/latest/build/Builder-class.html) +interface. ```dart abstract class Builder { - /// You can only output files that are configured here by suffix substitution. - /// You are not required to output all of these files, but no other builder - /// may declare the same outputs. + /// Declares inputs and outputs by extension. Map> get buildExtensions; - /// This is where you build and output files. + /// Builds all outputs for a single input. FutureOr build(BuildStep buildStep); } ``` -Here is an implementation of a `Builder` which just copies files to other files -with the same name, but an additional extension: +Its `buildExtensions` getter declares what inputs it runs on and what outputs +it might produce. -```dart -import 'package:build/build.dart'; +During a build its `build` method gets called once per matching input. + +It uses `buildStep` to read, analyze and write files. -/// A really simple [Builder], it just makes copies of .txt files! +For example, here is a builder that copies input `.txt` files to `.txt.copy` files: + +```dart class CopyBuilder implements Builder { @override final buildExtensions = const { @@ -49,106 +53,34 @@ class CopyBuilder implements Builder { @override Future build(BuildStep buildStep) async { - // Each `buildStep` has a single input. - var inputId = buildStep.inputId; + // Create the output ID from the build step input ID. + final inputId = buildStep.inputId; + final outputId = inputId.addExtension('.copy'); - // Create a new target `AssetId` based on the old one. - var copy = inputId.addExtension('.copy'); - var contents = await buildStep.readAsString(inputId); - - // Write out the new asset. - await buildStep.writeAsString(copy, contents); + // Read from the input, write to the output. + final contents = await buildStep.readAsString(inputId); + await buildStep.writeAsString(outputId, contents); } } ``` -It should be noted that you should _never_ touch the file system directly. Go -through the `buildStep#readAsString` and `buildStep#writeAsString` methods in -order to read and write assets. This is what enables the package to track all of -your dependencies and do incremental rebuilds. It is also what enables your -[`Builder`][dartdoc:Builder] to run on different environments. +Outputs are optional. For example, a builder that is activated by a particular +annotation will output nothing if it does not find that annotation. ### Using the analyzer -If you need to do analyzer resolution, you can use the `BuildStep#resolver` -object. This makes sure that all `Builder`s in the system share the same -analysis context, which greatly speeds up the overall system when multiple -`Builder`s are doing resolution. - -Here is an example of a `Builder` which uses the `resolve` method: - -```dart -import 'package:build/build.dart'; - -class ResolvingCopyBuilder implements Builder { - // Take a `.dart` file as input so that the Resolver has code to resolve - @override - final buildExtensions = const { - '.dart': ['.dart.copy'] - }; - - @override - Future build(BuildStep buildStep) async { - // Get the `LibraryElement` for the primary input. - var entryLib = await buildStep.inputLibrary; - // Resolves all libraries reachable from the primary input. - var resolver = buildStep.resolver; - // Get a `LibraryElement` for another asset. - var libFromAsset = await resolver.libraryFor( - AssetId.resolve(Uri.parse('some_import.dart'), - from: buildStep.inputId)); - // Or get a `LibraryElement` by name. - var libByName = await resolver.findLibraryByName('my.library'); - } -} -``` - -Once you have gotten a `LibraryElement` using one of the methods on `Resolver`, -you are now just using the regular `analyzer` package to explore your app. - -### Sharing expensive objects across build steps - -The build package includes a `Resource` class, which can give you an instance -of an expensive object that is guaranteed to be unique across builds, but may -be re-used by multiple build steps within a single build (to the extent that -the implementation allows). It also gives you a way of disposing of your -resource at the end of its lifecycle. - -The `Resource` constructor takes a single required argument which is a -factory function that returns a `FutureOr`. There is also a named argument -`dispose` which is called at the end of life for the resource, with the -instance that should be disposed. This returns a `FutureOr`. - -So a simple example `Resource` would look like this: - -```dart -final resource = Resource( - () => createMyExpensiveResource(), - dispose: (instance) async { - await instance.doSomeCleanup(); - }); -``` - -You can get an instance of the underlying resource by using the -`BuildStep#fetchResource` method, whose type signature looks like -`Future fetchResource(Resource)`. - -**Important Note**: It may be tempting to try and use a `Resource` instance to -cache information from previous build steps (or even assets), but this should -be avoided because it can break the soundness of the build, and may introduce -subtle bugs for incremental builds (remember the whole build doesn't run every -time!). The `build` package relies on the `BuildStep#canRead` and -`BuildStep#readAs*` methods to track build step dependencies, so sidestepping -those can and will break the dependency tracking, resulting in inconsistent and -stale assets. +The `buildStep` passed to `build` gives easy access to the analyzer for +processing Dart source code. -## Features and bugs +Use `buildStep.resolver.compilationUnitFor` to parse a single source file, or +`libraryFor` to fully resolve it. This can be used to introspect the full API +of the source code the builder is running on. For example, a builder can learn +enough about a class's field and field types to correctly serialize it. -Please file feature requests and bugs at the [issue tracker][tracker]. +## Examples -[tracker]: https://github.com/dart-lang/build/issues +There are some simple examples +[in the build repo](https://github.com/dart-lang/build/blob/master/example). -[dartdoc:Builder]: https://pub.dev/documentation/build/latest/build/Builder-class.html -[dartdoc:BuildStep]: https://pub.dev/documentation/build/latest/build/BuildStep-class.html -[dartdoc:Resolver]: https://pub.dev/documentation/build/latest/build/Resolver-class.html -[pub:analyzer]: https://pub.dev/packages/analyzer +For real examples of builders, see the list of popular builders in the +[build_runner package documentation](https://pub.dev/packages/build_runner). \ No newline at end of file diff --git a/build_config/CHANGELOG.md b/build_config/CHANGELOG.md index a4ae2a5696..9ce41d6ef2 100644 --- a/build_config/CHANGELOG.md +++ b/build_config/CHANGELOG.md @@ -5,6 +5,7 @@ for more information. - Bump the min sdk to 3.7.0. - Remove unused dep: `yaml`. +- Documentation revamp. ## 1.1.2 diff --git a/build_config/README.md b/build_config/README.md index e1d7441112..92f3475385 100644 --- a/build_config/README.md +++ b/build_config/README.md @@ -1,14 +1,32 @@ -# Customizing builds - -Customizing the build behavior of a package is done by creating a `build.yaml` -file, which describes your configuration. - -The full format is described in the +_Questions? Suggestions? Found a bug? Please +[file an issue](https://github.com/dart-lang/build/issues) or + [start a discussion](https://github.com/dart-lang/build/discussions)._ + +Configuration file format for +[build_runner](https://pub.dev/packages/build_runner) +builds. + +- [See also: build_yaml_format.md](#see-also-build_yaml_formatmd) +- [Dividing a package into build targets](#dividing-a-package-into-build-targets) +- [Configuring builders applied to your package](#configuring-builders-applied-to-your-package) +- [Configuring builders globally](#configuring-builders-globally) +- [Defining builders to apply to depenents](#defining-builders-to-apply-to-dependents) +- [Defining post process builders](#defining-post-process-builders) +- [Adjusting builder ordering](#adjusting-builder-ordering) +- [Triggers](#triggers) +- [Publishing build.yaml files](#publishing-buildyaml-files) +- [FAQ](#faq) + - [How do I avoid running builders on unnecessary inputs?](#how-do-i-avoid-running-builders-on-unnecessary-inputs) + - [How is the configuration for a builder resolved?](#how-is-the-configuration-for-a-builder-resolved) + - [How can I include additional sources in my build?](#how-can-i-include-additional-sources-in-my-build) + +## See also: build_yaml_format.md + +See also [docs/build_yaml_format.md](https://github.com/dart-lang/build/blob/master/docs/build_yaml_format.md) -file, while this documentation is more focused on specific usage scenarios of -the file. +for a more technical description of the format. -## Dividing a package into Build targets +## Dividing a package into build targets When a `Builder` should be applied to a subset of files in a package the package can be broken up into multiple 'targets'. Targets are configured in the @@ -35,7 +53,8 @@ Each target may also contain the following keys: (from the `pubspec.yaml`). - **builders**: Map, Optional. See "configuring builders" below. -## Configuring `Builder`s applied to your package +## Configuring builders applied to your package + Each target can specify a `builders` key which configures the builders which are applied to that target. The value is a Map from builder to configuration for that builder. The key is in the format `'$packageName:$builderName'`. The @@ -63,7 +82,7 @@ configuration may have the following keys: depending on the particular builder. The values in this map override Builder defaults or non mode-specific options when the build is done in release mode. -## Configuring `Builder`s globally +## Configuring builders globally Target level builder options can be overridden globally across all packages with the `global_options` section. These options are applied _after_ all Builder defaults and target level configuration, and _before_ `--define` command line @@ -83,7 +102,7 @@ arguments. depending on the particular builder. The values in this map override all other values per-key when the build is done in release mode. -## Defining `Builder`s to apply to dependents +## Defining builders to apply to dependents If users of your package need to apply some code generation to their package, then you can define `Builder`s and have those applied to packages with a @@ -158,7 +177,7 @@ builders: some_key: "Some value the users will want in release mode" ``` -## Defining `PostProcessBuilder`s +## Defining post process builders `PostProcessBuilder`s are configured similarly to normal `Builder`s, but they have some different/missing options. @@ -209,7 +228,7 @@ post_process_builders: [adjusting builder ordering]: #adjusting-builder-ordering -### Adjusting Builder Ordering +## Adjusting builder ordering Both `required_inputs` and `runs_before` can be used to tweak the order that Builders run in on a given target. These work by indicating a given builder is a @@ -307,7 +326,7 @@ triggers: - annotation NewAnnotation ``` -# Publishing `build.yaml` files +## Publishing `build.yaml` files `build.yaml` configuration should be published to pub with the package and checked in to source control. Whenever a package is published with a @@ -315,3 +334,99 @@ checked in to source control. Whenever a package is published with a the package consuming the config has a compatible version. Breaking version changes which do not impact the configuration file format will be clearly marked in the changelog. + +## FAQ + +### How do I avoid running builders on unnecessary inputs? + +You can skip unnecessary inputs and so speed up your build using the +`generate_for` option of the builder: + +``` +targets: + $default: + builders: + # Typically the builder key is just the package name, run + # `dart run build_runner doctor` to check your config. + : + generate_for: + # Example glob for only the Dart files under `lib/models` + - lib/models/*.dart +``` + +### How is the configuration for a builder resolved? + +Builders are constructed with a map of options which is resolved from the +builder specified defaults and user overrides. The configuration is specific to +a `target` and build mode. The configuration is "merged" one by one, where +the higher precedence configuration overrides values by String key. The order +of precedence from lowest to highest is: + +- Builder defaults without a mode. +- Builder defaults by mode. +- Target configuration without a mode. +- Target configuration by mode. +- Global options without a mode. +- Global options by mode. +- Options specified on the command line. + +For example: + +```yaml +builders: + some_builder: + # Some required fields omitted + defaults: + options: + some_option: "Priority 0" + release_options: + some_option: "Priority 1" + dev_options: + some_option: "Priority 1" +targets: + $default: + builders: + some_package:some_builder: + options: + some_option: "Priority 2" + release_options: + some_option: "Priority 3" + dev_options: + some_option: "Priority 3" + +global_options: + some_package:some_builder: + options: + some_option: "Priority 4" + release_options: + some_option: "Priority 5" + dev_options: + some_option: "Priority 5" +``` + +And when running the build: + +``` +dart run build_runner build --define=some_package:some_builder=some_option="Priority 6" +``` + +### How can I include additional sources in my build? + +The `build_runner` package defaults the included source files to directories +derived from the +[package layout conventions](https://dart.dev/tools/pub/package-layout). + +If you have additional files which you would like to be included as part of the +build, you can do that with the `sources` field on the `$default` target: + +```yaml +targets: + $default: + sources: + - my_custom_sources/** + - lib/** + - web/** + # Note that it is important to include these in the default target. + - pubspec.* + - $package$ +``` \ No newline at end of file diff --git a/build_runner/CHANGELOG.md b/build_runner/CHANGELOG.md index 60ba7aef8f..56e10e0460 100644 --- a/build_runner/CHANGELOG.md +++ b/build_runner/CHANGELOG.md @@ -7,6 +7,7 @@ for more information. - Remove interactive prompts for whether to delete files. - Ignore `-d` flag: always delete files as if `-d` was passed. +- Documentation revamp. ## 2.6.1 diff --git a/build_runner/README.md b/build_runner/README.md index 4bbe396666..cd1edcf962 100644 --- a/build_runner/README.md +++ b/build_runner/README.md @@ -1,243 +1,204 @@ -

- Standalone generator and watcher for Dart using package:build. -
- - Issues related to build_runner - - - Pub Package Version - - - Latest Dartdocs - -

- -The `build_runner` package provides a concrete way of generating files using -Dart code. Files are always generated directly on disk, and -rebuilds are _incremental_ - inspired by tools such as [Bazel][]. - -> **NOTE**: Are you a user of this package? You may be interested in -> simplified user-facing documentation, such as our -> [getting started guide][getting-started-link] and [faq][faq-link]. - -[getting-started-link]: https://github.com/dart-lang/build/blob/master/docs/getting_started.md -[faq-link]: https://github.com/dart-lang/build/blob/master/docs/faq.md -[other-docs-link]: https://github.com/dart-lang/build/tree/master/docs - -* [Installation](#installation) -* [Usage](#usage) - * [Built-in commands](#built-in-commands) - * [Inputs](#inputs) - * [Outputs](#outputs) - * [Source control](#source-control) - * [Publishing packages](#publishing-packages) -* [Docs](#docs) -* [Contributing](#contributing) - * [Testing](#testing) - -## Installation - -This package is intended to support development of Dart projects with -[`package:build`][]. In general, add it to your [`pubspec.yaml`][pubspec] -as a [dev_dependencies][] by running the following command. - -```console -$ dart pub add dev:build_runner +_Questions? Suggestions? Found a bug? Please +[file an issue](https://github.com/dart-lang/build/issues) or + [start a discussion](https://github.com/dart-lang/build/discussions)._ + +Code generation for Dart and Flutter packages. + +- [Builders](#builders) +- [Getting started](#getting-started) + - [Install builders](#install-builders) + - [Build and watch](#build-and-watch) + - [Output files](#output-files) + - [Internal files](#internal-files) + - [Additional configuration](#additional-configuration) +- [Writing your own builder](#writing-your-own-builder) + +## Builders + +A `build_runner` code generator is called a _builder_. + +Usually, a builder adds some capability to your code that is inconvenient to +add and maintain in pure Dart. Examples include serialization, data classes, +data binding, dependency injection, and mocking. + +Here are some popular builders and the capabilities they add: + +|Builder|Adds capabilities| +|-|-| +|[auto_route_generator](https://pub.dev/packages/auto_route)|Flutter navigation| +|[built_value_generator](https://pub.dev/packages/built_value)|data classes with JSON serialization| +|[chopper_generator](https://pub.dev/packages/chopper_generator)|REST HTTP client| +|[copy_with_extension_gen](https://pub.dev/packages/copy_with_extension_gen)|`copyWith` extension methods| +|[dart_mappable_builder](https://pub.dev/packages/dart_mappable)|data classes with JSON serialization| +|[drift_dev](https://pub.dev/packages/drift_dev)|reactive data binding and SQL| +|[envied_generator](https://pub.dev/packages/envied)|environment variable bindings| +|[freezed](https://pub.dev/packages/freezed)|data classes, tagged unions, nested classes, cloning| +|[flutter_gen_runner](https://pub.dev/packages/flutter_gen_runner)|Flutter asset bindings| +|[go_router_builder](https://pub.dev/packages/go_router_builder)|Flutter navigation| +|[hive_ce_generator](https://pub.dev/packages/hive_ce)|key-value database| +|[injectable_generator](https://pub.dev/packages/injectable_generator)|dependency injecton| +|[json_serializable](https://pub.dev/packages/json_serializable)|JSON serialization| +|[mockito](https://pub.dev/packages/mockito)|mocks and fakes for testing| +|[retrofit_generator](https://pub.dev/packages/retrofit_generator)|REST HTTP client| +|[riverpod_generator](https://pub.dev/packages/riverpod)|reactive caching and data binding| +|[slang_build_runner](https://pub.dev/packages/slang)|type-safe i18n| +|[swagger_dart_code_generator](https://pub.dev/packages/swagger_dart_code_generator)|dart types from Swagger/OpenAPI schemas| +|[theme_tailor](https://pub.dev/packages/theme_tailor)|Flutter themes and extensions| +|[webdev](https://pub.dev/packages/webdev)|compilation to javascript| + +## Getting started + +### Install builders + +Find builders that look useful, perhaps via the list above, and follow their +"getting started" guides. + +The guides will take you through adding the necessary dependencies to your +package, then how to write code that activates the builder's capabilities. +Most builders are activated via an annotation that tells the builder to run +and what exactly it should do. + +For example, after following the `json_serializable` guide you will have these +dependencies in your `pubspec.yaml`: + +```yaml +dependencies: + json_annotation: ^4.9.0 + +dev_dependencies: + build_runner: ^2.6.0 + json_serializable: ^6.10.0 ``` -## Usage +and activate it with code like -When the packages providing `Builder`s are configured with a `build.yaml` file -they are designed to be consumed using an generated build script. Most builders -should need little or no configuration, see the documentation provided with the -Builder to decide whether the build needs to be customized. If it does you may -also provide a `build.yaml` with the configuration. See the -`package:build_config` README for more information on this file. +```dart +import 'package:json_annotation/json_annotation.dart'; -To have web code compiled to js add a `dev_dependency` on `build_web_compilers`. +// Include the file that the builder will generate. +part 'example.g.dart';. -## Docs +// Activate the builder. +@JsonSerializable() +class Person { + final String name; + final DateTime? dateOfBirth; -More comprehensive documentation is stored in this repository, under the -[docs][other-docs-link] directory. If you find something is undocumented, please -file an issue. + Person({required this.name, this.dateOfBirth}); -### Built-in Commands + // Wire up the generated `toJson` in `example.g.dart`. + Map toJson() => _$PersonToJson(this); -The `build_runner` package exposes a binary by the same name, which can be -invoked using `dart run build_runner `. - -The available commands are `build`, `watch`, `serve`, and `test`. - -- `build`: Runs a single build and exits. -- `watch`: Runs a persistent build server that watches the files system for - edits and does rebuilds as necessary. -- `serve`: Same as `watch`, but runs a development server as well. - - By default this serves the `web` and `test` directories, on port `8080` and - `8081` respectively. See below for how to configure this. -- `test`: Runs a single build, creates a merged output directory, and then runs - `dart run test --precompiled `. See below for instructions - on passing custom args to the test command. - -#### Command Line Options - -All the above commands support the following arguments: - -- `--help`: Print usage information for the command. -- `--[no-]fail-on-severe`: Whether to consider the build a failure on an error - logged. By default this is false. -- `--build-filter`: Build filters allow you to choose explicitly which files to - build instead of building entire directories. See further documentation on - this feature [here][partial_builds]. - -Some commands also have additional options: - -##### serve + // Wire up the generated `fromJson` in `example.g.dart`. + factory Person.fromJson(Map json) => _$PersonFromJson(json); +} +``` -- `--hostname`: The host to run the server on. -- `--live-reload`: Enables automatic page reloading on rebuilds. +—see [the json_serializable documentation](https://pub.dev/packages/json_serializable) for more detail. -Trailing args of the form `:` are supported to customize what -directories are served, and on what ports. +### Build and watch -For example to serve the `example` and `web` directories on ports 8000 and 8001 -you would do `dart run build_runner serve example:8000 web:8001`. +Once you have installed builders in your package, use the terminal to do a single build -##### test +```bash +cd +dart run build_runner build +``` -The test command will forward any arguments after an empty `--` arg to the -`dart run test` command. +or to launch "watch mode", which runs a build whenever your source code changes: -For example if you wanted to pass `-p chrome` you would do -`dart run build_runner test -- -p chrome`. +```bash +cd +dart run build_runner watch +``` -### Inputs +So, for example, in the `json_serializable` example, watch mode updates the +generated `toJson` and `fromJson` as you add or remove fields from the +`Person` class. + +```dart +@JsonSerializable() +class Person { + final String name; + final DateTime? dateOfBirth; + // Added. + final int age; + + // Updated manually. + Person({required this.name, this.dateOfBirth, this.age}); + + // No change needed, the generated implementations referenced get updated. + Map toJson() => _$PersonToJson(this); + factory Person.fromJson(Map json) => _$PersonFromJson(json); +} +``` -Valid inputs follow the general dart package rules. You can read any files under -the top level `lib` folder any package dependency, and you can read all files -from the current package. +If you have multiple packages then you need to run `build` or `watch` in each +package separately; there is an +[open feature request for workspace support](https://github.com/dart-lang/build/issues/3804). -In general it is best to be as specific as possible with your `InputSet`s, -because all matching files will be checked against a `Builder`'s -[`buildExtensions`][build_extensions] - see [outputs](#outputs) for more -information. +### Output files -### Outputs +Output is written directly to your package source, for example under `lib`. +This makes it immediately available to all tools including compilers and IDEs. -* You may output files anywhere in the current package. +You can choose whether or not to check generated files into source control. -> **NOTE**: When a `BuilderApplication` specifies `hideOutput: true` it may -> output under the `lib` folder of _any_ package you depend on. +If you publish your package, you must publish the generated files with it. +Users getting your package via `pub` cannot run the build step themselves. -* Builders are not allowed to overwrite existing files, only create new ones. -* Outputs from previous builds will not be treated as inputs to later ones. -* You may use a previous `BuilderApplications`'s outputs as an input to a later - action. +### Internal files -### Source control +`build_runner`uses a folder called `.dart_tool` in your package for internal files. +These are private to `build_runner` and should not be edited, checked in, +published or used in any other way. -This package creates a top level `.dart_tool` folder in your package, which -should not be submitted to your source control repository. You can see [our own -`.gitignore`](https://github.com/dart-lang/build/blob/master/.gitignore) as an -example. +So, tools such as `git` must be configured to ignore them. Make `git` ignore `.dart_tool` by adding to your `.gitignore` file: -```git -# Files generated by dart tools +```bash .dart_tool ``` -When it comes to _generated_ files it is generally best to not submit them to -source control, but a specific `Builder` may provide a recommendation otherwise. - -It should be noted that if you do submit generated files to your repo then when -you change branches or merge in changes you may get a warning on your next build -about declared outputs that already exist. This will be followed up with a -prompt to delete those files. You can type `l` to list the files, and then type -`y` to delete them if everything looks correct. If you think something is wrong -you can type `n` to abandon the build without taking any action. - -### Publishing packages - -In general generated files **should** be published with your package, but this -may not always be the case. Some `Builder`s may provide a recommendation for -this as well. - +### Additional configuration -## Legacy Usage +Builders can be further configured with a `build.yaml` file in your package's +root folder. -If the generated script does not do everything you need it's possible to -manually write one. With this approach every package which *uses* a -[`Builder`][builder] must have it's own script, they cannot be reused -from other packages. A package which defines a [`Builder`][builder] may have an -example you can reference, but a unique script must be written for the consuming -packages as well. You can reference the generated script at -`.dart_tool/build/entrypoint/build.dart` for an example. +For example, you can restrict which files in your package a builder runs for: -Your script should the [**`run`**][run_fn] functions defined in this library. - -### Configuring - -[`run`][run_fn] has a required parameter which is a `List`. -These correspond to the `BuilderDefinition` class from `package:build_config`. -See `apply` and `applyToRoot` to create instances of this class. These will be -translated into actions by crawling through dependencies. The order of this list -is important. Each Builder may read the generated outputs of any Builder that -ran on a package earlier in the dependency graph, but for the package it is -running on it may only read the generated outputs from Builders earlier in the -list of `BuilderApplication`s. - -**NOTE**: Any time you change your build script (or any of its dependencies), -the next build will be a full rebuild. This is because the system has no way -of knowing how that change may have affected the outputs. - -## Contributing - -We welcome a diverse set of contributions, including, but not limited to: - -* [Filing bugs and feature requests][file_an_issue] -* [Send a pull request][pull_request] -* Or, create something awesome using this API and share with us and others! - -For the stability of the API and existing users, consider opening an issue -first before implementing a large new feature or breaking an API. For smaller -changes (like documentation, minor bug fixes), just send a pull request. - -### Testing - -All pull requests are validated against CI, and must pass. The -`build_runner` package lives in a mono repository with other `build` packages, -and _all_ of the following checks must pass for _each_ package. - -Ensure code passes all our [analyzer checks][analysis_options]: - -```sh -$ dart analyze . +```yaml +targets: + $default: + builders: + json_serializable: + generate_for: + # Only run `json_serializable` on source under `lib/models`. + - lib/models/*.dart ``` -Ensure all code is formatted with the latest [dev-channel SDK][dev_sdk]. - -```sh -$ dart format . +Occasionally when using multiple builders you will need to specify which order +they run in. For full details on this and other options see the +[build_config documentation](https://pub.dev/packages/build_config). + +Some settings apply to a specific builder, for example `freezed`: + +```yaml +targets: + $default: + builders: + freezed: + options: + # Do format output. + format: true + # Don't generate `copyWith` or `operator==`. + copy_with: false + equal: false ``` -Run all of our unit tests: +—see each builder's documentation for details. -```sh -$ dart run test -``` +## Writing your own builder + +For advanced use cases it's possible to write your own builder. -[Bazel]: https://bazel.build/ -[`package:build`]: https://pub.dev/packages/build -[analysis_options]: https://github.com/dart-lang/build/blob/master/analysis_options.yaml - -[builder]: https://pub.dev/documentation/build/latest/build/Builder-class.html -[run_fn]: https://pub.dev/documentation/build_runner/latest/build_runner/run.html -[builder_application]: https://pub.dev/documentation/build_runner/latest/build_runner/BuilderApplication-class.html -[build_extensions]: https://pub.dev/documentation/build/latest/build/Builder/buildExtensions.html -[partial_builds]: https://github.com/dart-lang/build/blob/master/docs/partial_builds.md - -[dev_sdk]: https://dart.dev/get-dart -[dev_dependencies]: https://dart.dev/tools/pub/dependencies#dev-dependencies -[pubspec]: https://dart.dev/tools/pub/pubspec -[file_an_issue]: https://github.com/dart-lang/build/issues/new -[pull_request]: https://github.com/dart-lang/build/pulls +Get started with the [build package documentation](https://pub.dev/packages/build). diff --git a/build_test/CHANGELOG.md b/build_test/CHANGELOG.md index b49065a3d6..aa716a6e70 100644 --- a/build_test/CHANGELOG.md +++ b/build_test/CHANGELOG.md @@ -2,6 +2,7 @@ - Use `build` 3.0.2. - Use `build_runner` 2.7.0. +- Documentation revamp. ## 3.3.1 diff --git a/build_test/README.md b/build_test/README.md index 0576737a4e..8e1bce881d 100644 --- a/build_test/README.md +++ b/build_test/README.md @@ -1,87 +1,26 @@ -

- Testing utilities for users of package:build. -
- - Issues related to build_test - - - Pub Package Version - - - Latest Dartdocs - - - Join the chat on Gitter - -

+_Questions? Suggestions? Found a bug? Please +[file an issue](https://github.com/dart-lang/build/issues) or + [start a discussion](https://github.com/dart-lang/build/discussions)._ -## Installation +Test helpers for [build_runner](https://pub.dev/packages/build_runner) builders. -This package is intended to only be as a [development dependency][] for users -of [`package:build`][], and should not be used in any production code. Simply -add to your `pubspec.yaml`: +- [In-memory builds](#in-memory-builds) +- [In-memory builds with real sources](#in-memory-builds-with-real-sources) +- [Resolving source code](#resolving-source-code) -```yaml -dev_dependencies: - build_test: ^3.0.0 -``` - -## Running tests - -To run tests, you should go through the `dart run build_runner test` command. -This will compile all your tests to a temp directory and run them using -`dart run test`. If you would like to see the output directory, you can use the -`--output=` option to force the output to go to a specific place. - -### Forwarding additional args to `dart run test` - -It is very common to need to pass some arguments through to the eventual call -to `dart run test`. To do this, add all those args after an empty `--` arg. - -For example, to run all chrome platform tests you would do -`dart run build_runner test -- -p chrome`. - -## Debugging web tests - -This package will automatically create `*.debug.html` files next to all your -`*_test.dart` files, which can be loaded in a browser from the normal -development server (`dart run build_runner serve`). - -**Note:** In order to run the tests this way, you will need to configure them -to be compiled (by default we only compile `*.browser_test.dart` files). You -can do this in your build.yaml file, with something like the following: - -```yaml -targets: - $default: - builders: - build_web_compilers:entrypoint: - generate_for: - - test/**_test.dart - - web/**.dart -``` +### In-memory builds -You may also view an index of links to every `*.debug.html` file by navigating -to `http://localhost:8081` (or wherever your `test` folder is being served). +The [testBuilders][api:testBuilders] method provides a way to run builds in +memory for small, self contained tests. See the `test` folder in the `build` package for examples. -## Writing tests for your custom Builder +### In-memory builds with real sources -In addition to assiting in running normal tests, this package provides some -utilities for testing your custom `Builder` classes. +To pass sources on disk to `testBuilders`, create a +[TestReaderWriter][api:TestReaderWriter]. -_See the `test` folder in the `build` package for more examples_. - -### Run a `Builder` within a test environment - -Using [`testBuilder`][api:testBuilder], you can run a functional test of a -`Builder`, including feeding specific assets, and more. It automatically -creates an in-memory representation of various utility classes. - -### Exposing actual package sources to `testBuilder` - -To pass sources on disk to `testBuilder`, create a `TestReaderWriter`. You can -write individual sources to it from a `PackageAssetReader`, or write all sources -to it with `loadIsolateSources`: +You can write individual sources to it from a +[PackageAssetReader][api:PackageAssetReader], or write all sources to it with +`loadIsolateSources`: ```dart final readerWriter = TestReaderWriter(rootPackage: 'test_package'); @@ -98,12 +37,10 @@ class TestClass {} ); ``` -### Resolve source code for testing +### Resolving source code -Using [`resolveAsset`][api:resolveAsset] and -[`resolveSource`][api:resolveSource], you can resolve Dart source code into a -static element model, suitable for probing and using within tests of code you -might have written for a `Builder`: +Use [resolveAsset][api:resolveAsset] or +[resolveSource][api:resolveSource] to resolve code with the analyzer: ```dart test('should resolve a simple dart file', () async { @@ -117,19 +54,8 @@ test('should resolve a simple dart file', () async { }); ``` -### Various test implementations of classes - -* [`FakeWatcher`][api:FakeWatcher] -* [`TestReaderWriter`][api:TestReaderWriter] -* [`PackageAssetReader`][api:PackageAssetReader] - -[development dependency]: https://dart.dev/tools/pub/dependencies#dev-dependencies -[`package:build`]: https://pub.dev/packages/build - -[api:FakeWatcher]: https://pub.dev/documentation/build_test/latest/build_test/FakeWatcher-class.html -[api:TestReaderWriter]: https://pub.dev/documentation/build_test/latest/build_test/TestReaderWriter-class.html [api:PackageAssetReader]: https://pub.dev/documentation/build_test/latest/build_test/PackageAssetReader-class.html - [api:resolveAsset]: https://pub.dev/documentation/build_test/latest/build_test/resolveAsset.html [api:resolveSource]: https://pub.dev/documentation/build_test/latest/build_test/resolveSource.html -[api:testBuilder]: https://pub.dev/documentation/build_test/latest/build_test/testBuilder.html +[api:testBuilders]: https://pub.dev/documentation/build_test/latest/build_test/testBuilders.html +[api:TestReaderWriter]: https://pub.dev/documentation/build_test/latest/build_test/TestReaderWriter-class.html diff --git a/build_web_compilers/CHANGELOG.md b/build_web_compilers/CHANGELOG.md index 19e961bb71..85e4276991 100644 --- a/build_web_compilers/CHANGELOG.md +++ b/build_web_compilers/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.2.2-wip + +- Documentation revamp. + ## 4.2.1 - Remove unused deps: `build_config`. diff --git a/build_web_compilers/README.md b/build_web_compilers/README.md index d03d6ab246..ab5a7ec3aa 100644 --- a/build_web_compilers/README.md +++ b/build_web_compilers/README.md @@ -1,24 +1,12 @@ -

- Web compilers for users of package:build. -
- - Issues related to build_web_compilers - - - Pub Package Version - - - Latest Dartdocs - - - Join the chat on Gitter - -

- -* [Installation](#installation) -* [Usage](#usage) -* [Configuration](#configuration) -* [Manual Usage](#manual-usage) + _Questions? Suggestions? Found a bug? Please +[file an issue](https://github.com/dart-lang/build/issues) or + [start a discussion](https://github.com/dart-lang/build/discussions)._ + + Web compilers for [build_runner](https://pub.dev/packages/build_runner). + +- [Installation](#installation) +- [Usage](#usage) +- [Configuration](#configuration) ## Installation @@ -234,80 +222,6 @@ targets: - -DANOTHER_VAR=true ``` -### Legacy builder options - -Previous versions of `build_web_compilers` only supported a single enabled -compiler that would be enabled with the `compiler` option. -If you only want to use `dart2js` for all builds, you can use that option: - -```yaml -targets: - $default: - builders: - build_web_compilers:entrypoint: - # These are globs for the entrypoints you want to compile. - generate_for: - - test/**.browser_test.dart - - web/**.dart - options: - compiler: dart2js - # List any dart2js specific args here, or omit it. - dart2js_args: - - -O2 -``` - -Similarly, only compiling with `dart2wasm`: - -```yaml -targets: - $default: - builders: - build_web_compilers:entrypoint: - options: - compiler: dart2wasm - # List flags that should be forwarded to `dart compile wasm` - dart2wasm_args: - - -O2 -``` - -When no option is set, the `compiler` option is implicitly set to `dart2js` on -release builds and to `dartdevc` otherwise. -Note that the `compilers` option takes precedence over the `compiler` option -when set. - -## Manual Usage - -If you are using a custom build script, you will need to add the following -builder applications to what you already have, almost certainly at the end of -the list (unless you need to post-process the js files). - -```dart -[ - apply( - 'build_web_compilers:ddc', - [ - (_) => new ModuleBuilder(), - (_) => new UnlinkedSummaryBuilder(), - (_) => new LinkedSummaryBuilder(), - (_) => new DevCompilerBuilder() - ], - toAllPackages(), - // Recommended, but not required. This makes it so only modules that are - // imported by entrypoints get compiled. - isOptional: true, - hideOutput: true), - apply('build_web_compilers:entrypoint', - // You can also use `WebCompiler.Dart2Js`. If you don't care about - // dartdevc at all you may also omit the previous builder application - // entirely. - [(_) => new WebEntrypointBuilder(WebCompiler.DartDevc)], toRoot(), - hideOutput: true, - // These globs should match your entrypoints only. - defaultGenerateFor: const InputSet( - include: const ['web/**', 'test/**.browser_test.dart'])), -] -``` - [development dependency]: https://dart.dev/tools/pub/dependencies#dev-dependencies [Dart development compiler]: https://dart.dev/tools/dartdevc [`package:build`]: https://pub.dev/packages/build diff --git a/build_web_compilers/pubspec.yaml b/build_web_compilers/pubspec.yaml index a2958a7543..66171ea101 100644 --- a/build_web_compilers/pubspec.yaml +++ b/build_web_compilers/pubspec.yaml @@ -1,5 +1,5 @@ name: build_web_compilers -version: 4.2.1 +version: 4.2.2-wip description: Builder implementations wrapping the dart2js and DDC compilers. repository: https://github.com/dart-lang/build/tree/master/build_web_compilers resolution: workspace diff --git a/docs/builder_author_faq.md b/docs/builder_author_faq.md deleted file mode 100644 index 1de979c372..0000000000 --- a/docs/builder_author_faq.md +++ /dev/null @@ -1,115 +0,0 @@ -## When should a Builder build to `cache` vs `source`? - -Outputs to `source` will generally be published with the package on pub. **This -can be risky.** If the generated code depends on _any_ details from the current -pub solve - that is it reads information from dependencies - then a consumer of -the package which has different versions of dependencies in their pub solve -**may be broken**. If the generated code imports any libraries, including from -the package providing the builder, it must only use the API surface area which -is guaranteed to not break without a major version bump. - -Outputs to `cache` will never be published with the package, and if they are -required to compile or run, then the build system must be used by every consumer -of the code. **This is always safe**, but may place limitations on the end user. -Any outputs which are used _during_ a build to produce other outputs, but don't -need to be compiled or seen by the user, should also be built to `cache`. - -## How expensive is it to get a resolved library (ex: buildStep.inputLibrary) - -This can be a very expensive operation, depending on a number of factors. - -The first time this is done in the build process, all transitive imports of the -file have to be parsed and analyzed, and even the entire SDK may have to be -analyzed. - -We have some optimizations to make this cheaper for subsequent builders, but -they can be circumvented by certain package structures. You should assume the -cost will be at least on the order of the number of all transitive imports. - -The build step will also be invalidated if any transitive import of the resolved -library changes, even in the best case scenarios. - -You should only use a resolved library if you absolutely need on. If you can -use simply a parsed compilation unit instead, you should consider using that. - -## How can I have temporary outputs only used during the Build? - -Due to build restrictions - namely that a builder can't read the outputs -produced by other builders in the same phase - it's sometimes necessary to write -information to a temporary file in one phase, then read that in a subsequent -phase, but the intermediate result is not a useful output outside of the build. - -Use a `PostProcessBuilder` to "delete" files so they are not included in the -merged output directory or available through the development server. Note that -files are never deleted from disk, instead a "delete" by a `PostProcessBuilder` -acts a filter on what assets can be seen in the result of the build. This works -best if temporary assets have a unique extension. - -The `FileDeletingBuilder` from the `build` package is designed for this case and -only needs to be configured with the extensions it should remove. In some cases -the builder should only operate in release mode so the files can see be seen in -development mode - use the `isEnabled` argument to the constructor rather than -returning a different builder or passing a different set of extensions - if the -extensions change between modes it will invalidate the entire build. - -For example: - -```dart -// In lib/builder.dart -PostProcessBuilder temporaryFileCleanup(BuilderOptions options) => - FileDeletingBuilder(const ['.used_during_build'], - isEnabled: options.config['enabled'] as bool? ?? false); -Builder writesTemporary([_]) => ... -Builder readsTemporaryWritesPermanent([_]) => ... -``` - -```yaml -builders: - my_builder: - import: "package:my_package/builders.dart" - builder_factories: - - writesTemporary - - readsTemporaryWritesPermanent - build_extensions: - .dart: - - .used_during_build - - .output_for_real - auto_apply: dependents - applies_builders: - - my_package|temporary_file_cleanup -post_process_builders: - temporary_file_cleanup: - import: "package:my_package/builders.dart" - builder_factory: temporaryFileCleanup - defaults: - release_options: - enabled: true -``` - -## How can I debug my builder? - -After running a build, or by running the `generate-build-script` command, a -build script will be written to `.dart_tool/build/entrypoint/build.dart`. This -is a Dart VM application that can be run manually, including with debugging -enabled. See the [devtool docs][] or [IntelliJ debugging docs][] -for usage instructions. The build script takes the same arguments as `dart run -build_runner`, for example: - -`dart --observe --pause-isolates-on-start .dart_tool/build/entrypoint/build.dart -build` - -[devtool docs]:https://dart.dev/tools/dart-devtools -[IntelliJ debugging docs]:https://www.jetbrains.com/help/idea/dart.html#dart_run_debug_command_line_application - -## Why can't my builder resolve code output by another builder? - -A builder may only read a generated output if it is ordered _after_ the builder -that emitted it. Ordering can be adjusted using the `runs_before` or -`required_inputs` configuration options for builders. In particular this can be -tricky for the `SharedPartBuilder` from `package:source_gen`. When using this -utility it is the `source_gen:combining_builder` which emits the Dart code in a -`.g.dart` file, and this always runs after all builders emitting `.g.part` -files. No `SharedPartBuilder` will be able to resolve the Dart code emitted by -another `SharedPartBuilder`. In order for emitted code to be used with the -`Resolver` by later build steps, it must write to a `.dart` file directly, and -should be a different file extension than `.g.dart`. diff --git a/docs/faq.md b/docs/faq.md deleted file mode 100644 index d5bcccc014..0000000000 --- a/docs/faq.md +++ /dev/null @@ -1,454 +0,0 @@ -## How do I avoid running builders on unnecessary inputs? - -Slow builds are often the result of builders that run on all Dart files in your -package, and analyze them. In this case you can speed up your builds by telling -those builders exactly which files they should run on. - -You can do this in your `build.yaml` file, by configuring the `generate_for` -option of the builder: - -``` -targets: - $default: - builders: - # Typically the builder key is just the package name, run - # `dart run build_runner doctor` to check your config. - : - generate_for: - # Example glob for only the Dart files under `lib/models` - - lib/models/*.dart -``` - -## Where are the generated files? - -There are 3 places you might see files getting generated. On _every_ build files -might go to _cache_ (`.dart_tool/build/generated/*`), and _source_ (the working -tree of your package). These are determined by the `build_to` configuration of -the Builders you are using. When a Builder specifies `build_to: source` you will -see them next to your other files but should not edit them by hand, and they are -generally meant to be published with your package. If you see a warning about -"conflicting outputs" they refer to _source_ outputs, because when the build -tool is starting with no prior information it can't tell if it might be -overwriting some file you wrote by hand. - -Separately the `--output` option can specify a directory to create a _merged_ -view of all the files in the build system. This copies _hand written source_ -files, along with _source_ and _cache_ outputs and puts them all together in the -same directory structure. - -## How can I debug my release mode web app (dart2js)? - -By default, the `dart2js` compiler is only enabled in `--release` mode, which -does not include source maps or the original `.dart` files. If you need to debug -an error which only happens in `dart2js`, you will want to change your debug -mode compiler to `dart2js`. You can either do this using the `--define` command -line option: - -```text ---define "build_web_compilers:entrypoint=compiler=dart2js" -``` - -Or by editing your `build.yaml` file: - -```yaml -targets: - $default: - builders: - build_web_compilers:entrypoint: - options: - compiler: dart2js -``` - -## How can I build with multiple configurations? - -The build system supports two types of builds, "dev" and "release". By default -with `build_runner` the "dev" version is built by regardless of the command -used, build in release mode by passing the `--release` flag. With `webdev` the -default mode for the `serve` command is dev, and the default mode for the -`build` command is release. The `build` command can use dev mode with the -`--no-release` flag. - -Options can be configured per mode, and they are -[merged by key](#how-is-the-configuration-for-a-builder-resolved) with the -defaults provided by the builder and global overrides. The `options` field -defines configuration used in all modes, and the `dev` and `release` fields -defines the overrides to those defaults for the specific mode chosen. Builders -can define their own defaults by mode which is overridden by user config. For -example `build_web_compilers` defines options that use `dartdevc` compiler in -dev mode, and `dart2js` in release mode. - -The following configuration builds with `dart2js` always, passes `--no-minify` -in dev mode, and passed `-O3` in release mode: - -```yaml -targets: - $default: - builders: - build_web_compilers:entrypoint: - options: - compiler: dart2js - dev_options: - dart2js_args: - - --no-minify - release_options: - dart2js_args: - - -O3 -``` - -If you need other configurations in addition to dev and release, you can define -multiple `build.yaml` files. For instance if you have a `build.debug.yaml` file -you can build with `--config debug` and this file will be used instead of the -default `build.yaml`. The dev and release flavors still apply. `dart run -build_runner serve --config debug` will use the `dev_options` in -`build.debug.yaml`, while `dart run build_runner build --config debug --release` -will use the `release_options` in `build.debug.yaml`. - -Only one build flavor can be built at a time. It is not possible to have -multiple targets defined which set different builder options for the same set of -sources. Builds will overwrite generated files in the build cache, so flipping -between build configurations may be less performant than building the same build -configuration repeatedly. - -## How is the configuration for a builder resolved? - -Builders are constructed with a map of options which is resolved from the -builder specified defaults and user overrides. The configuration is specific to -a `target` and [build mode](#how-can-i-build-with-multiple-configurations). The -configuration is "merged" one by one, where the higher precedence configuration -overrides values by String key. The order of precedence from lowest to highest -is: - -- Builder defaults without a mode. -- Builder defaults by mode. -- Target configuration without a mode. -- Target configuration by mode. -- Global options without a mode. -- Global options by mode. -- Options specified on the command line. - -For example: - -```yaml -builders: - some_builder: - # Some required fields omitted - defaults: - options: - some_option: "Priority 0" - release_options: - some_option: "Priority 1" - dev_options: - some_option: "Priority 1" -targets: - $default: - builders: - some_package:some_builder: - options: - some_option: "Priority 2" - release_options: - some_option: "Priority 3" - dev_options: - some_option: "Priority 3" - -global_options: - some_package:some_builder: - options: - some_option: "Priority 4" - release_options: - some_option: "Priority 5" - dev_options: - some_option: "Priority 5" -``` - -And when running the build: - -``` -dart run build_runner build --define=some_package:some_builder=some_option="Priority 6" -``` - -## How can I include additional sources in my build? - -The `build_runner` package defaults the included source files to directories -derived from the -[package layout conventions](https://dart.dev/tools/pub/package-layout). - -If you have additional files which you would like to be included as part of the -build, you will need a custom `build.yaml` file. You will want to modify the -`sources` field on the `$default` target: - -```yaml -targets: - $default: - sources: - - my_custom_sources/** - - lib/** - - web/** - # Note that it is important to include these in the default target. - - pubspec.* - - $package$ -``` - -## Why do Builders need unique outputs? - -`build_runner` relies on determining a static build graph before starting a -build - it needs to know every file that may be written and which Builder would -write it. If multiple Builders are configured to (possibly) output the same file -you can: - -- Add a `generate_for` configuration for one or both Builders so they do not - both operate on the same primary input. -- Disable one of the Builders if it is unneeded. -- Contact the author of the Builder and ask that a more unique output - extension is chosen. -- Contact the author of the Builder and ask that a more unique input extension - is chosen, for example only generating for files that end in - `_something.dart` rather than all files that end in `.dart`. - -## How can I use my own development server to serve generated files? - -There are 2 options for using a different server during development: - -1. Run `build_runner serve web:` and proxy the requests to it from your - other server. This has the benefit of delaying requests while a build is - ongoing so you don't get an inconsistent set of assets. - -2. Run `build_runner watch --output web:build` and use the created `build/` - directory to serve files from. This will include a `build/packages` - directory that has these files in it. - -## How can I fix `AssetNotFoundException`s for swap files? - -Some editors create swap files during saves, and while build_runner uses some -heuristics to try and ignore these, it isn't perfect and we can't hardcode -knowledge about all editors. - -One option is to disable this feature in your editor. Another option is you can -explicitly ignore files with a given extension by configuring the `exclude` -option for your targets `sources` in `build.yaml`: - -```yaml -targets: - $default: - sources: - exclude: - # Example that excludes intellij's swap files - - **/*___jb_tmp___ -``` - -## Why are some logs "(cached)"? - -`build_runner` will only run actions that have changes in their inputs. When an -action fails, and a subsequent build has exactly the same inputs for that action -it will not be rerun - the previous error messages, however, will get reprinted -to avoid confusion if a build fails with no printed errors. To force the action -to run again make an edit to any file that is an input to that action, or throw -away all cached values with `dart run build_runner clean` before starting the -next build. - -## How can I resolve "Skipped compiling" warnings? - -These generally come up in the context of a multi-platform package (generally -due to a mixture of vm and web tests). It can also happen if you have imports -to the `lib/src` directory of any package, even your own. - -The errors tend to look like this: - -```text -[WARNING] build_web_compilers:entrypoint on example|test/my_test.dart: - -Skipping compiling example|test/my_test.dart for the web because some of its -transitive libraries have sdk dependencies that not supported on this platform: - -example|test/imports_dart_io.dart -``` - -### Multi-platform packages - -While we are smart enough not to attempt to compile your web tests for the vm, -it is slow for us to figure that out so we print this warning to encourage you -to set up the proper configuration so we will never even attempt to compile -these tests. - -You can set up this configuration in your `build.yaml` file, using the -`generate_for` option on the builder. It helps a lot if you separate your web -and vm tests into separate directories, but you don't have to. - -For example, your `build.yaml` might look like this: - -```yaml -targets: - $default: - builders: - build_web_compilers:entrypoint: - generate_for: - - test/multiplatform/**_test.dart - - test/web/**_test.dart - - web/**.dart -``` - -### Imports of "private" libraries under lib/src - -We group libraries together into "modules" to optimize compilation, and that -grouping is based on the public imports of the package, as well as things like -any file containing a main function gets its own module. - -This means any time you have a package import that starts with `src/` in the -path, you might end up actually pulling in a module which contains additional -libraries which were not depended on by the actual library you imported. - -This can be very confusing, because tools that search for transitive imports -will not find the libraries that the error is complaining about not being -supported on the current platform. - -The best solution to this problem, is to import only public libraries. If you -cannot do that, you can opt out of this module grouping, by using the `fine` -module strategy, but this will come with a compile cost. - -If the import is in your own package, you can add this to your build.yaml: - -```yaml -targets: - $default: - builders: - build_web_compilers:ddc_modules: - options: - strategy: fine - build_web_compilers:dart2js_modules: - options: - strategy: fine -``` - -If it is to another package, you will need to do this as either a global -override (which will likely have a large negative effect on build times): - -```yaml -global_options: - builders: - build_web_compilers:ddc_modules: - options: - strategy: fine - build_web_compilers:dart2js_modules: - options: - strategy: fine -``` - -Or, override the entire `build.yaml` file for the package you depend on. -This would look like the local package override, but would go in a -`.build.yaml` file. If that package has its own build.yaml file -already, you will need to copy over its contents before adding the additional -configuration. - -## Why can't I see a file I know exists? - -A file may not be served or be present in the output of a build because: - -- You may be looking for it in the wrong place. For example if a server for - the `web/` directory is running on port `8080` then the file at - `web/index.html` will be loaded from `localhost:8080/index.html`. -- It may have be excluded from the build entirely because it isn't present as - in the `sources` for any `target` in `build.yaml`. Only assets that are - present in the build (as either a source or a generated output from a - source) can be served. -- It may have been removed by a `PostProcessBuilder`. For example in release - modes, by default, the `build_web_compilers` package enables a - `dart_source_cleanup` builder that removes all `.dart` source files. - -## Configuring the number of compiler processes - -Some builders run multiple compiler processes in order to speed up compilation. - -The amount of parallelism per task can be configured using the environment -variable `BUILD_MAX_WORKERS_PER_TASK`. - -The "tasks" in this case refer to different types of compilation (ie: different -compilers). There are least 3 different compilers which may be a part of any -given build - `kernel`, `dartdevc`, and `dart2js`. - -## How can I reduce the amount of memory used by the build process? - -By default most files in a typical build are cached in memory, but this can -cause problems in memory constrained environments (such as CI systems). - -You can pass the `--low-resources-mode` to disable this file caching. - -We may add future optimizations for this mode as well, with the general -principle being making the tradeoff of worse build times for less resource -usage on the machine. - -See also [Configuring the number of compiler processes](#configuring-the-number-of-compiler-processes). - -## How can I setup my editor to work with `build.yaml` files? - -A schema for valid keys and values in build configuration files is available on -[SchemaStore.org](https://www.schemastore.org/dart-build.json), but it is not -assigned to any file names by default. You can configure your editor to use the -correct schema. - -### VS Code - -When using VS Code, you can use the [YAML extension] by RedHat to validate the -schema of build configuration files. -Add the following snippet to your `settings.json` to use the correct schema for -`build.yaml` files: - -```json -"yaml.schemas": { - "https://json.schemastore.org/dart-build": [ - "build.yaml", - "*.build.yaml", - "build.*.yaml" - ] -} -``` - -### IntelliJ-based editors (e.g. IDEA, Android Studio, Webstorm) - -JetBrains IDEs have builtin support for YAML schema verification, but the -correct schema for `build.yaml` files needs to be configured here too. -To do so, open Settings and select "Languages & Frameworks", "Schemas and -DTDs" and "JSON Schema Mappings". -Add a new configuration with `https://json.schemastore.org/dart-build.json` as -a schema URL. The configuration should look similar to this: - -![Schema configuration for IDEA based IDEs](images/idea_schema_config.png) - -[YAML extension]: https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml - -## How can I adjust builder ordering? - -You can configure certain builders to run before other builders globally, using the -`global_options` configuration in your `build.yaml` file: - -```yaml -global_options: - some_package:some_builder: - runs_before: - - some_other_package:some_other_builder -``` - -## Unable to read asset, could not compute transitive deps - -If you see this error, it means that we tried to compute the transitive -dependencies of a library, but some of those dependencies did not (yet) exist. - -Typically this would be caused by having multiple `target` definitions in your -`build.yaml` file, but not setting up the proper `dependencies` between them. - -For example, lets say you have 2 targets "a" and "b". Target "b" does some code -generation, and target "a" imports some of those generate files. You will need -to add a dependency on the "b" target from the "a" target like so: - -```yaml -targets: - a: - sources: - - lib/a.dart - dependencies: - - :b - b: - sources: - - lib/b.dart // Assume some builder generates lib/b.g.dart in this target. -``` - -If you are still having problems, you can file an issue on this repo and ask for -help. diff --git a/docs/getting_started.md b/docs/getting_started.md deleted file mode 100644 index 9d3be163fd..0000000000 --- a/docs/getting_started.md +++ /dev/null @@ -1,116 +0,0 @@ -# Getting started with `build_runner` - -To use `build_runner`, you need a 2.x version of the Dart SDK. - -* [Automated installers](https://dart.dev/get-dart#install) -* [Direct downloads](https://dart.dev/get-dart/archive#dev-channel) - -If you have issues using `build_runner`, see the -[Troubleshooting section](#troubleshooting), below. - -- [Getting started with `build_runner`](#getting-started-with-build_runner) - - [Using `build_runner` as a development server](#using-build_runner-as-a-development-server) - - [Creating an output directory](#creating-an-output-directory) - - [Using other `build_runner` commands](#using-other-build_runner-commands) - - [Switching to dart2js](#switching-to-dart2js) - - [Troubleshooting](#troubleshooting) - - [Diagnosing build times](#diagnosing-build-times) - - [build_runner has no versions that match...](#build_runner-has-no-versions-that-match) - - [Too many open files](#too-many-open-files) - -## Using `build_runner` as a development server - -1. Edit your package's **pubspec.yaml** file, adding dev dependencies on - **build_runner** and **build_web_compilers**: - - ```sh - dart pub add dev:build_runner dev:build_web_compilers - ``` - -2. Get package dependencies: - - ```sh - dart pub get - ``` - -3. Start the server: - - ```sh - dart run build_runner serve - ``` - -While the `serve` command runs, every change you save triggers a rebuild. - -The first build is the slowest. After that, assets are cached on disk and -incremental builds are faster. - -## Creating an output directory - -Build with `--output ` to write files into a merged output -directory with file paths that match internally referenced URIs. This can be -used with the `build`, `watch`, and `serve` commands. This directory can also be -used with a different server if the `serve` command is insufficient. - -To output only part of the package, for example to output only the `web` -directory, use `--output web:`. - -## Using other `build_runner` commands - -In addition to **serve** you can use: - -- **build:** Runs a single build and exits. This is most useful if your build - also generates output to your source directory. With `--output ` - this also creates a merged output directory with all sources and generated - assets. - -- **watch:** Like `build` but reruns after file changes. With `--output - ` the merged output directory will be kept up to date with changes. - This can be used to keep the outputs updated for use with another - filed-based development server. - -- **test:** Creates an output directory and runs `dart run test` within it. - This command requires a dev dependency on `build_test`. - -## Switching to dart2js - -By default `build_web_compilers` uses dartdevc. To switch to dart2js, pass -`--release` to `dart run build_runner build` (or `serve`). Pass args to dart2js -by creating a `build.yaml` file. - -```yaml -targets: - $default: - builders: - build_web_compilers:entrypoint: - options: - dart2js_args: - - --minify - - --fast-startup -``` - -## Troubleshooting - - - -### Diagnosing build times - -See -. - -### build_runner has no versions that match... - -1. Make sure you're using a 2.x SDK. - - ```sh - dart --version - ``` - -2. Check the versions of the packages that your app depends on. They should all - be compatible with a 2.x SDK. - -### Too many open files - -If you see a FileSystemException, saying the directory listing failed due to too -many open files, you might need to increase the OS limits. - -For details, see . diff --git a/docs/images/example_build.png b/docs/images/example_build.png deleted file mode 100644 index 5149bead5dda02a2fc4c2ea3153a2c59373915d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52314 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 JihTC_{{VgGe8>O* diff --git a/docs/images/idea_schema_config.png b/docs/images/idea_schema_config.png deleted file mode 100644 index 0e90648d94860ce81f059b94b9391b35f4e6f219..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38422 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 KMNUMnLSTZ|Lh%d$ diff --git a/docs/measuring_performance.md b/docs/measuring_performance.md deleted file mode 100644 index 00e6dc4921..0000000000 --- a/docs/measuring_performance.md +++ /dev/null @@ -1,99 +0,0 @@ -# Measuring performance with `build` and `build_runner` - -You can enable performance tracking by passing the `--log-performance ` -option (which will save logs to disk) or the `--track-performance` flag. Both of -these options will allow you to view the result in `serve` mode by navigating to -`/$perf`. On that page you will see a timeline something like this: - -![example build](images/example_build.png) - -If you are using the `--log-performance ` option that will save the logs to -disk so that you can attach them to bug reports. - -Note that for larger builds it may take a while to load the timeline. - -## Understanding the performance timeline - -Each row in the timeline corresponds to a single "action" in the build, which -is a single `Builder` being applied to a single primary input file. - -In the left hand column is the name of the builder, followed by a colon, and -then the `AssetId` for the primary input. - -The time for each action is split into at 3 primary pieces: - -- **Setup**: Primarily this is time spent checking content hashes of inputs to - see if the action needs to be reran. - - __Note__: This may also involve lazily building assets that were - optional, so seeing a long time here is not unexpected. -- **Build**: Time actually spent inside the `build` method of the `Builder`. -- **Finalize**: Time spent updating the asset graph for all outputs, and some - other cleanup. - -If the builder uses a `Resolver`, you will also see a breakdown of time spent -getting the resolver. This will appear below the `build` time since it overlaps -with it. - -### Slices - -A "slice" is a piece of actual synchronous work, up to the granularity of the -[slices resolution](#slices-resolution) configuration, visualized as a -horizontal bar in a row in the graph. It does not include asynchronous work -(unless it is less than the slice resolution). - -If [show async slices](#show-async-slices) is disabled, the granularity is -infinite, so a slice is just the entire time spent in a stage, including all -async work. - -### Stage time, slice time, user time, and real time - -Within each action (row), you can hover over one of the active time slices, -which will show several metrics, described as follows: - -**Stage time**: The start and end time (relative to the start of the build) for -the stage of the time slice you are currently hovering over. - -**Slice time**: The start and end time (relative to the start of the build) for -the slice. - -**Slice duration**: The total time spent on the current slice. - -**User time**: The actual time spent synchronously performing actions related to -the current stage. This does not count time spent waiting for asynchronous tasks. -This is generally the most relevant time, because asynchronous reads of assets -as an example may require actually building those files. - -**Real time**: The total time between the start and end time of this stage. This -includes time waiting for asynchronous tasks. - -## Configuring the timeline - -### Hide skipped actions - -Many actions in a build are "optional", which means they only run if some other -action asks to read their output. This setting toggles whether those rows -should be hidden or not. - -### Show async slices - -Off by default for performance reasons, this shows the actual synchronous points -in time during which the action was running, not including the time it spent -waiting for other async tasks. - -This shows you visually how much time it spent waiting for other async tasks, -typically other build actions or a resolver. - -### Slices resolution - -For performance reasons, when show async slices is enabled, the actual slices -are grouped together if they occur within a certain amount of time from each -other. This setting configures that granularity, and is measured in -milliseconds. - -Larger numbers will give less accurate but faster loads, smaller numbers are more -accurate but will slow down the performance of the visualization. - -### Filter - -This filters rows from the visualization based on a regex of the value in the -first column. This allows you to filter based on builder name or primary input. diff --git a/docs/partial_builds.md b/docs/partial_builds.md deleted file mode 100644 index edc281e289..0000000000 --- a/docs/partial_builds.md +++ /dev/null @@ -1,81 +0,0 @@ -# Build Filters - -Build filters allow you to choose explicitly which files to build instead of -building entire directories or projects. - -A build filter is a combination of a package and a path, with glob syntax -supported for each. - -Whenever a build filter is provided, only required outputs matching one of the -build filters will be built, in addition to any required files for those outputs. - -## Command Line Usage - -Build filters are supplied using the `--build-filter` option, which accepts -relative paths under the root package as well as `package:` uris. - -Glob syntax is allowed in both package names and paths. - -**Example**: The following would build and serve the JS output for an -application, as well as copy over the required SDK resources for that app: - -``` -dart run build_runner serve \ - --build-filter="web/main.dart.js" \ - --build-filter="package:build_web_compilers/**/*.js" -``` - -## Common Use Cases - -**Note**: For all the listed use cases it is up to the user or tool the user is -using to request all the required files for the desired task. This package only -provides the core building blocks for these use cases. - -### Testing - -If you have a large number of tests but only want to run a single one you can -now build just that test instead of all tests under the `test` directory. - -This can greatly speed up iteration times in packages with lots of tests. - -**Example**: This will build a single web test and run it: - -``` -dart run build_runner test \ - --build-filter="test/my_test.dart.browser_test.dart.js" \ - --build-filter="package:build_web_compilers/**/*.js" \ - -- -p chrome test/my_test.dart -``` - -**Note**: If your test requires any other generated files (css, etc) you will -need to add additional filters. - -### Applications - -This feature works as expected with the `--output ` and the `serve` -command. This means you can create an output directory for a single -application in your package instead of all applications under the same -directory. - -The serve command also uses the build filters to restrict what files are -available, which means it ensures if something works in serve mode it will -also work when you create an output directory. - -**Example**: This will build a single web app and serve it: - -``` -dart run build_runner serve \ - --build-filter="web/my_app.dart.js" \ - --build-filter="package:build_web_compilers/**/*.js" -``` - -**Note**: Your app may rely on additional code generated files (such as css -files), which you will need to list as additional filters. - -### Build Daemon Usage - -The build daemon accepts build filters when registering a build target. If no -filters are supplied these default filters are used: - -- `/**` -- `package:*/**` diff --git a/docs/windows_faq.md b/docs/windows_faq.md deleted file mode 100644 index b7b31d8607..0000000000 --- a/docs/windows_faq.md +++ /dev/null @@ -1,34 +0,0 @@ -When running on windows there are a few quick tips that can help your file I/O -performance. - -## Exclude your package directory from Windows Defender - -You can exclude your package entirely from windows defender by following -[these instructions](https://support.microsoft.com/en-us/help/4028485/windows-10-add-an-exclusion-to-windows-defender-antivirus). - -This gives significant speed improvements (~2x in some light testing), but also -comes with some obvious security considerations. - -### Security Considerations - -By opting into this you are potentially opening yourself up to vulnerabilities. -Any `Builder` which is being applied to your package will no longer have its -outputs checked by Windows Defender. If you don't trust your (even transitive!) -dependencies then you should be wary of this option. - -Note that the original package dependency sources are not in your package -directory but instead in your pub cache, so they will still be processed by -windows defender. - -## Hide your output directories and the `.dart_tool` directory from your IDE - -It is common for IDEs to run file watchers on your entire package in order to -update the file tree view among other things. Explicitly telling them to ignore -the `.dart_tool` directory and any directories that you commonly use with `-o` -can give a decent performance improvement. - -In `VsCode` you can do this using the `files.exclude` option in your -preferences. - -In `Intellij` you can right click on a directory, select `Mark Directory as`, -and choose `Excluded`. diff --git a/docs/writing_a_builder.md b/docs/writing_a_builder.md deleted file mode 100644 index 877b744ba8..0000000000 --- a/docs/writing_a_builder.md +++ /dev/null @@ -1,141 +0,0 @@ -# Output Restrictions - -A `Builder` must have outputs that are known statically based on input paths and -file extensions. For example an input named `foo.dart` always results in an -output named `foo.something.dart`. Builders are not allowed to read the input in -order to determine outputs. The only outputs that can be produced are those -which share a file base name with an input. - -Having a predictable set of outputs allows: - -- Ability to reason about builds. We've found that arbitrarily complex builds - tend to become difficult to debug. -- Compatibility with a wide set of build systems. A Builder that follows these - restrictions can run within `build_runner`, or in a build system like - [bazel](https://bazel.build). - -## Configuring outputs - -Each `Builder` implements a property `buildExtensions` which is a `Map>` to configure what outputs are created for 1 or more input -extensions. - -Keys in `buildExtensions` match a suffix in the path of potential inputs. That -is, a builder will run when an input ends with its input extension. -Valid outputs are formed by replacing the matched suffix with values in that -map. For instance, `{'.dart': ['.g.dart']}` matches all files ending with -`.dart` and allows the builder to write a file with the same name but with a -`.g.dart` extension instead. -A primary input `some_library.dart` would match the `.dart` suffix and expect -an output `some_library.g.dart`. - -The input extensions (keys in the `buildExtensions` map) may also start with a -`^`. In this case, the input extension changes from a suffix match to an exact -path match. For example an input extension of `^pubspec.yaml` would only match -the root pubspec file, and no other nested pubspecs. - -If a `Builder` has an empty string key in `buildExtensions` then every input -will trigger a build step, and the expected output will have the extension -appended. For example with the configuration `{'': ['.foo', '.bar']}` all files -will be passed as a primary input, and each build step may produce two assets. -For the primary input `some_file.txt` the allowed outputs are -`some_file.txt.foo` and `some_file.txt.bar`. Note that you will also see the -synthetic inputs when using this approach (`$package$` etc). You can detect -synthetic inputs by doing a `buildStep.canRead(buildStep.inputId)` check, if -you can't read it then you know it is not a normal file. - -### Capture groups - -Builders can declare more complex inputs and outputs by using a capture group -in their build input. Capture groups can be used to write outputs in a -different directory than the primary input. -For instance, consider a builder that generates Dart code for -[Protocol Buffers][protobuf]. Let's assume that proto definitions are stored in -a top-level `proto/` folder, and that generated files should go to -`lib/src/proto/`. This cannot be expressed with simple build extensions that -may replace a suffix in the asset's path only. -Using `{'proto/{{}}.proto': ['lib/src/proto/{{}}.dart']}` as a build extension -lets the builder read files in `proto/` and emit Dart files in the desired -location. Here, the __`{{}}`__ is called a _capture group_. Capture groups have -the following noteworthy properties: - -- Capture groups match at least one character in the input path, but may match - arbitrarily many characters. -- When the input uses a capture group, every output must reference that capture - group as well. -- Capture groups match as many characters as possible. In the proto example, - the asset `proto/nested/proto/test.proto` would match with `{{}}` capturing - `nested/proto/test`. The shorter suffix match with `{{}}` capturing just - `test` is not considered. -- General rules about build extensions matching suffixes still apply. When - using capture groups, the suffix typically spans across multiple path - components which is what enables directory moves. - In the proto example, the input extension might match an entire file - `proto/services/auth.proto`. With `{{}}` bound to `services/auth`, the - expected output is `lib/src/proto/services/auth.dart`. -- Build extensions using capture groups can start with `^` to enforce matches - over the entire input (which is still technically a suffix). - In the example above, the builder would also run on - `lib/src/proto/test.proto` (outputting `lib/src/lib/src/proto/test.dart`). - If the builder had used `^proto/{{}}.proto` as an input, it would not have - run on strict suffix matches. - -#### Using multiple capture groups - -A builder may use multiple capture groups in an input. Groups must be given a -name to distinguish them. For instance, `{{foo}}` declares a capture group -named `foo`. Names may consist of alphanumeric characters only. When using -multiple capture groups, they must all have unique names. And once again, every -output must refer to every capture group used in the input. - -Multiple groups come in handy when a builder needs to distinguish an asset's -directory and its file name. Consider a builder running on `.dart` files and -emitting files in a subdirectory next to the input. The following diagram -highlights the desired structure: - -``` -lib/src/ -├── generated/ -│ ├── service.api.dart (generated) -│ └── service.impl.dart (generated) -└── service.dart -``` - -This structure cannot be expressed with a single capture group. One might use -`{{}}.dart` as an input, but as `{{}}` matches the whole path there's no way to -introduce a `generated/` in the middle of the output path. - -With two capture groups, `{{dir}}/{{file}}.dart` can be used as an input. As -input extensions match suffixes, `{{file}}.dart` matches Dart files and assigns -everything between the last slash and the `.dart` extension to a capture named -`file`. Finally, `{{dir}}` captures the directory of the input. -By using `{{dir}}/generated/{{file}}.api.dart` and -`{{dir}}/generated/{{file}}.impl.dart` as output extensions, the builder may -emit files in the desired directory. - -## Working around the restrictions - -### Builders which produce an unknown number of outputs - -Often codegen is used to build Dart code - in these cases we can usually -generate all of the code in a single file. Dart does not have restrictions like -Java does - we don't need a 1:1 mapping between files and classes. - -If it's not possible to generate the output into a set of files known ahead of -time it's possible to write them to a single archive. - -### Builders which are based on an unknown number of inputs - -In Barback it was possible to write an `AggregateTransformer`, but there is no -matching concept as `Builder` - outputs must be known statically and must share -a `basename` with their input. - -In most cases the expected file is known statically, so the package can have a -placeholder (with a different extension) where that file should be created. For -example: if a Builder is meant to produce the file `lib/foo.dart` and use as -inputs existing Dart files in `lib/`. - Write an empty file to -`lib/foo.placeholder` - Use the extension config `{'.placeholder': ['.dart']}` - -Ignore the `buildStep.inputId` and find the real inputs with -`buildStep.findAssets(new Glob('lib/*dart')` - -[protobuf]: https://developers.google.com/protocol-buffers diff --git a/docs/writing_an_aggregate_builder.md b/docs/writing_an_aggregate_builder.md deleted file mode 100644 index 52517ff27b..0000000000 --- a/docs/writing_an_aggregate_builder.md +++ /dev/null @@ -1,226 +0,0 @@ -Most examples (and use-cases) for builders and generation are around reading a -single file, and outputting another file as a result. For example, -`json_serializable` emits a `.g.dart` per a `.dart` to encode/decode -to JSON, and `sass_builder` emits a `.css` per a `.scss`. - -However, sometimes you want to output one or more files based on the inputs of -_many_ files, perhaps even all of them. We call this abstractly, an _aggregate -builder_, or a builder with many inputs and one (or less) outputs. - -> **WARNING**: This pattern could have negative effects on your development -> cycle and incremental build, as it invalidates frequently (if _any_ of the -> read files change). - -## Defining your `Builder` - -Like usual, you'll implement the `Builder` class from `package:build`. Lets -write a simple builder that writes a text file called `all_files.txt` to your -`lib/` folder, which contains a listing of all the files found in `lib/**`. - -Obviously this builder isn't too useful, it's just an example! - -```dart -import 'package:build/build.dart'; - -class ListAllFilesBuilder implements Builder { - // TODO: Implement. -} -``` - -Every `Builder` needs a method, `build` implemented, and a field or getter, -`buildExtensions`. While they work the same here as any normal builder, they are -slightly more involved. Lets look at `buildExtensions` first. - -Normally to write, "generate `{file}.g.dart` for `{file.dart}`", you'd write: - -```dart -Map> get buildExtensions { - return const { - '.dart': const ['.g.dart'], - }; -} -``` - -However, we only want a single output file in (this) aggregate builder. So, -instead we will build on a _synthetic_ input - a file that does not actually -exist on disk, but rather is used as an identifier for build extensions. We -currently support the following synthetic files for this purpose: - -* `lib/$lib$` -* `$package$` - -When choosing whether to use `$package$` or `lib/$lib$`, there are two primary -considerations. - -- _where_ do you want to output your files (which directory should they be - written to). - - If you want to output to directories other than `lib`, you should use - `$package$`. - - If you want to output files only under `lib`, then use `lib/$lib$`. -- _which_ packages will this builder run on (only the root package or any - package in the dependency tree). - - If want to run on any package other than the root, you _must_ use - `lib/$lib$` since only files under `lib` are accessible from - dependencies - even synthetic files. - -## Writing the `Builder` using a synthetic input - -Each of these synthetic inputs exist if the folder exists (and is available to -the build), but they cannot be read. So, for this example, lets write one based -on `lib/$lib$`, and say that we will always emit the file `lib/all_files.txt`. - -Since out files are declared by simply replacing the declared input extension -with the declared output extensions, we can use `$lib$` as the input extension, -and `all_files.txt` as the output extension, which will declare an output at -`lib/all_files.txt`. - -**Note:** If using `$package$` as an input extension you need to declare the -full output path from the root of the package, since it lives at the root of the -package. - -```dart -import 'package:build/build.dart'; - -class ListAllFilesBuilder implements Builder { - @override - Map> get buildExtensions { - return const { - // Using r'...' is a "raw" string, so we don't interpret $lib$ as a field. - // An alternative is escaping manually, or '\$lib\$'. - r'$lib$': const ['all_files.txt'], - }; - } -} -``` - -Great! Now, to write the `build` method. Normally for a `build` method you'd -read an input, and write based on that. Again, aggregate builders work a little -differently, there is no "input" (you need to find inputs manually): - -```dart -import 'package:build/build.dart'; - -class ListAllFilesBuilder implements Builder { - @override - Future build(BuildStep buildStep) async { - // Will throw for aggregate builders, because '$lib$' isn't a real input! - buildStep.readAsString(buildStep.inputId); - } -} -``` - -Instead, we can use the `findAssets` API to find the inputs we want to process, -and create a new `AssetId` based off the current package we are processing. - -```dart -import 'package:build/build.dart'; -import 'package:glob/glob.dart'; -import 'package:path/path.dart' as p; - -class ListAllFilesBuilder implements Builder { - static final _allFilesInLib = new Glob('lib/**'); - - static AssetId _allFileOutput(BuildStep buildStep) { - return AssetId( - buildStep.inputId.package, - p.join('lib', 'all_files.txt'), - ); - } - - @override - Map> get buildExtensions { - return const { - r'$lib$': ['all_files.txt'], - }; - } - - @override - Future build(BuildStep buildStep) async { - final files = []; - await for (final input in buildStep.findAssets(_allFilesInLib)) { - files.add(input.path); - } - final output = _allFileOutput(buildStep); - return buildStep.writeAsString(output, files.join('\n')); - } -} -``` - -## Using a `Resolver` - -Since the input of aggregate builders isn't a real asset that could be read, we -also can't use `buildStep.inputLibrary` to resolve it. However some methods, -such as `libraryFor`, allow resolving any asset the builder can read. - -For instance, we could adapt the `ListAllFilesBuilder` from before to instead -list the names of all classes defined in `lib/`: - -```dart -import 'package:build/build.dart'; -import 'package:glob/glob.dart'; -import 'package:source_gen/source_gen.dart'; -import 'package:path/path.dart' as p; - -class ListAllClassesBuilder implements Builder { - @override - Map> get buildExtensions { - return const {r'$lib$': ['all_classes.txt']}; - } - - static AssetId _allFileOutput(BuildStep buildStep) { - return AssetId( - buildStep.inputId.package, - p.join('lib', 'all_classes.txt'), - ); - } - - @override - Future build(BuildStep buildStep) async { - final classNames = []; - - await for (final input in buildStep.findAssets(Glob('lib/**'))) { - final library = await buildStep.resolver.libraryFor(input); - final classesInLibrary = LibraryReader(library).classes; - - classNames.addAll(classesInLibrary.map((c) => c.name)); - } - - await buildStep.writeAsString( - _allFileOutput(buildStep), classNames.join('\n')); - } -} -``` - -As the resolver has no single entry point in aggregate builders, be aware that -[`findLibraryByName`][findLibraryByName] and [`libraries`][libraries] can only -find libraries that have been discovered through `libraryFor` or `isLibrary`. - -### Improving invalidation - -If the builder uses a `Resolver` the output will be invalidated, and the builder -will be rerun, any time there is a change in any resolved library _or any of -it's transitive imports_. If the builder output only depends on limited -information from the resolved libraries, it may be possible to invalidate the -output only when a library changes in a way that is meaningful to the builder. - -Split the process across two builders: - -1. A `Builder` with `buildExtensions` of `{'.dart': ['.some_name.info']}`. Use - the `Resolver` to find the information about the code that will be necessary - later. Serialize this to json or similar and write it as an intermediate - file. This should always be `build_to: cache`. -2. A `Builder` with `buildExtensiosn` of `{r'$lib$': ['final_output_name']}`. - Use the glob APIs to read and deserialize the outputs from the previous - step, then generate the final content. - -Each of these steps must be a separate `Builder` instance in Dart code. They can -be in the same builder definition in `build.yaml` only if they are both output -to cache. If the final result should be built to source they must be separate -builder definitions. In the single builder definition case ordering is handled -by the order of the `builder_factories` in the config. In the separate builder -definition case ordering should be handled by configuring the second step to -have a `required_inputs: ['.some_name.info']` based on the build extensions of -the first step. - -[findLibraryByName]: https://pub.dev/documentation/build/latest/build/Resolver/findLibraryByName.html -[libraries]: https://pub.dev/documentation/build/latest/build/Resolver/libraries.html From 44b0cae39b623a4a32eb0778b7e8eb5cf273d8e0 Mon Sep 17 00:00:00 2001 From: David Morgan Date: Tue, 12 Aug 2025 16:33:18 +0200 Subject: [PATCH 2/3] Address review comments. --- build_runner/README.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/build_runner/README.md b/build_runner/README.md index cd1edcf962..5e59ee5460 100644 --- a/build_runner/README.md +++ b/build_runner/README.md @@ -21,30 +21,31 @@ Usually, a builder adds some capability to your code that is inconvenient to add and maintain in pure Dart. Examples include serialization, data classes, data binding, dependency injection, and mocking. -Here are some popular builders and the capabilities they add: +Here is a selection of the most-used builders on [pub.dev](https://pub.dev). +Except as noted, they are not owned or specifically endorsed by Google. -|Builder|Adds capabilities| -|-|-| +|Builder|Adds capabilities|Notes| +|-|-|- |[auto_route_generator](https://pub.dev/packages/auto_route)|Flutter navigation| -|[built_value_generator](https://pub.dev/packages/built_value)|data classes with JSON serialization| -|[chopper_generator](https://pub.dev/packages/chopper_generator)|REST HTTP client| +|[built_value_generator](https://pub.dev/packages/built_value)|data classes with JSON serialization|[Flutter Favourite](https://docs.flutter.dev/packages-and-plugins/favorites) by Google +|[chopper_generator](https://pub.dev/packages/chopper_generator)|REST HTTP client|[Flutter Favourite](https://docs.flutter.dev/packages-and-plugins/favorites) |[copy_with_extension_gen](https://pub.dev/packages/copy_with_extension_gen)|`copyWith` extension methods| |[dart_mappable_builder](https://pub.dev/packages/dart_mappable)|data classes with JSON serialization| |[drift_dev](https://pub.dev/packages/drift_dev)|reactive data binding and SQL| |[envied_generator](https://pub.dev/packages/envied)|environment variable bindings| -|[freezed](https://pub.dev/packages/freezed)|data classes, tagged unions, nested classes, cloning| +|[freezed](https://pub.dev/packages/freezed)|data classes, tagged unions, nested classes, cloning|[Flutter Favourite](https://docs.flutter.dev/packages-and-plugins/favorites) |[flutter_gen_runner](https://pub.dev/packages/flutter_gen_runner)|Flutter asset bindings| -|[go_router_builder](https://pub.dev/packages/go_router_builder)|Flutter navigation| +|[go_router_builder](https://pub.dev/packages/go_router_builder)|Flutter navigation|by Google |[hive_ce_generator](https://pub.dev/packages/hive_ce)|key-value database| |[injectable_generator](https://pub.dev/packages/injectable_generator)|dependency injecton| -|[json_serializable](https://pub.dev/packages/json_serializable)|JSON serialization| -|[mockito](https://pub.dev/packages/mockito)|mocks and fakes for testing| +|[json_serializable](https://pub.dev/packages/json_serializable)|JSON serialization|[Flutter Favourite](https://docs.flutter.dev/packages-and-plugins/favorites) by Google +|[mockito](https://pub.dev/packages/mockito)|mocks and fakes for testing|by Google |[retrofit_generator](https://pub.dev/packages/retrofit_generator)|REST HTTP client| -|[riverpod_generator](https://pub.dev/packages/riverpod)|reactive caching and data binding| +|[riverpod_generator](https://pub.dev/packages/riverpod)|reactive caching and data binding|[Flutter Favourite](https://docs.flutter.dev/packages-and-plugins/favorites) |[slang_build_runner](https://pub.dev/packages/slang)|type-safe i18n| |[swagger_dart_code_generator](https://pub.dev/packages/swagger_dart_code_generator)|dart types from Swagger/OpenAPI schemas| |[theme_tailor](https://pub.dev/packages/theme_tailor)|Flutter themes and extensions| -|[webdev](https://pub.dev/packages/webdev)|compilation to javascript| +|[webdev](https://pub.dev/packages/webdev)|compilation to javascript|by Google ## Getting started From 95e2198f8e283c7b2e9e1caebadc4e81d44156a7 Mon Sep 17 00:00:00 2001 From: David Morgan Date: Wed, 13 Aug 2025 09:00:18 +0200 Subject: [PATCH 3/3] Address review comments. --- build_runner/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_runner/README.md b/build_runner/README.md index 5e59ee5460..b8c592170b 100644 --- a/build_runner/README.md +++ b/build_runner/README.md @@ -28,7 +28,7 @@ Except as noted, they are not owned or specifically endorsed by Google. |-|-|- |[auto_route_generator](https://pub.dev/packages/auto_route)|Flutter navigation| |[built_value_generator](https://pub.dev/packages/built_value)|data classes with JSON serialization|[Flutter Favourite](https://docs.flutter.dev/packages-and-plugins/favorites) by Google -|[chopper_generator](https://pub.dev/packages/chopper_generator)|REST HTTP client|[Flutter Favourite](https://docs.flutter.dev/packages-and-plugins/favorites) +|[chopper_generator](https://pub.dev/packages/chopper)|REST HTTP client|[Flutter Favourite](https://docs.flutter.dev/packages-and-plugins/favorites) |[copy_with_extension_gen](https://pub.dev/packages/copy_with_extension_gen)|`copyWith` extension methods| |[dart_mappable_builder](https://pub.dev/packages/dart_mappable)|data classes with JSON serialization| |[drift_dev](https://pub.dev/packages/drift_dev)|reactive data binding and SQL|