run-codegen
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseRun codegen (build_runner)
运行 codegen(build_runner)
A deterministic, low-freedom runbook: regenerate all annotation-driven code in
one pass, then analyze. Run the pinned command exactly as written — do not
modify it, add flags, or hand-edit generated files. Applies whenever a source
file carries a codegen annotation (, ,
, , a drift table) and its /
/ part is missing or stale.
@freezed@JsonSerializable@riverpod@DriftDatabase*.g.dart*.freezed.dart*.drift.dart这是一份确定性且严格受限的操作手册:一次重新生成所有由注解驱动的代码,
然后执行 analyze。严格按原样运行固定命令——不要修改它、添加 flags,或
手动编辑生成文件。只要一个 source file 带有 codegen 注解(、
、、、drift table),且它的
/ / part 缺失或过期,就适用本流程。
@freezed@JsonSerializable@riverpod@DriftDatabase*.g.dart*.freezed.dart*.drift.dartNon-negotiable rules
不可违反的规则
- Run codegen BEFORE . A fresh clone, branch switch, or freshly edited annotated file has no generated part on disk. Analyzing that tree produces misleading "missing part file" and undefined-class errors that describe the missing output, not a real code defect — regenerate, then analyze.
flutter analyze - Use the pinned command verbatim, always with . Without it, build_runner refuses to overwrite an output it did not write this run and fails with a wall of "conflicting outputs" text. That is a stale-file collision, not a bug — do not go hunting for one.
--delete-conflicting-outputs - Never hand-edit a generated file. The next build silently reverts it and takes your edit with it. Change the annotated source — the drift table, the freezed class, the Notifier, the ARB — and rerun.
- Never a generated file. Whether generated code is committed or gitignored is one decision owned by
git add -f; whichever the repo chose, never force-add an artifact past the ignore rules or commit one the current source would not reproduce.codegen-and-toolchain - is a local-dev convenience, never CI or a pre-commit hook. CI and the pre-analyze step always use the one-shot
watch.build - Fix hand-written source first. The generator reads a resolved AST; it
cannot generate from source that does not analyze. An unrelated error
anywhere in can block generation of a table or provider — clear those before blaming codegen.
lib/
- 先运行 codegen,再运行 。 全新 clone、切换分支或 刚编辑过带注解的 file 时,磁盘上还没有对应的生成 part。此时分析该代码树 会产生误导性的 “missing part file” 和 undefined-class 错误;这些错误描述的 是缺失的输出,而不是真实的代码缺陷——应先重新生成,再执行 analyze。
flutter analyze - 逐字使用固定命令,并始终加上 。 如果省略它,build_runner 会拒绝覆盖本次运行未写入的生成产物,并因大量 “conflicting outputs” 文本而失败。这是 stale-file 冲突,不是 bug—— 不要为此四处查找问题。
--delete-conflicting-outputs - 绝不手动编辑生成文件。 下次 build 会在无提示的情况下将其还原, 你的编辑也会随之消失。修改带注解的 source——drift table、freezed class、 Notifier、ARB——然后重新运行。
- 绝不对生成文件执行 。 生成代码是提交到 repo 还是由 gitignore 忽略,这项决策由
git add -f统一负责;无论 repo 选择了哪一种,都不要绕过 ignore 规则强制 add artifact,也不要提交当前 source 无法重新生成的 artifact。codegen-and-toolchain - 只是本地开发的便利功能,绝不能用于 CI 或 pre-commit hook。 CI 和 pre-analyze 步骤始终使用一次性的
watch。build - 先修复手写的 source。 generator 读取的是解析完成的 AST;它无法基于
无法通过 analyze 的 source 生成代码。中任何位置的无关错误都可能 阻断 table 或 provider 的生成——先解决这些问题,再去怀疑 codegen。
lib/
The canonical command
固定命令
Run from the package root (single-package app) or the workspace root
(multi-package repo):
bash
dart run build_runner build --delete-conflicting-outputsThis is the first step in every CI lane and on every fresh clone, before format
and analyze.
从 package 根目录(单 package app)或 workspace 根目录(多 package repo)运行:
bash
dart run build_runner build --delete-conflicting-outputs在每条 CI lane 和每次全新 clone 后,都必须先执行这一步,再执行 format
和 analyze。
Standard sequence on a fresh clone, pull, or branch switch
全新 clone、pull 或切换分支后的标准流程
- (resolve dependencies).
flutter pub get - (regenerate).
dart run build_runner build --delete-conflicting-outputs - Only then .
flutter analyze
Skipping step 2 is the single most common cause of a red analyzer on a clone
whose code is actually fine.
- (解析 dependencies)。
flutter pub get - (重新生成)。
dart run build_runner build --delete-conflicting-outputs - 之后才运行 。
flutter analyze
跳过步骤 2,是代码本身完全正常的 clone 出现 analyzer 变红的最常见原因。
Dev iteration (optional watch)
开发迭代(可选 watch)
For an active edit loop on annotated sources, run the watcher instead of a
one-shot build; it rebuilds affected outputs on save:
bash
dart run build_runner watch --delete-conflicting-outputsStop the watcher before running the one-shot — two concurrent
build_runner processes over the same tree race on outputs.
build对带注解的 source 进行高频编辑时,可以运行 watcher 代替一次性 build;
保存时会重新构建受影响的 outputs:
bash
dart run build_runner watch --delete-conflicting-outputs运行一次性 前先停止 watcher——两个 build_runner 进程同时操作同一
代码树时,会在 outputs 上产生竞态。
buildWhen multi-package (workspace)
多 package(workspace)时
build_runner runs per-package: one invocation regenerates the current package
plus its path-dependency packages, not automatically every sibling in the
workspace. So running the single command at the workspace root covers the
root package and its path dependencies in one pass, but a coordinator-style root
that does not itself depend on every member will not regenerate those siblings.
For full multi-package regeneration, use the repo-level fan-out wrapper (e.g.
) that runs the command over every workspace member; prefer it
when the workspace is bootstrapped. To deliberately scope one package during
development, run the same command from that package's directory. Builder scoping
(which files each builder reads) lives in each package's , owned by
.
melos run genbuild.yamlcodegen-and-toolchainbuild_runner 按 package 运行:一次调用会重新生成当前 package 及其
path-dependency packages,但不会自动重新生成 workspace 中的所有 sibling
packages。因此,在 workspace 根目录运行这条单一命令,可以一次覆盖根 package
及其 path dependencies;不过,若根 package 采用 coordinator 形式,并且自身不
依赖所有成员,就不会重新生成那些 sibling packages。
若要完整重新生成多 package 内容,请使用 repo 级 fan-out wrapper(例如
),它会对每个 workspace member 运行该命令;如果 workspace
已完成初始化,应优先使用这种方式。开发期间如需明确限定到某个 package,
请从该 package 的目录运行相同命令。Builder scoping(每个 builder 读取哪些
文件)记录在各 package 的 中,由 负责。
melos run genbuild.yamlcodegen-and-toolchainWhen codegen and the analyzer disagree
codegen 与 analyzer 不一致时
The analyzer reads files on disk; build_runner writes them. A disagreement
almost always means the disk is behind, not that the code is wrong.
| Symptom | Do this |
|---|---|
| Analyzer flags an undefined class/getter that codegen should produce | Rerun the pinned build, then restart the analysis server. Do not "fix" the call site. |
Errors reported inside a | The file is stale or the analyzer excludes are wrong. Regenerate first; never hand-edit generated output. |
| build_runner fails with analyzer errors in hand-written source | Fix the hand-written source — the generator cannot resolve an unanalyzable AST. |
| "Conflicting outputs" wall of text | Re-run with |
analyzer 读取磁盘上的文件;build_runner 则负责写入。二者不一致几乎总是
说明磁盘内容落后,而不是代码有误。
| 症状 | 应执行的操作 |
|---|---|
| Analyzer 标记了 codegen 应生成的 undefined class/getter | 重新运行固定 build,然后重启 analysis server。不要去“修复”调用点。 |
错误报告在 | 文件已过期,或 analyzer excludes 配置有误。先重新生成;绝不手动编辑 generated output。 |
| build_runner 因手写 source 中的 analyzer 错误而失败 | 修复手写 source——generator 无法解析无法通过 analyze 的 AST。 |
| 出现大量 “Conflicting outputs” 文本 | 使用 |
Anti-patterns
反模式
- Running before codegen on a fresh tree — you chase phantom missing-part errors that regeneration erases.
flutter analyze - Dropping — the first rename or deletion fails the whole run on a stale-output collision.
--delete-conflicting-outputs - Editing a /
.g.dart/.freezed.dartby hand — the next build reverts it; the fix belongs in the annotated source..drift.dart - on a gitignored generated file — bypasses the repo's committed-vs-gitignored decision and ships a possibly-stale artifact.
git add -f - in CI or a pre-commit hook — non-deterministic; CI must use the one-shot
build_runner watch.build
- 在全新代码树上先运行 ,后运行 codegen——你会追查 重新生成后便会消失的虚假 missing-part 错误。
flutter analyze - 省略 ——第一次发生重命名或删除时, 整个运行就会因 stale-output 冲突而失败。
--delete-conflicting-outputs - 手动编辑 /
.g.dart/.freezed.dart——下次 build 会将其 还原;正确的修复位置是带注解的 source。.drift.dart - 对被 gitignore 的生成文件执行 ——这会绕过 repo 关于 generated code 提交与忽略的决策,并交付可能已过期的 artifact。
git add -f - 在 CI 或 pre-commit hook 中运行 ——不具备确定性; CI 必须使用一次性的
build_runner watch。build
Definition of done
完成标准
- The pinned ran at the package/workspace root without "conflicting outputs" errors.
dart run build_runner build --delete-conflicting-outputs - It ran before , which is now green.
flutter analyze - No generated file was hand-edited or force-added.
- No process is wired into CI or hooks.
build_runner watch
- 固定的 已在 package/workspace 根目录运行完成,且没有 “conflicting outputs” 错误。
dart run build_runner build --delete-conflicting-outputs - 它在 之前运行,且现在 analyze 已通过。
flutter analyze - 没有手动编辑或强制 add 任何生成文件。
- 没有将任何 进程接入 CI 或 hooks。
build_runner watch
Related skills
相关 skills
- See for the knowledge behind this runbook:
codegen-and-toolchainbuilder scoping, the commit-vs-gitignore-generated-code decision, SDK pinning, and analyzer/coverage excludes for generated files.build.yaml - See for the drift schema-snapshot and migration ritual that wraps
run-migrationaround this codegen pass.drift_dev make-migrations - See for the CI freshness gate that reruns this command and diffs the tree.
ci-pipeline-and-gates - See for the analyzer excludes that keep generated files out of lint scope.
lint-and-style-config
- 有关本手册背后的原理,请参阅 :
codegen-and-toolchainbuilder scoping、generated code 提交与 gitignore 的决策、 SDK pinning,以及 generated files 的 analyzer/coverage excludes。build.yaml - 有关 drift schema-snapshot 和 migration 的完整流程,请参阅 ; 该流程将
run-migration编排在此 codegen pass 前后。drift_dev make-migrations - 有关会重新运行此命令并对代码树执行 diff 的 CI freshness gate,请参阅
。
ci-pipeline-and-gates - 有关将 generated files 排除在 lint scope 之外的 analyzer excludes,请参阅
。
lint-and-style-config
References
参考
- build_runner: https://pub.dev/packages/build_runner
- Dart tools — build_runner usage: https://dart.dev/tools/build_runner
- drift codegen: https://drift.simonbinder.eu/docs/getting-started/
- freezed: https://pub.dev/packages/freezed
- riverpod_generator: https://pub.dev/packages/riverpod_generator
- build_runner:https://pub.dev/packages/build_runner
- Dart 工具——build_runner 用法:https://dart.dev/tools/build_runner
- drift codegen:https://drift.simonbinder.eu/docs/getting-started/
- freezed:https://pub.dev/packages/freezed
- riverpod_generator:https://pub.dev/packages/riverpod_generator