build_runner 2.16.0

SDKdart
Platformwindowslinuxmacos

A build system for Dart code generation and modular compilation.

Questions? Suggestions? Found a bug? Please file an issue or start a discussion.

Code generation for Dart and Flutter packages.

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 is a selection of the most-used builders on pub.dev. Except as noted, they are not owned or specifically endorsed by Google.

BuilderAdds capabilitiesNotes
auto_route_generatorFlutter navigation
built_value_generatordata classes with JSON serializationFlutter Favourite by Google
chopper_generatorREST HTTP clientFlutter Favourite
copy_with_extension_gencopyWith extension methods
dart_mappable_builderdata classes with JSON serialization
drift_devreactive data binding and SQL
envied_generatorenvironment variable bindings
flutter_gen_runnerFlutter asset bindings
freezeddata classes, tagged unions, nested classes, cloningFlutter Favourite
go_router_builderFlutter navigationby Google
hive_ce_generatorkey-value database
injectable_generatordependency injecton
json_serializableJSON serializationFlutter Favourite by Google
mockitomocks and fakes for testingby Google
retrofit_generatorREST HTTP client
riverpod_generatorreactive caching and data bindingFlutter Favourite
slang_build_runnertype-safe i18n
swagger_dart_code_generatordart types from Swagger/OpenAPI schemas
theme_tailorFlutter themes and extensions
webdevcompilation to javascriptby Google

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:

dependencies:
  json_annotation: ^4.9.0

dev_dependencies:
  build_runner: ^2.6.0
  json_serializable: ^6.10.0

and activate it with code like

import 'package:json_annotation/json_annotation.dart';

// Include the file that the builder will generate.
part 'example.g.dart';.

// Activate the builder.
@JsonSerializable()
class Person {
  final String name;
  final DateTime? dateOfBirth;

  Person({required this.name, this.dateOfBirth});

  // Wire up the generated `toJson` in `example.g.dart`.
  Map<String, dynamic> toJson() => _$PersonToJson(this);

  // Wire up the generated `fromJson` in `example.g.dart`.
  factory Person.fromJson(Map<String, dynamic> json) => _$PersonFromJson(json);
}

—see the json_serializable documentation for more detail.

Build and watch

Once you have installed builders in your package, use the terminal to do a single build

cd <package root folder>
dart run build_runner build

or to launch "watch mode", which runs a build whenever your source code changes:

cd <package root folder>
dart run build_runner watch

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.

@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<String, dynamic> toJson() => _$PersonToJson(this);
  factory Person.fromJson(Map<String, dynamic> json) => _$PersonFromJson(json);
}

You can build or watch more than one package together by putting them in a workspace and passing the --workspace flag. This is still experimental and subject to change based on feedback, consider giving your own feedback in the discussion forum.

Output files

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 can choose whether or not to check generated files into source control.

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.

Internal files

build_runneruses 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.

So, tools such as git must be configured to ignore them. Make git ignore .dart_tool by adding to your .gitignore file:

.dart_tool

With the --workspace flag the .dart_tool directory is written under the workspace root instead of under a package.

Additional configuration

Builders can be further configured with a build.yaml file in your package's root folder.

For example, you can restrict which files in your package a builder runs for:

targets:
  $default:
    builders:
      json_serializable:
        generate_for:
          # Only run `json_serializable` on source under `lib/models`.
          - lib/models/*.dart

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.

Some settings apply to a specific builder, for example freezed:

targets:
  $default:
    builders:
      freezed:
        options:
          # Do format output.
          format: true
          # Don't generate `copyWith` or `operator==`.
          copy_with: false
          equal: false

—see each builder's documentation for details.

With the --workspace flag package-specific options are read from each package's build.yaml file. Global options are read from the build.yaml in the workspace root, if there is one.

Writing your own builder

For advanced use cases it's possible to write your own builder.

Get started with the build package documentation. For testing builders, see the build_test package.

Debugging builds

To debug the build process, note that build_runner spawns a child process to run the build. So, the args that turn on debugging must be passed through build_runner to the child process using --dart-jit-vm-arg, for example:

dart run build_runner build --dart-jit-vm-arg=--observe --dart-jit-vm-arg=--pause-isolates-on-start

The args in the example will cause the child process to output a URL for debugging:

The Dart DevTools debugger and profiler is available at:
http://127.0.0.1:8181/3xXtAPE8msc=/devtools/?uri=ws://127.0.0.1:8181/3xXtAPE8msc=/ws

To use your IDE to debug, launch a "remote debug" session. For example in VSCode the remote debug action is called "Debug: Attach to Dart Process". It will ask for the URL to connect to: paste in the one that was printed.