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.

Builder Adds capabilities Notes
auto_route_generator Flutter navigation
built_value_generator data classes with JSON serialization Flutter Favourite by Google
chopper_generator REST HTTP client Flutter Favourite
copy_with_extension_gen copyWith extension methods
dart_mappable_builder data classes with JSON serialization
drift_dev reactive data binding and SQL
envied_generator environment variable bindings
freezed data classes, tagged unions, nested classes, cloning Flutter Favourite
flutter_gen_runner Flutter asset bindings
go_router_builder Flutter navigation by Google
hive_ce_generator key-value database
injectable_generator dependency injecton
json_serializable JSON serialization Flutter Favourite by Google
mockito mocks and fakes for testing by Google
retrofit_generator REST HTTP client
riverpod_generator reactive caching and data binding Flutter Favourite
slang_build_runner type-safe i18n
swagger_dart_code_generator dart types from Swagger/OpenAPI schemas
theme_tailor Flutter themes and extensions
webdev compilation to javascript by 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);
}

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.

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

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.

Writing your own builder

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

Get started with the build package documentation.

Libraries

build_runner