携手创作,一起成长!这是我参加「日新计划 8 月更文应战」的第1天,点击检查活动详情

前语

对于Flutter开发者来说,build_runner 能够说并不是一个陌生的东西,很多package中就要求调用build_runner 来主动生成处理代码,比如说json_serializable;

但正如其描绘中所述的那样,其是经过 Dart Build System来完成的,build_runner 和其又是一个什么关系,接下来就来学习一下dart的build体系

dart 的 build 体系

组成

dart 的 build体系,由 build_config、 build_modules、build_resolvers、 build_runner、 build_test、 build_web_compilers 一起组合、完成了dart 的 build 体系;

  • build_config 便是解析那个build.yaml文件,用来装备build_runner,没什么好说的,具体的功用后边再细说;
  • build_modules 如同是解析module级别信息的一个库
  • build_resolvers 从自述文件中分析,如同是一个给build_runner 每步提供所需信息的解析器?
  • build_runner 整个build体系的中心部分,其他部分都是为了拓展和完成此功用而存在的;
  • build_test 字面意思,一个测验库;
  • build_web_compilers 用于web端的build体系;

效果

Flutter的build体系其实便是生成代码,对标的应该是JAVA的APT这块的东西;

另外,对于 dart 的 build 体系,官方是有这么一段介绍:

Although the Dart build system is a good alternative to reflection (which has performance issues) and macros (which Dart’s compilers don’t support), it can do more than just read and write Dart code. For example, thesass_builderpackage implements a builder that generates.cssfiles from.scssand.sassfiles.

也便是说dart build理论上是能够来做很多人心心念念的反射的;

根本运用

假如仅仅是运用方面来说,build_runner 的运用非常简单;比如说我们最常用的一条指令便是:

flutter pub run build_runner build

也能够装备build.yaml来修正装备信息,生成契合需求的代码;

不过在输入上面那句build_runner build之后发生了什么,像build_config之类的在这个过程中各自起了什么效果,这就需求追寻一下;

build_runner 都干了什么

[Flutter] Flutter 的 build 系统(一)

依据日志信息,build_runner 的流程根本遵循这样一个套路:

  • 生成和预编译build脚本
  • 处理输入环境和资源
  • 依据前面的脚本和输入信息,开端正式履行builder生成代码;
  • 缓存信息,用于下一回生成代码的时分增量判别运用;

接下来就看下这些编译脚本、输入环境、资源等不知所云的东西,到底是什么;

生成和预编译build脚本

生成部分:

首要来到build_runner的main函数部分,前面一大片对参数检测的拦截判别,真实履行指令的当地放在了最终:

[Flutter] Flutter 的 build 系统(一)

在这个办法中最先做的事便是生成build脚本

[Flutter] Flutter 的 build 系统(一)

其内容也很简单,说白了便是输出一个文件罢了:

[Flutter] Flutter 的 build 系统(一)

至于这个文件内容是什么,有什么用,先放到后边再说;现在先重视于全体流程;

那么现在能够得知,这步会在scriptLocaton这个途径上生成一个build脚本;而这个途径也不难得到:

[Flutter] Flutter 的 build 系统(一)
[Flutter] Flutter 的 build 系统(一)
[Flutter] Flutter 的 build 系统(一)

其实便是 .dart_tool/build/entrypoint/build.dart 这个文件;

预编译部分:

在上面贴的generateAndRun办法中,生成文件之后就会履行一个 _createKernelIfNeeded 办法,其效果也正如其名,检测是否需求就创立内核文件;

[Flutter] Flutter 的 build 系统(一)

[Flutter] Flutter 的 build 系统(一)

而这个内核文件,也便是后缀为build.dart.dill 文件

[Flutter] Flutter 的 build 系统(一)

同时,在这儿也说到了一个新的概念:assetGraph,不过这些也是后边再细看的东西;

处理输入环境和资源

