//python/private:rule_builders.bzl
Builders for creating rules, aspects et al.
When defining rules, Bazel only allows creatingimmutable objects that can’tbe introspected. This makes it difficult to perform arbitrary customizations ofhow a rule is defined, which makes extending a rule implementation prone tocopy/paste issues and version skew.
These builders are, essentially, mutable and inspectable wrappers for thoseBazel objects. This allows defining a rule where the values are mutable andcallers can customize them to derive their own variant of the rule while stillinheriting everything else about the rule.
To that end, the builders are not strict in how they handle values. Theygenerally assume that the values provided are valid and provide ways tooverride their logic and force particular values to be used when they areeventually converted to the args for calling e.g.rule().
Important
When using builders, most lists, dicts, et al passed into themmust belocally created values, otherwise they won’t be mutable. This is due to Bazel’simplicit immutability rules: after evaluating a.bzl file, its globalvariables are frozen.
Tip
To aid defining reusable pieces, many APIs accept no-arg callable functionsthat create a builder. For example, common attributes can be storedin adict[str,lambda], e.g.ATTRS={"srcs":lambda:LabelList(...)}.
Example usage:
load(":rule_builders.bzl","ruleb")load(":attr_builders.bzl","attrb")# File: foo_binary.bzl_COMMON_ATTRS={"srcs":lambda:attrb.LabelList(...),}defcreate_foo_binary_builder():foo=ruleb.Rule(executable=True,)foo.implementation.set(_foo_binary_impl)foo.attrs.update(COMMON_ATTRS)returnfoodefcreate_foo_test_builder():foo=create_foo_binary_build()binary_impl=foo.implementation.get()deffoo_test_impl(ctx):binary_impl(ctx)...foo.implementation.set(foo_test_impl)foo.executable.set(False)foo.test.test(True)foo.attrs.update(_coverage=attrb.Label(default="//:coverage"))returnfoofoo_binary=create_foo_binary_builder().build()foo_test=create_foo_test_builder().build()# File: custom_foo_binary.bzlload(":foo_binary.bzl","create_foo_binary_builder")defcreate_custom_foo_binary():r=create_foo_binary_builder()r.attrs["srcs"].default.append("whatever.txt")returnr.build()custom_foo_binary=create_custom_foo_binary()
Added in version 1.3.0.
- typedefAttributeBuilder
An abstract base typedef for builder for a Bazel
AttributeInstances of this are a builder for a particular
Attributetype,e.g.attr.label,attr.string, etc.
- typedefAttrsDict
Builder for the dictionary of rule attributes.
- AttrsDict.map:dict[str,AttributeBuilder]
The underlying dict of attributes. Directly accessible so that regulardict operations (e.g.
xiny) can be performed, if necessary.
- AttrsDict.get(key,default=None)
Get an entry from the dict. Convenience wrapper for
.map.get(...)
- AttrsDict.items()→list[tuple[str,object]]
Returns a list of key-value tuples. Convenience wrapper for
.map.items()
- AttrsDict.pop(key,default)→object
Removes a key from the attr dict
- AttrsDict.build()
Build an attribute dict for passing to
rule().
- AttrsDict.new(initial)
Creates a builder for the
rule.attrsdict.
- AttrsDict.update(other)
Merge
otherinto this object.- Args:
other–(dict[str,callable|AttributeBuilder])the values tomerge into this object. If the value a function, it is calledwith no args and expected to return an attribute builder. Thisallows defining dicts of common attributes (where the values arefunctions that create a builder) and merge them into the rule.
- typedefExecGroup
Builder for
exec_group- ExecGroup.toolchains()→list[ToolchainType]
- ExecGroup.exec_compatible_with()→list[str|Label]
- ExecGroup.kwargs:dict[str,Any]
Additional kwargs to use when building. This is to allow manipulations thataren’t directly supported by the builder’s API. The state of this dictmay or may not reflect prior API calls, and subsequent API calls maymodify this dict. The general contract is that modifications to this willbe respected when
build()is called, assuming there were no API callsin between.
- ExecGroup.build()
- ExecGroup.new(**kwargs)
Creates a builder for
exec_group.- Args:
kwargs– Same asexec_group
- Returns:
- typedefRule
A builder to accumulate state for constructing a
ruleobject.- Rule.doc()→str
- Rule.exec_groups()→dict[str,ExecGroup]
- Rule.executable()→bool
- Rule.kwargs:dict[str,Any]
Additional kwargs to use when building. This is to allow manipulations thataren’t directly supported by the builder’s API. The state of this dictmay or may not reflect prior API calls, and subsequent API calls maymodify this dict. The general contract is that modifications to this willbe respected when
build()is called, assuming there were no API callsin between.
- Rule.fragments()→list[str]
- Rule.implementation()→callable|None
- Rule.provides()→list[provider|list[provider]]
- Rule.set_doc(v)
- Rule.set_executable(v)
- Rule.set_implementation(v)
- Rule.set_test(v)
- Rule.test()→bool
- Rule.toolchains()→list[ToolchainType]
- Rule.build(debug='')
Builds a
ruleobject
- ruleb.ExecGroup(**kwargs)
Creates a builder for
exec_group.- Args:
kwargs– Same asexec_group
- Returns:
- ruleb.Rule(**kwargs)
Builder for creating rules.
- Args:
kwargs– The same as therule()function, but using builders ordicts to specify sub-objects instead of the immutable Bazelobjects.
- ruleb.ToolchainType(name=None,**kwargs)
Creates a builder for
config_common.toolchain_type.- Args:
name–(str|Label|None)(defaultNone)the toolchain type target.
kwargs– Same asconfig_common.toolchain_type
- Returns:
- typedefRuleCfg
Wrapper for
rule.cfgarg.- RuleCfg.implementation()→str|callable|None|config.target|config.none
- RuleCfg.inputs()→list[Label]
See also
The
add_inputs()andupdate_inputsmethods for adding uniquevalues.
- RuleCfg.outputs()→list[Label]
See also
The
add_outputs()andupdate_outputsmethods for adding uniquevalues.
- RuleCfg.set_implementation(v)
The string values “target” and “none” are supported.
- RuleCfg.add_inputs(*inputs)
Adds an input to the list of inputs, if not present already.
See also
The
update_inputs()method for adding a collection ofvalues.
- RuleCfg.add_outputs(*outputs)
Adds an output to the list of outputs, if not present already.
See also
The
update_outputs()method for adding a collection ofvalues.
- RuleCfg.build()
Builds the rule cfg into the value rule.cfg arg value.
- Returns:
transitionthe transition object to apply to the rule.
- RuleCfg.new(rule_cfg_arg)
Creates a builder for the
rule.cfgarg.- Args:
rule_cfg_arg–(str|dict|None)The
cfgarg passed to Rule().
- Returns:
- RuleCfg.update_inputs(*others)
Add a collection of values to inputs.
- typedefToolchainType
Builder for
config_common.toolchain_type- ToolchainType.kwargs:dict[str,Any]
Additional kwargs to use when building. This is to allow manipulations thataren’t directly supported by the builder’s API. The state of this dictmay or may not reflect prior API calls, and subsequent API calls maymodify this dict. The general contract is that modifications to this willbe respected when
build()is called, assuming there were no API callsin between.
- ToolchainType.mandatory()→bool
- ToolchainType.name()→str|Label|None
- ToolchainType.set_name(v)
- ToolchainType.set_mandatory(v)
- ToolchainType.build()
Builds a
config_common.toolchain_type- Returns: