携手创作,一起生长!这是我参与「日新方案 8 月更文挑战」的第4天,点击检查活动概况

前言

这次是对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 支持的参数有:builderspost_process_builderstargetsglobal_optionsadditional_public_assets;这些是一个build.yaml 榜首级可以装备的参数;如下图所示:

[Flutter] Flutter 的 build 系统(番外篇)--build.yaml里面的参数都是啥?我用这些来干啥的?

源码中也规则了这些参数:

[Flutter] Flutter 的 build 系统(番外篇)--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 aBuildershould be applied to a subset of files in a package the package can be broken up into multiple ‘targets’. Targets are configured in thetargetssection 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 packagemustuse the package name so that consumers will use it by default. In thebuild.yamlfile this target can be defined with the key$defaultor 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 keysincludeandexclude. Any file which matches any glob inincludeand no globs inexcludeis considered a source of the target. Whenincludeis 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$packageNameto 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;

[Flutter] Flutter 的 build 系统(番外篇)--build.yaml里面的参数都是啥?我用这些来干啥的?
[Flutter] Flutter 的 build 系统(番外篇)--build.yaml里面的参数都是啥?我用这些来干啥的?

builders

  • builders 的话,先看其所说的那个;

    其对应部分文档:

    ConfiguringBuilders applied to your package

    Each target can specify abuilderskey 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’sauto_applyconfiguration. 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’ssourceswhich should have this Builder applied. Seesourcesconfiguration above for how to configure this.
    • options: Map, Optional: A free-form map which will be passed to theBuilderas aBuilderOptionswhen 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_optionsorrelease_options.
    • dev_options: Map, Optional: A free-form map which will be passed to theBuilderas aBuilderOptionswhen 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 theBuilderas aBuilderOptionswhen 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.

    其对应的两个新增参数类型:

BuilderKey

BuilderKey

An identifier for abuilder. A builder has two parts, apackageand aname.

To construct a key, you join the package and name with a:, so for instance thebarbuilder in thefoopackage would be referenced like thisfoo:bar.

但奇怪的是,这部分在我这儿对应的是一个String……不过格式仍是相同的,感觉是我版别的问题;

[Flutter] Flutter 的 build 系统(番外篇)--build.yaml里面的参数都是啥?我用这些来干啥的?

对应build.yaml中的这部分内容:

[Flutter] Flutter 的 build 系统(番外篇)--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的东西,其实其效果仅仅是一个过滤器:

[Flutter] Flutter 的 build 系统(番外篇)--build.yaml里面的参数都是啥?我用这些来干啥的?
假如include为空,标明所有的都会接受;exclude为空标明所有项都视为include;

options、dev_options、release_options 这三个都是BuilderOptions,效果也仅仅是供给一下一些装备参数之类的,里边可以放任何自定义的数据:

[Flutter] Flutter 的 build 系统(番外篇)--build.yaml里面的参数都是啥?我用这些来干啥的?

dependencies

dependencies 字面意思,可用来设定当时BuildTarget的指定依靠;用来后边生成BuildPhases的时候,在项目依靠有向图中先挑选一遍,进而缩小模块巨细规模和数量(感觉是这个意思~~);

[Flutter] Flutter 的 build 系统(番外篇)--build.yaml里面的参数都是啥?我用这些来干啥的?

为空的时候会直接以当时package的依靠为默许值;

[Flutter] Flutter 的 build 系统(番外篇)--build.yaml里面的参数都是啥?我用这些来干啥的?

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三个东西;

再来到到文档部分:

DefiningBuilders to apply to dependents

If users of your package need to apply some code generation to their package, then you can defineBuilders 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.

ExposedBuilders are configured in thebuilderssection 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 theBuilderclass. This should always be apackage:uri.

  • builder_factories: AList<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 mergedbuildExtensionsmaps from eachBuilderinbuilder_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, seeadjusting builder ordering

  • runs_before: Optional, seeadjusting 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 toFalse.

  • 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 theirbuilderssection. 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 withincludeandexcludelists of globs.
    • options: Arbitrary yaml map, provided as theconfigmap inBuilderOptionsto theBuilderFactoryfor this builder. Individual keys will be overridden by configuration provided in eitherdev_optionsorrelease_optionsbased on the build mode, and then overridden by any user specified configuration.
    • dev_options: Arbitrary yaml map. Values will replace the defaults fromoptionswhen the build is done in dev mode (the default mode).
    • release_options: Arbitrary yaml map. Values will replace the defaults fromoptionswhen the build is done in release mode (with--release).

Examplebuildersconfig:

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这么写的:

[Flutter] Flutter 的 build 系统(番外篇)--build.yaml里面的参数都是啥?我用这些来干啥的?

转化的build.dart 是这样的:

[Flutter] Flutter 的 build 系统(番外篇)--build.yaml里面的参数都是啥?我用这些来干啥的?

而这个_i4.jsonSerializable是个啥东西?

[Flutter] Flutter 的 build 系统(番外篇)--build.yaml里面的参数都是啥?我用这些来干啥的?

哦,现在知道了,import是_i4的内容,builder_factories 是要调用的办法名;

build.dart便是经过这两者拿到了自定义的Builder;

import

功用嘛,如上所述;

不过要记得一点,这块的import要以package最初;

build_extensions

必填项,从输入扩展名到输出扩展名的映射。

其实看一下入参也能猜出来;

auto_apply

auto_apply引入了一个新的枚举类:

[Flutter] Flutter 的 build 系统(番外篇)--build.yaml里面的参数都是啥?我用这些来干啥的?

而这个autoApply唯一使用的地方是这儿:

[Flutter] Flutter 的 build 系统(番外篇)--build.yaml里面的参数都是啥?我用这些来干啥的?

对应上图的部分,回来的东西是一个PackageFilter

[Flutter] Flutter 的 build 系统(番外篇)--build.yaml里面的参数都是啥?我用这些来干啥的?

而这个PackageFilter的效果是表现在上面那个BuildTargetauto_apply_builders这部分中:

[Flutter] Flutter 的 build 系统(番外篇)--build.yaml里面的参数都是啥?我用这些来干啥的?

所以这个装备的效果仍是跟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的兜底装备,设置其默许值而已;

[Flutter] Flutter 的 build 系统(番外篇)--build.yaml里面的参数都是啥?我用这些来干啥的?

总结

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该怎么自定义了;以及其自定义才能能到什么程度,跨模块才能有多强;