在编译完build脚本生成内核后,下面便是履行这个内核文件;在这儿新开了一个isolate去履行这个文件:

[Flutter] Flutter 的 build 系统(一)

接下来就该看下这个内核文件到底是什么……但是呢,内核文件这东西,原本就不是给人看的………………所以呢,能够从另一方面考虑下,比如说,既然内核文件看不了,那我就看内核文件的从哪编译来的,反正逻辑上也是大差不差,彻底能够参阅;

正好内核文件的来历,也便是那个build脚本,其方位在上面也说到过了;在我测验代码中,它最终是这样的:

[Flutter] Flutter 的 build 系统(一)
其间的这个_i10,正是build_runner……看来兜兜转转又回来了?

应该说回来了,但没彻底回来,上面说到的build_runner是bin目录下的;这次的build_runner是lib目录下的,进口还是不一样的;

在这儿,build_runner build中的build这个参数才真实辨认并开端履行;前面都是前戏;而履行这个build指令的是一个名为BuildCommandRunner的类,其内部内置了包括build在内的诸多函数指令:

[Flutter] Flutter 的 build 系统(一)

由于测验的指令参数为build,所以命中的commend为 BuildCommand;而 BuildCommand 所做的事也根本会集在 src/generate/build.dart 这个文件中的build办法中了;自此开端真实去履行build_runner对应Builder中要求做的事;

其build办法所做的事还是比较简单看懂的:

[Flutter] Flutter 的 build 系统(一)

  1. 装备环境(包括输入输出装备)
  2. 装备通用选项(build时分的装备项目)
  3. 调用BuildRunner.create创立Builder和生成所需数据,最终调用run履行;

而这部分所说的处理输入环境和资源就在 BuildRunner.create 这部分中;其会调用 BuildDefinition.prepareWorkspace办法;

[Flutter] Flutter 的 build 系统(一)

而在这儿就呈现了上面说到的assetGraph,这儿便是其创立和运用的当地:

[Flutter] Flutter 的 build 系统(一)

所以,最终总结一下,处理输入环境和资源 这个环节所做的事便是依据装备生成输入输出、build过程中所需的各种参数,提供assetGraph这个东西;

具体这些装备进口在哪,从何而来,assetGraph又是什么东西,有什么效果,后边再看;

正式履行builder生成代码

这部分便是刚才说到的调用run办法的当地;

[Flutter] Flutter 的 build 系统(一)

它的run办法咋看如同也不难明的样子,主要是各种新名词有点多:

[Flutter] Flutter 的 build 系统(一)

不过现在只跟随build流程来说的话,中心应该事其间的_safeBuild办法:

[Flutter] Flutter 的 build 系统(一)

其所做的事,除了各种心跳log之外,应该便是更新assetGraph;履行_runPhases;另外究竟事safeBuild嘛,所以新开了一个zone来处理;

[Flutter] Flutter 的 build 系统(一)

_runPhases所做的事便是真实去履行build所做的事,生成代码之类的;比如说json_serializable中的build,就会走_runBuilder部分并最终调用runBuilder中的builder.build,也便是自定义Builder中需求自己完成的部分;

[Flutter] Flutter 的 build 系统(一)

对了,关于像json_serializable的自定义Builder从何而来的问题,答案是一开端就已经集成进来了,在builder.dart中已经呈现了其身影:

[Flutter] Flutter 的 build 系统(一)

不过为什么build.dart 能得知具体有哪些builder?比如说json_serializable中的builder,是怎么加入到build.dart中的,那也是后边要看的东西;

缓存信息

再次回到 _safeBuild 这块,缓存信息的部分紧贴着run部分:

[Flutter] Flutter 的 build 系统(一)

如同就写了一下文件,没了?

结语

这篇大体粗略的过了一下build这个指令都干了什么;不过像生成的文件内部结构、效果;装备信息来历,如何解析之类的问题还未解决;在后边会依次看看;

最终尝试完成一份自己的自定义Builder;