Description
TODO
- Ensure the output directory is left untouched by the native assets builder.
-
MakeNot needed. With the current compilers wrapped, doing it in the same outputDirectory works fine.native_toolchain_c
use a subdirectory for each builder. - Add documentation.
==================
How does a hook writer producing many assets, reuse their previous build in a next run? E.g. How do they cache assets?
For example: If we have 1000 3d models in source files, and they need to be compiled to some binary format, and we change one. Then the next cold start of the flutter app will rerun the hook, and if the hook writer does not get access to their previously built binary files, they will need to rerun the "compilation" step for all 1000 assets.
This is a simpler variant than thinking about caching with hot restart in mind, but both will need similar infrastructure.
- [native_assets_cli][native_assets_builder] Hot reload and hot restart #1207
- [native_assets_cli] Dependencies should be per asset #1208 (comment)
We have two possible approaches here: (1) hook writers can check the timestamps of their own dependencies and the build outputs and on rebuild the ones which need rebuilding, or (2) the protocol reports changed dependencies and asset IDs that need rebuilding.
1. Hooks do caching internally
If the native assets builder promises to not modify the output directory in between runs, then hook writers can internally.
The hooks always output the full list of assets, and all the asset files exist after a hook run.
import 'dart:io';
import 'package:native_assets_cli/native_assets_cli.dart';
void main(List<String> args) async {
await build(args, (config, output) async {
final packageName = config.packageName;
final sourceDirectory =
Directory.fromUri(config.packageRoot.resolve('models/'));
// If assets are added, rerun hook.
output.addDependency(sourceDirectory.uri);
await for (final sourceFile in assetDirectory.list()) {
if (sourceFile is! File) {
continue;
}
final targetFile = File.fromUri(output.outputDirectory.resolve(sourceFile.replaceLast('.model', '.binary'));
if (!await targetFile.exists() || await sourceFile.lastModified() > await targetFile.lastModified()){
compile(sourceFile, targetFile)
}
// The file path relative to the package root, with forward slashes.
final name = targetFile
.toFilePath(windows: false)
.substring(config.packageRoot.toFilePath(windows: false).length);
output.addAsset(
DataAsset(
package: packageName,
name: name,
file: targetFile.uri,
),
linkInPackage: config.linkingEnabled ? packageName : null,
dependencies: [dataAsset.uri],
);
output.addDependency(
sourceFile,
);
}
});
}
For example wrapping a CMake build already works this way by default, as CMake caches stuff internally in its build folder.
On thing to consider is if a hook has multiple builders adding assets. Then those builders should likely have their own subdirectory in the output directory.
TODO:
- Ensure the output directory is left untouched by the native assets builder.
- Make
native_toolchain_c
use a subdirectory for each builder.
2. BuildConfig reports changed dependencies and assets which need to be rebuilt
An alternative design is to have hooks get a list of changed global dependencies and a map with changed asset ids as keys and which of the dependencies for each asset changed as values in the map.
Then the hook would only run the build for the changed assets and only report the changed assets.
An open question is whether this should be done inside the same directory as the initial build or not. If no, then no intermediate build artifacts can be used (CMake). If yes, we have to worry about combining all the build outputs from various runs.
It's not clear that this is beneficial for hook writers over using dart:io
. But it does add a lot of extra book keeping to the native_assets_builder
to combine the build outputs of various subsequent runs.
Hence, we suggest going with option 1.
Thanks @HosseinYousefi for triggering this discussion!
Background, only accessible for Googlers: http://go/dart-native-asset-caching
Somewhat related:
Metadata
Metadata
Assignees
Type
Projects
Status