aboutsummaryrefslogtreecommitdiffhomepage
path: root/site
diff options
context:
space:
mode:
authorGravatar Dmitry Lomov <dslomov@google.com>2017-04-25 11:14:05 +0200
committerGravatar Vladimir Moskva <vladmos@google.com>2017-04-25 14:48:16 +0200
commit3b5f9bd49d4e891aa3ca07e30a28158f1184c3db (patch)
treeaad59c7c520ba071483b5d350104d1fa0ea8f4f1 /site
parent3d37b4c4924b07c2245fcbb149e5ce5788b5ddea (diff)
Document declared providers.
Change-Id: Ifdc1773fb1439c16327bb84961998793a942e666 PiperOrigin-RevId: 154151084
Diffstat (limited to 'site')
-rw-r--r--site/designs/index.md4
-rw-r--r--site/versions/master/docs/skylark/cookbook.md28
-rw-r--r--site/versions/master/docs/skylark/rules.md72
3 files changed, 67 insertions, 37 deletions
diff --git a/site/designs/index.md b/site/designs/index.md
index 67656da97f..6792ee2449 100644
--- a/site/designs/index.md
+++ b/site/designs/index.md
@@ -18,6 +18,10 @@ ongoing changes as designs are implemented.
Always go to the [documentation](/versions/master/docs/bazel-overview.md) for
descriptions of current Bazel functionality.
+## Bazel Code Style and Best Practices
+
+* [Implementing Native Declared Provders](https://docs.google.com/document/d/1BKCBuYvf6fwmMnFu3KMWdRFysDgGCzdMiNxY_foosAM/preview) 12 April 2017
+
## Bazel Design Documents
<ul>
diff --git a/site/versions/master/docs/skylark/cookbook.md b/site/versions/master/docs/skylark/cookbook.md
index 4e173645d4..b71ce51c78 100644
--- a/site/versions/master/docs/skylark/cookbook.md
+++ b/site/versions/master/docs/skylark/cookbook.md
@@ -503,7 +503,7 @@ def _impl(ctx):
content=command,
executable=True)
- return struct(
+ return [DefaultInfo(
# Create runfiles from the files specified in the data attribute.
# The shell executable - the output of this rule - can use them at runtime.
# It is also possible to define data_runfiles and default_runfiles.
@@ -513,7 +513,7 @@ def _impl(ctx):
# to have a field named "runfiles" in order to create the actual runfiles
# symlink tree.
runfiles=ctx.runfiles(files=ctx.files.data)
- )
+ )]
execute = rule(
implementation=_impl,
@@ -661,14 +661,16 @@ to its dependents.
`sum.bzl`:
```python
+NumberInfo = provider()
+
def _impl(ctx):
result = ctx.attr.number
- for i in ctx.attr.deps:
- result += i.number
+ for dep in ctx.attr.deps:
+ result += dep[NumberInfo].number
ctx.file_action(output=ctx.outputs.out, content=str(result))
- # Fields in the struct will be visible by other rules.
- return struct(number=result)
+ # Return the provider with result, visible to other rules.
+ return [NumberInfo(number=result)]
sum = rule(
implementation=_impl,
@@ -709,15 +711,17 @@ This is a similar example, but dependencies may not provide a number.
`sum.bzl`:
```python
+NumberInfo = provider()
+
def _impl(ctx):
result = ctx.attr.number
- for i in ctx.attr.deps:
- if hasattr(i, "number"):
- result += i.number
+ for dep in ctx.attr.deps:
+ if NumberInfo in dep:
+ result += dep[NumberInfo].number
ctx.file_action(output=ctx.outputs.out, content=str(result))
- # Fields in the struct will be visible by other rules.
- return struct(number=result)
+ # Return the provider with result, visible to other rules.
+ return [NumberInfo(number=result)]
sum = rule(
implementation=_impl,
@@ -864,7 +868,7 @@ def _impl(ctx):
files = depset()
files += ctx.attr.dep_rule_1.files
files += ctx.attr.dep_rule_2.files
- return struct(files=files)
+ return [DefaultInfo(files=files)]
# This rule binds the depending rules together
master_rule = rule(
diff --git a/site/versions/master/docs/skylark/rules.md b/site/versions/master/docs/skylark/rules.md
index 5db62cf5e0..56ef328b85 100644
--- a/site/versions/master/docs/skylark/rules.md
+++ b/site/versions/master/docs/skylark/rules.md
@@ -114,11 +114,7 @@ Example:
```python
def _impl(ctx):
...
- return struct(
- runfiles = ...,
- my_provider = ...,
- ...
- )
+ return [DefaultInfo(runfiles=...), MyInfo(...)]
my_rule = rule(
implementation = _impl,
@@ -350,46 +346,72 @@ information can be accumulated from all dependencies. In such cases, consider
using [depsets](depsets.md) to hold the data more efficiently without excessive
copying.
-The following data types can be passed using providers:
+Providers can be declared using the [provider()](lib/globals.html#provider) function:
-* [bool](lib/bool.html)
-* [integer](lib/int.html)
-* [string](lib/string.html)
-* [file](lib/File.html)
-* [label](lib/Label.html)
-* [None](lib/globals.html#None)
-* anything composed of these types and [lists](lib/list.html),
- [dicts](lib/dict.html), [depsets](lib/depset.html) or
- [structs](lib/struct.html).
+```python
+TransitiveDataInfo = provider()
+```
-Providers are created from the return value of the rule implementation function:
+Rule implementation function can then construct and return provider instances:
```python
def rule_implementation(ctx):
...
- return struct(
- transitive_data = depset(["a", "b", "c"])
- )
+ return [TransitiveDataInfo(value = ["a", "b", "c"])]
```
-A dependent rule might access these data as struct fields of the `target` being
-depended upon:
+`TransitiveDataInfo` acts both as a constructor for provider instances and as a key to access them.
+A [target](lib/Target.html) serves as a map from each provider that the target supports, to the
+target's corresponding instance of that provider.
+A rule can access the providers of its dependencies using the square bracket notation (`[]`):
```python
def dependent_rule_implementation(ctx):
...
s = depset()
for dep_target in ctx.attr.deps:
- # Use `print(dir(dep_target))` to see the list of providers.
- s += dep_target.transitive_data
+ s += dep_target[TransitiveDataInfo].value
...
```
+All targets have a [`DefaultInfo`](lib/globals.html#DefaultInfo) provider that can be used to access
+some information relevant to all targets.
+
Providers are only available during the analysis phase. Examples of usage:
* [mandatory providers](cookbook.md#mandatory-providers)
* [optional providers](cookbook.md#optional-providers)
+> *Note:*
+> Historically, Bazel also supported provider instances that are identified by strings and
+> accessed as fields on the `target` object instead of as keys. This style is deprecated
+> but still supported. Return legacy providers as follows:
+>
+```python
+def rule_implementation(ctx):
+ ...
+ modern_provider = TransitiveDataInfo(value = ["a", "b", "c"])
+ # Legacy style.
+ return struct(legacy_provider = struct(...),
+ another_legacy_provider = struct(...),
+ # The `providers` field contains provider instances that can be accessed
+ # the "modern" way.
+ providers = [modern_provider])
+```
+> To access legacy providers, use the dot notation.
+> Note that the same target can define both modern and legacy providers:
+>
+```python
+def dependent_rule_implementation(ctx):
+ ...
+ s = depset()
+ for dep_target in ctx.attr.deps:
+ x = dep_target.legacy_provider # legacy style
+ s += dep_target[TransitiveDataInfo].value # modern style
+ ...
+```
+> **We recommend using modern providers for all future code.**
+
## Runfiles
Runfiles are a set of files used by the (often executable) output of a rule
@@ -418,9 +440,9 @@ def _rule_implementation(ctx):
# deps and data attributes.
collect_default = True,
)
- # Add a field named "runfiles" to the return struct in order to actually
+ # Add a field named "runfiles" to the DefaultInfo provider in order to actually
# create the symlink tree.
- return struct(runfiles = runfiles)
+ return [DefaultInfo(runfiles=runfiles)]
```
Note that non-executable rule outputs can also have runfiles. For example, a