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 が必要なのか
- Dartではリフレクション(dart:mirrors)が使えない
JavaやKotlinでは、リフレクションを使えば実行時にクラス構造やアノテーションを取得できます。
しかしFlutterでは、dart:mirrors は使えません。
これはAOT(事前コンパイル)の都合上、リフレクションが非対応だからです。
つまり実行時に動的に情報を取得することができないため、
ビルド時に必要なコードを生成しておく必要があるためです。
⸻
- Dartのコンパイラにはアノテーション処理機構がない
Dartは @MyAnnotation()
のようなアノテーションをただの「メタ情報」として扱うだけで、
そこから自動でコードを生成する仕組みを持っていません。
そのため、build_runner
のような外部ツールを使って、
- アノテーションを検出
- 必要な情報を抽出
- .g.dart のようなファイルを生成
といった処理を手動で行う必要があります。
⸻
-
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 が必要になります:
- DartにはJavaのようなアノテーション処理の標準機構がない
- Flutterではリフレクション(dart:mirrors)が使えない
- build_runner がビルド時のコード生成を管理してくれるツールである
参考記事
- https://zenn.dev/kosukesaigusa/articles/dart-code-generation-1
- https://blog.pentagon.tokyo/2590/
- https://qiita.com/shiraji/items/ed674c5883ed0520791b
- https://zenn.dev/kenya_saitoh/articles/c0cb1c1344556a
- https://zenn.dev/masatoshi_tada/articles/7d18bdd0d84990
- https://kazamori.jp/blogs/2020/07/12/java-annotation-processor/
- https://blog.smartbank.co.jp/entry/2025/04/11/unlock-the-potential-of-swift-code-generation
Discussion