33// found in the LICENSE file.
44
55import 'package:package_config/package_config.dart' ;
6+ import 'package:yaml/yaml.dart' ;
67
78import '../../artifacts.dart' ;
89import '../../base/build.dart' ;
@@ -121,15 +122,17 @@ class ReleaseCopyFlutterBundle extends CopyFlutterBundle {
121122/// even though it is not listed as an input. Pub inserts a timestamp into
122123/// the file which causes unnecessary rebuilds, so instead a subset of the contents
123124/// are used an input instead.
124- class KernelSnapshot extends Target {
125- const KernelSnapshot ();
125+ ///
126+ /// This kernel snapshot is concatenated with the [KernelSnapshotNativeAssets]
127+ /// inside [KernelSnapshot] byte-wise to create the combined kernel snapshot.
128+ class KernelSnapshotProgram extends Target {
129+ const KernelSnapshotProgram ();
126130
127131 @override
128- String get name => 'kernel_snapshot ' ;
132+ String get name => 'kernel_snapshot_program ' ;
129133
130134 @override
131135 List <Source > get inputs => const < Source > [
132- Source .pattern ('{BUILD_DIR}/native_assets.yaml' ),
133136 Source .pattern ('{PROJECT_DIR}/.dart_tool/package_config_subset' ),
134137 Source .pattern ('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/common.dart' ),
135138 Source .artifact (Artifact .platformKernelDill),
@@ -139,7 +142,9 @@ class KernelSnapshot extends Target {
139142 ];
140143
141144 @override
142- List <Source > get outputs => const < Source > [];
145+ List <Source > get outputs => const < Source > [
146+ // TODO(mosuem): Should output resources.json. https://github.com/flutter/flutter/issues/146263
147+ ];
143148
144149 @override
145150 List <String > get depfiles => < String > [
@@ -148,11 +153,12 @@ class KernelSnapshot extends Target {
148153
149154 @override
150155 List <Target > get dependencies => const < Target > [
151- NativeAssets (),
152156 GenerateLocalizationsTarget (),
153157 DartPluginRegistrantTarget (),
154158 ];
155159
160+ static const String dillName = 'program.dill' ;
161+
156162 @override
157163 Future <void > build (Environment environment) async {
158164 final KernelCompiler compiler = KernelCompiler (
@@ -186,13 +192,6 @@ class KernelSnapshot extends Target {
186192 final List <String >? fileSystemRoots = environment.defines[kFileSystemRoots]? .split (',' );
187193 final String ? fileSystemScheme = environment.defines[kFileSystemScheme];
188194
189- final File nativeAssetsFile = environment.buildDir.childFile ('native_assets.yaml' );
190- final String nativeAssets = nativeAssetsFile.path;
191- if (! await nativeAssetsFile.exists ()) {
192- throwToolExit ("$nativeAssets doesn't exist." );
193- }
194- environment.logger.printTrace ('Embedding native assets mapping $nativeAssets in kernel.' );
195-
196195 TargetModel targetModel = TargetModel .flutter;
197196 if (targetPlatform == TargetPlatform .fuchsia_x64 ||
198197 targetPlatform == TargetPlatform .fuchsia_arm64) {
@@ -242,6 +241,8 @@ class KernelSnapshot extends Target {
242241 logger: environment.logger,
243242 );
244243
244+ final String dillPath = environment.buildDir.childFile (dillName).path;
245+
245246 final CompilerOutput ? output = await compiler.compile (
246247 sdkRoot: environment.artifacts.getArtifactPath (
247248 Artifact .flutterPatchedSdkPath,
@@ -252,9 +253,8 @@ class KernelSnapshot extends Target {
252253 buildMode: buildMode,
253254 trackWidgetCreation: trackWidgetCreation && buildMode != BuildMode .release,
254255 targetModel: targetModel,
255- outputFilePath: environment.buildDir.childFile ('app.dill' ).path,
256- initializeFromDill: buildMode.isPrecompiled ? null :
257- environment.buildDir.childFile ('app.dill' ).path,
256+ outputFilePath: dillPath,
257+ initializeFromDill: buildMode.isPrecompiled ? null : dillPath,
258258 packagesPath: packagesFile.path,
259259 linkPlatformKernelIn: forceLinkPlatform || buildMode.isPrecompiled,
260260 mainPath: targetFileAbsolute,
@@ -268,6 +268,109 @@ class KernelSnapshot extends Target {
268268 buildDir: environment.buildDir,
269269 targetOS: targetOS,
270270 checkDartPluginRegistry: environment.generateDartPluginRegistry,
271+ );
272+ if (output == null || output.errorCount != 0 ) {
273+ throw Exception ();
274+ }
275+ }
276+ }
277+
278+ /// Generate a kernel snapshot of the native assets mapping for resolving
279+ /// `@Native` assets at runtime.
280+ ///
281+ /// This kernel snapshot is concatenated to the [KernelSnapshotProgram]
282+ /// inside [KernelSnapshot] to create the combined kernel snapshot.
283+ class KernelSnapshotNativeAssets extends Target {
284+ const KernelSnapshotNativeAssets ();
285+
286+ @override
287+ String get name => 'kernel_snapshot_native_assets' ;
288+
289+ @override
290+ List <Source > get inputs => < Source > [
291+ const Source .pattern ('{BUILD_DIR}/native_assets.yaml' ),
292+ ...const KernelSnapshotProgram ().inputs,
293+ ];
294+
295+ @override
296+ List <Source > get outputs => const < Source > [];
297+
298+ @override
299+ List <String > get depfiles => const < String > [];
300+
301+ @override
302+ List <Target > get dependencies => < Target > [
303+ const NativeAssets (),
304+ ];
305+
306+ static const String dillName = 'native_assets.dill' ;
307+
308+ @override
309+ Future <void > build (Environment environment) async {
310+ final File nativeAssetsFile = environment.buildDir.childFile ('native_assets.yaml' );
311+ final File dillFile = environment.buildDir.childFile (dillName);
312+
313+ final YamlNode nativeAssetContents = loadYamlNode (await nativeAssetsFile.readAsString ());
314+ final Object ? nativeAssetsInYaml = (nativeAssetContents as Map <Object ?, Object ?>)['native-assets' ];
315+ if (nativeAssetsInYaml is ! Map || nativeAssetsInYaml.isEmpty) {
316+ // Write an empty file to make concatenation a no-op.
317+ // Write the file out to disk for caching.
318+ await dillFile.writeAsBytes (< int > []);
319+ return ;
320+ }
321+
322+ final KernelCompiler compiler = KernelCompiler (
323+ fileSystem: environment.fileSystem,
324+ logger: environment.logger,
325+ processManager: environment.processManager,
326+ artifacts: environment.artifacts,
327+ fileSystemRoots: < String > [],
328+ );
329+ final String ? buildModeEnvironment = environment.defines[kBuildMode];
330+ if (buildModeEnvironment == null ) {
331+ throw MissingDefineException (kBuildMode, 'kernel_snapshot' );
332+ }
333+ final String ? targetPlatformEnvironment = environment.defines[kTargetPlatform];
334+ if (targetPlatformEnvironment == null ) {
335+ throw MissingDefineException (kTargetPlatform, 'kernel_snapshot' );
336+ }
337+ final BuildMode buildMode = BuildMode .fromCliName (buildModeEnvironment);
338+ final File packagesFile = environment.projectDir
339+ .childDirectory ('.dart_tool' )
340+ .childFile ('package_config.json' );
341+
342+ final TargetPlatform targetPlatform = getTargetPlatformForName (targetPlatformEnvironment);
343+
344+ final String ? frontendServerStarterPath = environment.defines[kFrontendServerStarterPath];
345+
346+ final String nativeAssets = nativeAssetsFile.path;
347+ if (! await nativeAssetsFile.exists ()) {
348+ throwToolExit ("$nativeAssets doesn't exist." );
349+ }
350+ environment.logger.printTrace ('Embedding native assets mapping $nativeAssets in kernel.' );
351+
352+ final PackageConfig packageConfig = await loadPackageConfigWithLogging (
353+ packagesFile,
354+ logger: environment.logger,
355+ );
356+
357+ final String dillPath = dillFile.path;
358+
359+ final CompilerOutput ? output = await compiler.compile (
360+ sdkRoot: environment.artifacts.getArtifactPath (
361+ Artifact .flutterPatchedSdkPath,
362+ platform: targetPlatform,
363+ mode: buildMode,
364+ ),
365+ aot: buildMode.isPrecompiled,
366+ buildMode: buildMode,
367+ trackWidgetCreation: false ,
368+ outputFilePath: dillPath,
369+ packagesPath: packagesFile.path,
370+ frontendServerStarterPath: frontendServerStarterPath,
371+ packageConfig: packageConfig,
372+ buildDir: environment.buildDir,
373+ dartDefines: < String > [],
271374 nativeAssets: nativeAssets,
272375 );
273376 if (output == null || output.errorCount != 0 ) {
@@ -276,6 +379,43 @@ class KernelSnapshot extends Target {
276379 }
277380}
278381
382+ class KernelSnapshot extends Target {
383+ const KernelSnapshot ();
384+
385+ @override
386+ String get name => 'kernel_snapshot' ;
387+
388+ @override
389+ List <Target > get dependencies => const < Target > [
390+ KernelSnapshotProgram (),
391+ KernelSnapshotNativeAssets (),
392+ ];
393+
394+ @override
395+ List <Source > get inputs => < Source > [];
396+
397+ @override
398+ List <Source > get outputs => < Source > [];
399+
400+ static const String dillName = 'app.dill' ;
401+
402+ @override
403+ Future <void > build (Environment environment) async {
404+ final File programDill = environment.buildDir.childFile (
405+ KernelSnapshotProgram .dillName,
406+ );
407+ final File nativeAssetsDill = environment.buildDir.childFile (
408+ KernelSnapshotNativeAssets .dillName,
409+ );
410+ final File dill = environment.buildDir.childFile (dillName);
411+ await programDill.copy (dill.path);
412+ await dill.writeAsBytes (
413+ await nativeAssetsDill.readAsBytes (),
414+ mode: FileMode .append,
415+ );
416+ }
417+ }
418+
279419/// Supports compiling a dart kernel file to an ELF binary.
280420abstract class AotElfBase extends Target {
281421 const AotElfBase ();
0 commit comments