aboutsummaryrefslogtreecommitdiffhomepage
path: root/site/designs/skylark/declared-providers.md
diff options
context:
space:
mode:
Diffstat (limited to 'site/designs/skylark/declared-providers.md')
-rw-r--r--site/designs/skylark/declared-providers.md288
1 files changed, 0 insertions, 288 deletions
diff --git a/site/designs/skylark/declared-providers.md b/site/designs/skylark/declared-providers.md
deleted file mode 100644
index ef88b5ba3f..0000000000
--- a/site/designs/skylark/declared-providers.md
+++ /dev/null
@@ -1,288 +0,0 @@
----
-layout: contribute
-title: Declared Providers
----
-
-# Design Document: Declared Providers
-
-**Design documents are not descriptions of the current functionality of Skylark.
-Always go to the documentation for current information.**
-
-
-**Status:** Approved
-
-**Authors:** [Dmitry Lomov](mailto:dslomov@google.com),
-[Laurent Le Brun](mailto:laurentlb@google.com)
-
-**Design document published**: 2016-06-06
-
-## Motivation
-
-Skylark rules use simple Skylark structs as their providers. Skylark providers
-are identified as simple names, such as 'java' or 'files'. This approach has the
-advantage of simplicity, but as the number and complexity of Skylark rules grow,
-we run into engineering scalability problems:
-
-* Using simple names for providers might lead to name conflicts (when
- unrelated rules call their providers the same simple name).
-* There is no clear formal way to add documentation for those providers; if
- any, the documentation is in prose in rule's doc comment, where it tends to
- become obsolete/incomplete; most existing providers have no documentation
- explaining their contracts at all.
-* It’s hard to know which fields to expect in a provider.
-* It’s hard to know which rule can depend on which rule.
-
-## Goals
-
-* Solve name-conflict problem for providers
-* Allow to specify providers in Skylark rules with the same level of
- robustness as other components of the language, such as rules and aspects
-* Enable the same or better documentability of Skylark providers as native
- providers allow
-* Improve providers interoperability with native code.
-
-## Proposal
-
-We propose a redesign of how Skylark rules deal with providers to address the
-above concerns. The redesign can occur in stages; those stages represent
-implementation stages, but allow Skylark users to gradually opt for "more and
-more engineering" as their custom rules progress from a small project on the
-side to a public release.
-
-Our proposal is backwards compatible with the existing providers in Bazel and
-allows easy, gradual piecemeal replacement of them.
-
-### Stage 1: Solving the Naming Problem
-
-Under the new proposal, a minimum implementation of a custom provider looks like
-this:
-
-```
-# rust.bzl
-
-# Introduces a provider. `rust_provider` is now both a function
-# that can be used to construct the provider instance,
-# and a "symbol" that can be used to access it.
-rust_provider = provider()
-
-def _impl(ctx):
- # `rust_provider` is used as struct-like constructor
- # it accepts the same arguments as a standard `struct` function
- rust = rust_provider(defines = "-DFOO", ...)
- # return value of rule implementation function
- # is just a list of providers; their "names" are specified
- # by their constructors, see below
- return [ctx.provider(files = ...), rust]
-rust_library = rule(implementation = _impl,
- # Optional declaration; the rule MUST provide all the
- # providers in this list
- providers = [rust_provider])
-```
-
-```
-# Example of how to access the provider
-
-load(":rust.bzl", "rust_provider")
-
-def _impl(ctx):
- dep = ctx.attr.deps[0] # Target object
- # `rust_provider` is used as a key to access a particular
- # provider
- defines = dep[rust_provider].defines ...
-```
-
-#### The provider function
-
-* We introduce two new kinds of Skylark values, a *provider declaration* and a
- *provider*.
-* Provider declaration (`rust_provider` in the example) is created using the
- `provider` function.
-* Provider declaration can be used to construct a *provider* (`rust` in the
- example). Provider is a struct-like Skylark value, with the only difference
- that every provider is associated with its declaration (it is a different
- type). Arguments of a provider declaration when used as a function are
- exactly the same as that of a built-in `struct` function.
-* [Target](http://www.bazel.build/docs/skylark/lib/Target.html) objects become
- dictionaries of providers indexed by their declaration. Bracket notation can
- be used to retrieve a particular provider. Thus, provider declarations are
- [symbol-like](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Symbol)
- values.
-* Providers can be private to an extension file; in that case the provider
- cannot be accessed outside that file.
-
-#### Default providers (ctx.provider)
-
-There is a set of default providers (`files`, `runfiles`, `data_runfiles`,
-`executable`, `output_groups`, etc.). We group them in a single provider,
-`ctx.provider`:
-
-```
-defaults = ctx.provider(files = set(), runfiles = ...)
-```
-
-The current set of APIs on Target objects that access these providers
-(`target.files`, `target.output_group("name")` etc.) will continue to work.
-
-#### Return value
-
-The implementation function can return either a provider, or a list of
-providers. It is an error to return two providers of the same type.
-
-```
-return [defaults, rust, cc]
-return ctx.provider(files = set())
-```
-
-#### Declaring providers returned by a rule
-
-Users need to know which rules provide which providers. This is important for
-documentation and for knowing which dependencies are allowed (e.g. we want to
-find easily what can go in the deps attribute of cc_library).
-
-We allow rules to declare the providers they intend to return with a `providers`
-argument of a
-<code>[rule](http://www.bazel.build/docs/skylark/lib/globals.html#rule)</code>
-function. It is an error if the rule implementation function does not return all
-the providers listed in `providers`. It may however return additional providers.
-
-```
-rust_provider = provider()
-
-rust_library = rule(implementation = _impl,
- # Optional declaration; the rule MUST provide all the
- # providers in this list
- providers = [rust_provider])
-```
-
-#### Migration path and support for "legacy" providers
-
-To support current model of returning providers, where they are identified by a
-simple name, we continue to allow providers name in the return struct:
-
-```
-def _impl(ctx):
- ...
- return struct(
- legacy_provider = struct(...),
- files = set(...),
- providers = [rust])
-```
-
-This also works for “default” providers, such as “files”, “runfiles” etc.
-However if one of those legacy names is specified, it is an error to have
-ctx.provider instance in the list of `providers`.
-
-We also allow returning a declared provider both directly and with a simple
-name:
-
-```
-def _impl(ctx):
- ...
- return struct(rust = rust, providers = [rust])
-```
-
-This allows the rules to mix old and new style, and migrate rule definition to a
-new style without changing all the uses of that rule.
-
-Old-style providers with simple names can still be accessed with dot-notation on
-Target object, so all of the following is valid.
-
-Old-style usage:
-
-* `target.rust` (=> rust)
-* `getattr(target, "rust")` (=> rust)
-* `hasattr(target, "rust")` (=> True)
-
-New-style usage:
-
-* `target[rust_provider]` (=> rust)
-* `rust_provider in target` (=> True)
-* `target.keys` (=> [rust_provider])
-* `target.values` (=> [rust])
-* `target.items` (=> [(rust_provider, rust)])
-
-#### type function
-
-Type function on providers returns a string `"provider"`. Type function on a
-provider instance returns a string `"struct"`.
-
-### Stage 2: Documentation and Fields
-
-Provider declarations are a convenient place to add more annotations to
-providers. We propose 2 specific things there:
-
-```
-rust_provider = provider(
- doc = "This provider contains Rust information ...",
- fields = ["defines", "transitive_deps"]
-)
-```
-
-This specifies documentation for the provider and a list of fields that the
-provider can have.
-
-If `fields` argument is present, extra, undeclared fields are not allowed.
-
-Both `doc` and `fields` arguments to `provider` function are optional.
-
-`fields` argument can also be a dictionary (from string to string), in that case
-the keys are names of fields, and the values are documentation strings about
-individual fields
-
-```
-rust_provider = provider(
- doc = "This provider contains Rust information ...",
- fields = {
- "defines": "doc for define",
- "transitive_deps": "doc for transitive deps,
- })
-```
-
-### Native Providers
-
-Providers (as Skylark values) can be also declared natively. A set of
-annotations can be developed to facilitate declaring them with little effort.
-
-As a strawman example:
-
-```
-/**
- * Hypothetical implementation of Skylark provider value (result of
- * provider(..) function.
- */
-class SkylarkProviderValue extends SkylarkValue {
- ...
- /**
- * Creates a SkylarkProviderValue for a native provider
- * `native` must be annotated with @SkylarkProvider annotation.
- * Field accessors and constructor function appear magically.
- */
- static <T> SkylarkProviderValue forNative(Class<T> native) { ... }
-}
-
-@SkylarkProvider(builder = Builder.class)
-// A class with this annotation can be used as provider declaration
-class rustProvider implements TransitiveInfoProvider {
- @SkylarkProviderField(doc = ...)
- // Skylark name is 'defines'
- String getDefines() { ... }
-
- @SkylarkProviderField(doc = ...)
- // Skylark name is 'transitive_deps'
- NestedSet<Artifact> getTransitiveDeps() { ... }
-
- @SkylarkProviderField(doc = ...)
- // Not allowed, the set of types exposed to Skylark is restricted
- DottedVersion getVersion() { ... }
-
- // Automatically used to provide an implementation for
- // construction function.
- static class Builder {
- // a setter for 'defines' field, based on name.
- void setDefines(String defines) { ... }
- // a setter for 'transitive_deps' field, based on name.
- void setTransitiveDeps(...) {...}
- rustProvider build() { ... }
- }
-}
-```