[Flutter] Flutter 的 build 系统(番外篇)--build.yaml里面的参数都是啥?我用这些来干啥的?
前言
这次是对build.yaml
格式做个分析;虽说build_config
自己有对应的文档,但那份文档,怎么说呢,看了有种听君一席话,如听一席话的感觉;看完之后好像懂了,但是写起来完全不知道哪里对应哪里;
这次打算通过源码部分,结合一些具体实战实例,对其中参数怎么配置做一个分析总结;
PS:太长不看背面试题专用八股总结版拉最后
PPS:用目录来看会好受很多;
BuildConfig和build.yaml的对应关系:
关于BuildConfig具体支持的参数,其文档中倒是很明显的体现了出来:
BuildConfig | Value | Default |
---|---|---|
targets | Map<String, BuildTarget> | a single target with the same name as the package |
builders | Map<String, BuilderDefinition> | empty |
post_process_builders | Map<String, PostProcessBuilderDefinition> | empty |
global_options | Map<String, GlobalBuilderOptions> | empty |
additional_public_assets | List | empty |
因此现在得知的情报如下:
build.yaml 支持的参数有:builders
、post_process_builders
、targets
、global_options
、additional_public_assets
;这些是一个build.yaml 第一级可以配置的参数;如下图所示:
源码中也规定了这些参数:
- targets对应BuildTarget;
- builders对应BuilderDefinition;
- post_process_builders对应PostProcessBuilderDefinition;
- global_options对应GlobalBuilderOptions;
- additional_public_assets是一个List列表;
那么接下来就该看看具体配置内容了;
BuildTarget
参数方面:
Key | Value | Default |
---|---|---|
auto_apply_builders | bool | true |
builders | Map<BuilderKey, TargetBuilderConfig> | empty |
dependencies | List<TargetKey> | all default targets from all dependencies in your pubspec |
sources | InputSet | all defaults sources |
文档中对其解释是这样的:
Dividing a package into Build targets
When a
Builder
should be applied to a subset of files in a package the package can be broken up into multiple 'targets'. Targets are configured in thetargets
section of thebuild.yaml
. The key for each target makes up the name for that target. Targets can be referred to in'$definingPackageName:$targetname'
. When the target name matches the package name it can also be referred to as just the package name. One target in every package must use the package name so that consumers will use it by default. In thebuild.yaml
file this target can be defined with the key$default
or with the name of the package.Each target may also contain the following keys:
- sources: List of Strings or Map, Optional. The set of files within the package which make up this target. Files are specified using glob syntax. If a List of Strings is used they are considered the 'include' globs. If a Map is used can only have the keys
include
andexclude
. Any file which matches any glob ininclude
and no globs inexclude
is considered a source of the target. Wheninclude
is omitted every file is considered a match.- dependencies: List of Strings, Optional. The targets that this target depends on. Strings in the format
'$packageName:$targetName'
to depend on a target within a package or$packageName
to depend on a package's default target. By default this is all of the package names this package depends on (from thepubspec.yaml
).- builders: Map, Optional. See "configuring builders" below.
不过好像并没提到 auto_apply_builders ?
总结一下的话:
auto_apply_builders
auto_apply_builders 用于buildRunner中BuildPhases
的生成部分,设置为false的话就不会根据当前builder配置去生成BuildPhases
;
换句话说就是要自己配置builder,调用执行builder;
builders
-
builders 的话,先看其所说的那个;
其对应部分文档:
Configuring
Builder
s applied to your packageEach target can specify a
builders
key which configures the builders which are applied to that target. The value is a Map from builder to configuration for that builder. The key is in the format'$packageName:$builderName'
. The configuration may have the following keys:- enabled: Boolean, Optional: Whether to apply the builder to this target. Omit this key if you want the default behavior based on the builder's
auto_apply
configuration. Builders which are manually applied (auto_apply: none
) are only ever used when there is a target specifying the builder withenabled: True
. - generate_for: List of String or Map, Optional:. The subset of files within the target's
sources
which should have this Builder applied. Seesources
configuration above for how to configure this. - options: Map, Optional: A free-form map which will be passed to the
Builder
as aBuilderOptions
when it is constructed. Usage varies depending on the particular builder. Values in this map will override the default provided by builder authors. Values may also be overridden based on the build mode withdev_options
orrelease_options
. - dev_options: Map, Optional: A free-form map which will be passed to the
Builder
as aBuilderOptions
when it is constructed. Usage varies depending on the particular builder. The values in this map override Builder defaults or non mode-specific options per-key when the build is done in dev mode. - release_options: Map, Optional: A free-form map which will be passed to the
Builder
as aBuilderOptions
when it is constructed. Usage varies depending on the particular builder. The values in this map override Builder defaults or non mode-specific options when the build is done in release mode.
其对应的两个新增参数类型:
- enabled: Boolean, Optional: Whether to apply the builder to this target. Omit this key if you want the default behavior based on the builder's
BuilderKey
BuilderKey
An identifier for a
builder
. A builder has two parts, apackage
and aname
.To construct a key, you join the package and name with a
:
, so for instance thebar
builder in thefoo
package would be referenced like thisfoo:bar
.
但奇怪的是,这部分在我这里对应的是一个String……不过格式还是一样的,感觉是我版本的问题;
对应build.yaml中的这部分内容:
TargetBuilderConfig
TargetBuilderConfig
key | value | default |
---|---|---|
enabled | bool | true |
generate_for | InputSet | ** |
options | BuilderOptions | none |
dev_options | BuilderOptions | none |
release_options | BuilderOptions | none |
enable 的作用正如字面意思,当前TargetBuilderConfig是否启用;如果设置为true,那么后续overrideBuildConfig就会去覆盖builder配置为当前这个TargetBuilderConfig;否则就使用通用的默认配置;
generate_for 又引入了一个叫InputSet
的东西,其实其作用仅仅是一个过滤器:
如果include为空,表示所有的都会接受;exclude为空表示所有项都视为include;
options、dev_options、release_options 这三个都是BuilderOptions,作用也仅仅是提供一下一些配置参数之类的,里面可以放任何自定义的数据:
dependencies
dependencies 字面意思,可用来设定当前BuildTarget的指定依赖;用来后面生成BuildPhases的时候,在项目依赖有向图中先筛选一遍,进而缩小模块大小范围和数量(感觉是这个意思~~);
为空的时候会直接以当前package的依赖为默认值;
source
source这块就是指输入给builder的部分;同样也是一个InputSet;可以通过这个参数设置给buider开放的输入文件检测范围;
总结
BuildTarget 的作用正如其名字所述,用于规定builder们的目标、应用范围;
auto_apply_builder用于配置是否自动应用到builder的开关;
builders中重要的部分是TargetBuilderConfig部分,保存了builder的generate_for,自定义参数等东西,提供了生成目标限制和自定义参数的功能;
dependencies 规定了开放给builder的依赖包有哪些;
source 规定了开放给builder的可检测文件的路径有哪些;
BuilderDefinition
key | value | default |
---|---|---|
builder_factories | List | none |
import | String | none |
build_extensions | Map<String, List> | none |
auto_apply | AutoApply | AutoApply.none |
required_inputs | List | none |
runs_before | List<BuilderKey> | none |
applies_builders | List<BuilderKey> | none |
is_optional | bool | false |
build_to | BuildTo | BuildTo.cache |
defaults | TargetBuilderConfigDefaults | none |
万幸新增的东西只有AutoApply、BuildTo和TargetBuilderConfigDefaults三个东西;
再来到到文档部分:
Defining
Builder
s to apply to dependentsIf users of your package need to apply some code generation to their package, then you can define
Builder
s and have those applied to packages with a dependency on yours.The key for a Builder will be normalized so that consumers of the builder can refer to it in
'$definingPackageName:$builderName'
format. If the builder name matches the package name it can also be referred to with just the package name.Exposed
Builder
s are configured in thebuilders
section of thebuild.yaml
. This is a map of builder names to configuration. Each builder config may contain the following keys:
import: Required. The import uri that should be used to import the library containing the
Builder
class. This should always be apackage:
uri.builder_factories: A
List<String>
which contains the names of the top-level methods in the imported library which are a function fitting the typedefBuilder factoryName(BuilderOptions options)
.build_extensions: Required. A map from input extension to the list of output extensions that may be created for that input. This must match the merged
buildExtensions
maps from eachBuilder
inbuilder_factories
.auto_apply: Optional. The packages which should have this builder automatically to applied. Defaults to
'none'
The possibilities are:
"none"
: Never apply this Builder unless it is manually configured"dependents"
: Apply this Builder to the package with a direct dependency on the package exposing the builder."all_packages"
: Apply this Builder to all packages in the transitive dependency graph."root_package"
: Apply this Builder only to the top-level package.required_inputs: Optional, see adjusting builder ordering
runs_before: Optional, see adjusting builder ordering
applies_builders: Optional, list of Builder keys. Specifies that other builders should be run on any target which will run this Builder.
is_optional: Optional, boolean. Specifies whether a Builder can be run lazily, such that it won't execute until one of it's outputs is requested by a later Builder. This option should be rare. Defaults to
False
.build_to: Optional. The location that generated assets should be output to. The possibilities are:
"source"
: Outputs go to the source tree next to their primary inputs."cache"
: Outputs go to a hidden build cache and won't be published. The default is "cache". If a Builder specifies that it outputs to "source" it will never run on any package other than the root - but does not necessarily need to use the "root_package" value for "auto_apply". If it would otherwise run on a non-root package it will be filtered out.defaults: Optional: Default values to apply when a user does not specify the corresponding key in their
builders
section. May contain the following keys:
- generate_for: A list of globs that this Builder should run on as a subset of the corresponding target, or a map with
include
andexclude
lists of globs.- options: Arbitrary yaml map, provided as the
config
map inBuilderOptions
to theBuilderFactory
for this builder. Individual keys will be overridden by configuration provided in eitherdev_options
orrelease_options
based on the build mode, and then overridden by any user specified configuration.- dev_options: Arbitrary yaml map. Values will replace the defaults from
options
when the build is done in dev mode (the default mode).- release_options: Arbitrary yaml map. Values will replace the defaults from
options
when the build is done in release mode (with--release
).Example
builders
config:builders: my_builder: import: "package:my_package/builder.dart" builder_factories: ["myBuilder"] build_extensions: {".dart": [".my_package.dart"]} auto_apply: dependents defaults: release_options: some_key: "Some value the users will want in release mode"
不得不说,这个builder部分,是挺多参数的~~~~~
builder_factories
builder_factories 是一个必填项,按照我工地英语,翻译了一下其注释,好像是从下面那个import的路径中,获取顶级方法,并将参数转换为builder;
这句话啥意思看不懂没关系,我也没看懂~
找个例子看一下就知道了;
以json_serializable为例,其builder这么写的:
转换的build.dart 是这样的:
而这个_i4.jsonSerializable是个啥东西?
哦,现在知道了,import是_i4的内容,builder_factories 是要调用的方法名;
build.dart就是通过这两者拿到了自定义的Builder;
import
功能嘛,如上所述;
不过要记得一点,这块的import要以package开头;
build_extensions
必填项,从输入扩展名到输出扩展名的映射。
其实看一下入参也能猜出来;
auto_apply
auto_apply引入了一个新的枚举类:
而这个autoApply唯一应用的地方是这里:
对应上图的部分,返回的东西是一个PackageFilter
:
而这个PackageFilter
的作用是体现在上面那个BuildTarget
的auto_apply_builders
这部分中:
所以这个配置的作用还是跟auto_apply_builder一样,用于将依赖包转为builderPhase去执行对应builder的过程中,用于判断是否需要生成对应builderPhase;
所以总结一下的话:
auto_apply 跟BuilderTarget的auto_apply_builder的作用一样,用于筛选是否需要生成builderPhase执行builder;
AutoApply.none,会返回toNoneByDefault的PackageFilter,其不会允许任何PackageNode通过检测,也就是不会生成BuilderPhase,如果没有自己创建、调用的builder,就不要设置此项;
AutoApply.dependents,会返回toDependentsOf的PackageFilter,这个只要自己或者依赖中包含对应package即可;其实就是前面说的,依赖有向图的强连通分量(或者直接说项目依赖模块?)部分;但是父依赖是不判断的,仅仅看自己和子依赖;
AutoApply.allPackages,会返回toAllPackages的PackageFilter,这个直接返回ture,允许任何依赖生成builerPhase;
AutoApply.rootPackage,字面意思,只允许根目录;
required_inputs
用于调整顺序,需要等到指定拓展名类型输出之后才执行;
感觉换个名字比较好?至少体现一下调整执行顺序这种等待关系部分,加个run之类的~~
runs_before
用于调整顺序,表明会在指定builder前运行;参数还是那种package:开头的那种;
applies_builders
表明会运行此builder的builder;参数还是那种package:开头的那种;
is_optional
表明是否是延迟加载的,其实就是懒汉式这个概念;除非后来的构建器调用readAs*
或canRead
请求它的输出,否则不会运行。
build_to
虽然build_to 里面又个BuildTo枚举,但是其概念还是蛮明显的;
build_to 用于生成的源码是放到缓存文件夹中隐藏起来,还是放到项目中体现出来;
defaults
类型是TargetBuilderConfigDefaults
,其实从名字也能看出来,其实就是对BuildTarget中的TargetBuilderConfig的兜底配置,设置其默认值而已;
总结
BuilderDefinition 是对builder的具体描述部分:
builder_factories 表示会生成builder的方法名;
import 表示要引入的依赖工程;
build_extensions 表示生成映射;
auto_apply 表示的是根据依赖生成builder这个功能的应用范围;
required_inputs和runs_before都是执行混序的调整;
applies_builder 表示会提供给哪些builder用;
is_optional 表示是否是懒汉式
build_to 表示生成的代码是否是隐藏的;
defaults是builder的默认兜底builder配置;
PostProcessBuilderDefinition
PostProcessBuilderDefinition跟BuilderDefinition没有太大区别,唯一不同是builder_factories,由于PostProcess本身就是多个builder,所以只由一个方法提供就行;
结语
总结部分见各章结尾的总结;
现在就该看下Builder该怎么自定义了;以及其自定义能力能到什么程度,跨模块能力有多强;
转载自:https://juejin.cn/post/7136082099454836773