flutter而为了提升整体的编译效率,大部分模块都被提前编译成了 snapshot 文件( 一种 Dart 的编译产物,可被 Dart VM 所运行,用于提升执行效率)
1、frontend_server:前端编译器生成 kernel 文件
2、gen_snapshot :将 dart 代码编译成 AOT 产物
1. frontend_server命令
KernelCompiler.compile() 过程等价于如下命令:
可见,通过 dart 虚拟机启动 frontend_server.dart.snapshot,将 dart 代码转换成 app.dill 形式的 kernel 文件。
frontend_server 前端编译器将 dart 代码转换为 AST,并生成 app.dill 文件,其中 bytecode 生成过程默认是关闭的。
ini
static Future<bool> checkAspectdFlutterFrontendServerSnapshot(String packagesPath) async {
final Directory flutterFrontendServerDirectory = await getFlutterFrontendServerDirectory(packagesPath);
final String aspectdFlutterFrontendServerSnapshot = globals.fs.path.join(flutterFrontendServerDirectory.absolute.path, frontendServerDartSnapshot);
final String defaultFlutterFrontendServerSnapshot = globals.artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk);
if (!globals.fs.file(aspectdFlutterFrontendServerSnapshot).existsSync()) {
final String dartSdkDir = await getDartSdkDependency((await getPackagePathFromConfig(packagesPath, 'aspectd')).absolute.path);
final String frontendServerPackageConfigJsonFile = '${flutterFrontendServerDirectory.absolute.path}/package_config.json';
final String rebasedFrontendServerPackageConfigJsonFile = '${flutterFrontendServerDirectory.absolute.path}/rebased_package_config.json';
String frontendServerPackageConfigJson = globals.fs.file(frontendServerPackageConfigJsonFile).readAsStringSync();
frontendServerPackageConfigJson = frontendServerPackageConfigJson.replaceAll('../../../third_party/dart', dartSdkDir);
globals.fs.file(rebasedFrontendServerPackageConfigJsonFile).writeAsStringSync(frontendServerPackageConfigJson);
final List<String> commands = <String>[
globals.artifacts.getArtifactPath(Artifact.engineDartBinary),
'--deterministic',
'--packages=$rebasedFrontendServerPackageConfigJsonFile',
'--snapshot=$aspectdFlutterFrontendServerSnapshot',
'--snapshot-kind=kernel',
'${flutterFrontendServerDirectory.absolute.path}/starter.dart'];
final ProcessResult processResult = await globals.processManager.run(commands);
globals.fs.file(rebasedFrontendServerPackageConfigJsonFile).deleteSync();
if (processResult.exitCode != 0 || globals.fs.file(aspectdFlutterFrontendServerSnapshot).existsSync() == false) {
throwToolExit('Aspectd unexpected error: ${processResult.stderr.toString()}');
}
String res = "";
for (String command in commands) {
res += command;
}
print("command args:" + res); } else {
print("aspectdFlutterFrontendServerSnapshot exist:"+aspectdFlutterFrontendServerSnapshot);
}
if (globals.fs.file(defaultFlutterFrontendServerSnapshot).existsSync()) {
globals.fs.file(defaultFlutterFrontendServerSnapshot).deleteSync();
}
globals.fs.file(aspectdFlutterFrontendServerSnapshot).copySync(defaultFlutterFrontendServerSnapshot);
return true;
}
命令的参数:
bash
command args:/Users/warren/env/flutter/bin/cache/dart-sdk/bin/dart--deterministic--packages=/Users/warren/Project/openSource/aspectd/lib/src/flutter_frontend_server/rebased_
package_config.json--snapshot=/Users/warren/Project/openSource/aspectd/lib/src/flutter_frontend_server/frontend_server.dart.snapshot--snapshot-kind=kernel/Users/warr
en/Project/openSource/aspectd/lib/src/flutter_frontend_server/starter.dart
这个dart命令,其实就是把我们aspectD中的starter.dart文件编译成为了frontend_server.dart.snapshot这个文件。starter.dart文件就是我们aspectD插入的编译过程的入口:
arduino
void main(List<String> args) async {
final int exitCode = await starter(args);
if (exitCode != 0) {
exit(exitCode);
}
}
最后一段:
scss
globals.fs
.file(aspectdFlutterFrontendServerSnapshot)
.copySync(defaultFlutterFrontendServerSnapshot);
这个逻辑就是把生成的frontend_server.dart.snapshot文件拷贝至flutter sdk中的对应位置
结合aspectd的编译过程:
运行之后aop方法用以下命令可查看编译后的app.dill文件内容:
dart dump_kernel.dart /Users/warren/Project/openSource/aspectd/lib/src/flutter_frontend_server/frontend_server.dart.snapshot ~/app.dill.text
2.gen_snapshot 命令
GenSnapshot.run 具体命令根据前面的封装,针对 Android 和 iOS 平台各有不同:
针对 Android:
上述命令主要是将 dart kernel 转换为机器码,对应流程图为
此处的 gen_snapshot 是一个二进制可执行文件,主要作用是将 dart 代码生成 AOT 二进制机器码。