📘

FlutterでAnnotation Processingを行うには何故build_runnerが必要なのか

に公開

結論

Dart/FlutterにはJavaのようなAnnotation Processing機構が存在しないから

~完~


だと流石に面白くないのでここからまだ掘ります。


そもそもAnnotation Processingとは

JavaやKotlinにおけるAnnotation Processingは、

コンパイル時にアノテーション付きのコードを解析してコードを自動生成する仕組みです。

代表例として以下のようなライブラリがあります

  • Dagger(DI)
  • Room(DBアクセス)

こういったライブラリは、アノテーションをもとにJavaコンパイラ(javac)の機能を利用して、

追加のソースコードを生成しています。

Dart/FlutterにはAnnotation Processingがない

DartにはJavaのような標準的なAnnotation Processingの機構がありません。

つまり、Dartのコンパイラは

アノテーションを解析してコードを生成するような仕組みを標準では提供していません。

なぜ build_runner が必要なのか

  1. Dartではリフレクション(dart:mirrors)が使えない

JavaやKotlinでは、リフレクションを使えば実行時にクラス構造やアノテーションを取得できます。

しかしFlutterでは、dart:mirrors は使えません。

これはAOT(事前コンパイル)の都合上、リフレクションが非対応だからです。

つまり実行時に動的に情報を取得することができないため、

ビルド時に必要なコードを生成しておく必要があるためです。

  1. Dartのコンパイラにはアノテーション処理機構がない

Dartは @MyAnnotation() のようなアノテーションをただの「メタ情報」として扱うだけで、

そこから自動でコードを生成する仕組みを持っていません。


そのため、build_runner のような外部ツールを使って、

  • アノテーションを検出
  • 必要な情報を抽出
  • .g.dart のようなファイルを生成

といった処理を手動で行う必要があります。

  1. build_runner はビルド全体を管理する「統括役」

Dartのコード生成はファイル単位で完結するとは限りません。

依存関係やキャッシュ、複数ジェネレーターの組み合わせなどが発生します。

build_runner はそれらを一元管理して、

最小限の差分で効率的にコード生成を行ってくれる「ビルドマネージャー」の役割を担っています。

Flutterでは build_runner + source_gen が代替手段

そこでFlutter/Dartの世界では、

Annotation Processingの代わりに次の2つのツールを組み合わせて使います:

  • build_runner:コード生成やビルドタスクを統括するツール
  • source_gen:アノテーション付きコードを解析してソースを生成するライブラリ

この2つを使うことで、アノテーションベースのコード生成が可能になります。

実際の使用例:json_serializable

()
class User {
  final String name;
  final int age;

  User(this.name, this.age);

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}


このようなクラスを定義すると、以下のコマンドで .g.dart ファイルが生成されます

flutter pub run build_runner build

このとき裏側では:

  • source_gen が User クラスを解析
  • build_runner が生成されたコードをビルドに統合

という処理が行われており、ファイルが生成されるというわけですね。

まとめ

FlutterでAnnotation Processingのようなコード生成を行うには、

以下の理由から build_runner が必要になります:

  1. DartにはJavaのようなアノテーション処理の標準機構がない
  2. Flutterではリフレクション(dart:mirrors)が使えない
  3. build_runner がビルド時のコード生成を管理してくれるツールである

参考記事

Discussion