热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

flutter生成源代码_[译]Flutter的编译模式

[译]Flutter的编译模式原文使用过Flutter构建APP的人可能有个疑惑,Flutter的编译产物有时候是一个共享库,有时候是几个文件ÿ
c6d6c5245d1e4ff7be62659b7322d103.png

[译]Flutter 的编译模式

原文

使用过 Flutter 构建 APP 的人可能有个疑惑,Flutter 的编译产物有时候是一个共享库,有时候是几个文件,比较难于理解,本文主要介绍 Flutter 中的编译模式。

编译模式分类

源代码需要编译才能运行,一般来讲编译模式分为 JIT 和 AOT 两大类

JIT

全称为 Just In Time(即时编译),比较典型的就是 V8 JS引擎,它能够即时的编译和运行 Javascript 代码。你只要输入 Javascript 的字符串源码,V8 就能编译和运行这段代码。通常来说,支持 JIT 的语言一般能够支持自省函数(eval),在运行时动态的执行源码。

所以 JIT 模式有个显然的优点,你可以直接将代码分发给用户,而不用考虑用的机器架构。有这个,就可以为用户提供丰富和动态的内容。

但缺点也是比较明显的,大量的字符串源码,将花费 JIT 编译器大量的时间和内存来编译和执行,会让用户感觉应用启动缓慢。

AOT

全称为 Ahead Of Time(事前编译), 典型的例子就是像 C/C++ 需要被编译成特殊的二进制,才可以通过进程加载和运行。

AOT 的优势就是速度快,通过事先编译好的二进制代码,加载和执行的速度都会非常快,在密集计算或者图形渲染的场景下能够获得比较好的用户体验。

但 AOT 也有一些缺点,编译源代码的时候,需要注意用户的设备架构。对于不同的构架需要生成不同的二进制代码,也就会增加应用需要下载的程序包大小。而且二进制代码需要获得执行权限,所以无法在权限比较严格的系统(比如iOS)中动态更新。

Dart 的编译模式

Flutter 使用 Dart 作为开发语言,自然和 Dart 的编译模式脱离不了关系,所以我们先来看一下 Dart 的编译模式。

Script: 最常见的 JIT 模式,就像 Node.js 那样,可以在命令行直接执行 Dart 源代码

Script Snapshot: 不同于 Script 模式,Script Snapshot 模式载入的是已经 token 化的 dart 源码,提前做了编译期间的 Lexer 步骤, 也是属于 JIT 模式

Application Snapshot: JIT 模式,这种模式来源于 dart vm直接载入源码后 dump 出数据。dart vm 通过这种数据启动会更快。不过这种模式是区分架构的,在 X64 下生成的无法给 IA_32 用

AOT: AOT 模式,dart 源代码会被编译成汇编文件,汇编再经过汇编器生成不同架构下的二进制代码

用表格总结一下:

8518337aa14eade56db8168dd70b1256.png

Flutter 的编译模式

Flutter 程序完全用 Dart, 理论上 Flutter 的编译模式应该和 Dart 的一致,事实上因为 Android 和 iOS 生态的差异,Flutter 衍生了不同的编译模式。

Script: 和 Dart 的 Script 模式一样,但是没有开启使用

Script Snapshot: 也是和 Dart 的 Script Snapshot 模式一样,也没有开启使用

Kernel Snapshot: Dart 的 bytecode 模式,在某种程度上类似 JVM。在 Flutter 项目中也被叫做 Core Snapshot,它是和设备架构无关的

Core JIT: 一种编译后的二进制格式,程序的数据和指令被打包成特殊的二进制,在运行时加载。事实上Core JIT 也被叫做 AOT Blobs, 是 AOT 的一种

AOT Assembly: 和 Dart 的 AOT 模式一样

所以在 Flutter 里会更复杂一点,我们结合 Flutter 的各个开发阶段来解读一下。

开发阶段

开发 Flutter APP 的时候,我们需要 HOT Reload 方便 UI 快速成型,同时也需要比较高的性能来进行视图渲染,所以 Flutter 在 Debug 下使用了 Kernel Snapshot 编译模式,会生成如下产物:

isolate_snapshot_data: 加速 isolate 启动的数据,和业务无关

vm_snapshot_data: 加速 Dart VM 启动的数据,和业务无关

kernel_blob.bin: 业务代码产物

12c6951ff5facaa6a4286e2b3e946449.png

发布阶段

在生产阶段,应用需要非常快的速度。所以 Flutter 使用了 AOT 编译模式,但是在不同的平台下,还是有些不一样的

c2e503a6628d433d6607b61f73749c86.png

在 iOS 平台由于 App Store 审核条例不允许动态下发可执行二进制代码,所以在 iOS 上,除了 Javascript,其他语言都使用 AOT 编译。

但是在 Android 平台上,Core JIT 和 AOT Assembly 都支持了,在 Core JIT 模式下会生成四个产物:isolate_snapshot_data/vm_snapshot_data/isolate_snapshot_instr/vm_snapshot_instr

vm_snapshot_instr 和 isolate_snapshot_instr 是 Dart VM 和 isolate 的指令,在载入后,直接将该块内存执行即可。

isolate_snapshot_data 和 vm_snapshot_data 是 Dart VM 和 isolate 的启动数据,主要是为了加速启动速度。

Flutter Engine 支持情况

Flutter Engine 包含了 Dart 的运行时,Flutter 应用的编译产物必须和 Engine 匹配才行,Engine 在不同的阶段提供了不同的支持

0ca0f89f8d8b5f9a920d2f893869ab51.png

通过 gen_snapshot -h 也可以查看到,Engine 对编译模式的支持,事实上 Dart 源码就是经过 gen_snapshot 去处理的。

To create a core snapshot:
--snapshot_kind=core
--vm_snapshot_data=
--isolate_snapshot_data=
To create an AOT application snapshot as assembly suitable for compilation
as a static or dynamic library:
--snapshot_kind=app-aot-assembly
--assembly=
[--obfuscate]
[--save-obfuscation-map=]
To create an AOT application snapshot as an ELF shared library:
--snapshot_kind=app-aot-elf
--elf=
[--strip]
[--obfuscate]
[--save-obfuscation-map=]
AOT snapshots can be obfuscated: that is all identifiers will be renamed
during compilation. This mode is enabled with --obfuscate flag. Mapping
between original and obfuscated names can be serialized as a JSON array
using --save-obfuscation-map= option. See dartbug.com/30524
for implementation details and limitations of the obfuscation pass.

AOT snapshots 也可以使用 obfuscated 选项开启混淆, --save-obfuscation-map= 保存符号 mapping 文件。

9e1d52dcd0cea6ae28a2bd6c1b2f5442.png



推荐阅读
author-avatar
小妖2502898957
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有