You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Asset transformers (docs) run a Dart package over one declared asset file. They have no way to tell flutter_tools about other files they read while transforming. So if a transformer reads file B while transforming declared asset A, editing B does not retrigger the transform. During flutter run the output stays stale until you touch A itself.
This breaks hot reload for any transformer that reads more than its single input. Examples:
A transformer that compiles a shader bundle from a manifest: the manifest lists several shader files, and those shaders #include more files. None of the referenced files are watched.
Any compiler-style transformer that follows imports or includes.
The user-visible result is confusing. You edit a referenced file, save, and nothing happens. You then have to edit the top-level declared asset (even a whitespace change) before the update shows up.
Today flutter_tools invokes a transformer as a subprocess with --input, --output, and any args declared in pubspec (packages/flutter_tools/lib/src/build_system/tools/asset_transformer.dart:114-120). There is no channel for the transformer to report which other files it read, so the dev loop only notices a change when the declared asset's own bytes change.
Alternatives considered: build hooks already have first-class dependency tracking (the hook reports a dependencies set), so the shader bundle case can be solved there. But build hooks are heavier (they require a hook/build.dart), and asset transformers are the natural lightweight, per-asset, composable option. This cannot be solved by a package on pub.dev, because the missing piece is in flutter_tools' own transformer invocation and file-watch loop.
Proposal
Let the transformer package report the files it read, and have flutter_tools watch them. The transformer is the only thing that knows its real inputs (the manifest entries it followed, the headers it included), so it produces the dependency list. flutter_tools only supplies a destination and consumes the result:
flutter_tools passes a --depfile=<path> flag to the transformer subprocess. This is a write destination, not data: it tells the transformer where to put its dependency list.
The transformer writes that file, listing every file it read (the declared asset plus anything it pulled in). A transformer that wraps a compiler can forward this straight through. impellerc, for example, already emits exactly this file ([ImpellerC] Write a depfile when --shader-bundle is in use #186341, Compiler::CreateDepfileContents).
After a successful transform, flutter_tools reads the depfile and adds the listed files to the dev-loop watch set, so editing any of them retriggers the transform.
The format is the trivial single-line Ninja form <outputs>: <input1> <input2> ..., and flutter_tools already has a Dart parser for it (DepfileService.parse in build_system/depfile.dart), which it already uses to consume depfiles emitted by other separate-process compilers such as the Dart frontend server and dart2js. So no new parser or format is introduced; this reuses the dependency format the tool already speaks.
Transformers that do not write a depfile keep today's behavior, so this is backward compatible.
Today's asset watch set is effectively static (one entry per declared asset). To watch transformer-reported dependencies it needs to become dynamic. This is the same requirement called out in #186343 for tracking FragmentProgram #include headers, so one change can cover both.
Use case
Asset transformers (docs) run a Dart package over one declared asset file. They have no way to tell
flutter_toolsabout other files they read while transforming. So if a transformer reads file B while transforming declared asset A, editing B does not retrigger the transform. Duringflutter runthe output stays stale until you touch A itself.This breaks hot reload for any transformer that reads more than its single input. Examples:
#includemore files. None of the referenced files are watched.The user-visible result is confusing. You edit a referenced file, save, and nothing happens. You then have to edit the top-level declared asset (even a whitespace change) before the update shows up.
Today
flutter_toolsinvokes a transformer as a subprocess with--input,--output, and any args declared in pubspec (packages/flutter_tools/lib/src/build_system/tools/asset_transformer.dart:114-120). There is no channel for the transformer to report which other files it read, so the dev loop only notices a change when the declared asset's own bytes change.Alternatives considered: build hooks already have first-class dependency tracking (the hook reports a
dependenciesset), so the shader bundle case can be solved there. But build hooks are heavier (they require ahook/build.dart), and asset transformers are the natural lightweight, per-asset, composable option. This cannot be solved by a package on pub.dev, because the missing piece is influtter_tools' own transformer invocation and file-watch loop.Proposal
Let the transformer package report the files it read, and have
flutter_toolswatch them. The transformer is the only thing that knows its real inputs (the manifest entries it followed, the headers it included), so it produces the dependency list.flutter_toolsonly supplies a destination and consumes the result:flutter_toolspasses a--depfile=<path>flag to the transformer subprocess. This is a write destination, not data: it tells the transformer where to put its dependency list.impellerc, for example, already emits exactly this file ([ImpellerC] Write a depfile when --shader-bundle is in use #186341,Compiler::CreateDepfileContents).flutter_toolsreads the depfile and adds the listed files to the dev-loop watch set, so editing any of them retriggers the transform.The format is the trivial single-line Ninja form
<outputs>: <input1> <input2> ..., andflutter_toolsalready has a Dart parser for it (DepfileService.parseinbuild_system/depfile.dart), which it already uses to consume depfiles emitted by other separate-process compilers such as the Dart frontend server and dart2js. So no new parser or format is introduced; this reuses the dependency format the tool already speaks.Transformers that do not write a depfile keep today's behavior, so this is backward compatible.
Today's asset watch set is effectively static (one entry per declared asset). To watch transformer-reported dependencies it needs to become dynamic. This is the same requirement called out in #186343 for tracking FragmentProgram
#includeheaders, so one change can cover both.Related
#includeheaders. Same dynamic-watch-set need, different producer.