aboutsummaryrefslogtreecommitdiffhomepage
path: root/site/docs/skylark/rules.md
diff options
context:
space:
mode:
Diffstat (limited to 'site/docs/skylark/rules.md')
-rw-r--r--site/docs/skylark/rules.md460
1 files changed, 2 insertions, 458 deletions
diff --git a/site/docs/skylark/rules.md b/site/docs/skylark/rules.md
index 809b8763da..22b62057eb 100644
--- a/site/docs/skylark/rules.md
+++ b/site/docs/skylark/rules.md
@@ -1,460 +1,4 @@
---
-layout: documentation
-title: Rules
+layout: redirect
+redirect: docs/skylark/rules.html
---
-# Rules
-
-**Status: Experimental**. We may make breaking changes to the API, but we will
- help you update your code.
-
-A rule defines a series of actions that Bazel should perform on inputs to get a
-set of outputs. For example, a C++ binary rule might take a set of .cpp
-files (the inputs), run `g++` on them (the action), and return an executable
-file (the output).
-
-Note that, from Bazel's perspective, `g++` and the standard C++ libraries are
-also inputs to this rule. As a rule writer, you must consider not only the
-user-provided inputs to a rule, but also all of the tools and libraries required
-to execute the actions (called _implicit inputs_).
-
-## Rule creation
-
-In a `.bzl` file, use the [rule](lib/globals.html#rule)
-function to create a new rule and store it in a global variable:
-
-```python
-my_rule = rule(...)
-```
-
-See [the cookbook](cookbook.md#empty) for examples. The rule can then be
-loaded by BUILD files:
-
-```python
-load('//some/pkg:whatever.bzl', 'my_rule')
-```
-
-A custom rule can be used just like a native rule. It has a mandatory `name`
-attribute, you can refer to it with a label, and you can see it in
-`bazel query`.
-
-The rule is analyzed when you explicitly build it, or if it is a dependency of
-the build. In this case, Bazel will execute its `implementation` function. This
-function decides what the outputs of the rule are and how to build them (using
-`actions`). During analysis, no external command can be executed: actions will
-be run in the execution phase.
-
-## Attributes
-
-An attribute is a rule argument, such as `srcs` or `deps`. You must list
-the attributes and their types when you define a rule.
-
-```python
-sum = rule(
- implementation = impl,
- attrs = {
- "number": attr.int(default = 1),
- "deps": attr.label_list(),
- },
-)
-```
-
-The following attributes are implicitly added to every rule: `deprecation`,
-`features`, `name`, `tags`, `testonly`, `visibility`. Test rules also have the
-following attributes: `args`, `flaky`, `local`, `shard_count`, `size`,
-`timeout`.
-
-Labels listed in `attr` will be inputs to the rule.
-
-To access an attribute in a rule's implementation, use
-`ctx.attr.<attribute_name>`. The name and the package of a rule are available
-with `ctx.label.name` and `ctx.label.package`.
-
-See [an example](cookbook.md#attr) of using `attr` in a rule.
-
-### <a name="private-attributes"></a> Private Attributes
-
-If an attribute name starts with `_` it is private and users cannot set it. It
-is useful in particular for label attributes (your rule will have an
-implicit dependency on this label).
-
-```python
-metal_compile = rule(
- implementation=impl,
- attrs={
- "srcs": attr.label_list(),
- "_compiler": attr.label(
- default=Label("//tools:metalc"),
- allow_single_file=True,
- executable=True,
- ),
- },
-)
-```
-
-## Implementation function
-
-Every rule requires an `implementation` function. It contains the actual
-logic of the rule and is executed strictly in the Analysis Phase. The function
-has exactly one input parameter, `ctx`, and it may return
-the [runfiles](#runfiles) and [providers](#providers)
-of the rule. The input parameter `ctx` can be used to access attribute values,
-outputs and dependent targets, and files. It also has some helper functions.
-See [the library](lib/ctx.html) for more context. Example:
-
-```python
-def impl(ctx):
- ...
- return struct(
- runfiles=...,
- my_provider=...,
- ...
- )
-
-my_rule = rule(
- implementation=impl,
- ...
-)
-```
-
-## Files
-
-There are two kinds of files: files stored in the file system and generated
-files. For each generated file, there must be one and only one generating
-action, and each action must generate one or more output files. Bazel will throw
-an error otherwise.
-
-## Targets
-
-Every build rule corresponds to exactly one target. A target can create
-[actions](#actions), can have dependencies (which can be files or
-other build rules), [output files](#output-files) (generated by
-its actions), and [providers](#providers).
-
-A target `y` depends on target `x` if `y` has a label or label list type
-attribute where `x` is declared:
-
-```python
-my_rule(
- name = "x",
-)
-
-my_rule(
- name = "y",
- deps = [":x"],
-)
-```
-
-In the above case, it's possible to access targets declared in `my_rule.deps`:
-
-```python
-def impl(ctx):
- for dep in ctx.attr.deps:
- # Do something with dep
- ...
-
-my_rule = rule(
- implementation=impl,
- attrs={
- "deps": attr.label_list(),
- },
- ...
-)
-```
-
-## <a name="output-files"></a> Output files
-
-A target can declare output files, which must be generated by the target's
-actions. There are three ways to create output files:
-
-* If the rule is marked `executable`, it creates an output file of the same name
- as the rule's. [See example](cookbook.md#outputs-executable)
-
-* The rule can declare default `outputs`, which are always generated.
- [See example](cookbook.md#outputs-default)
-
-* The rule can have output or output list type attributes. In that case the
- output files come from the actual attribute values.
- [See example](cookbook.md#outputs-custom)
-
-Each output file must have exactly one generating action. See the
-[library](lib/ctx.html#outputs) for more context.
-
-## Default outputs
-
-Every rule has a set of default outputs. This is used:
-
-* When the user runs `bazel build` on your target. Bazel will build the default
- outputs of the rule.
-
-* When the target is used as a dependency of another rule. A rule can access
- the default outputs by using [target.files](lib/Target.html#files).
- This is the case, for example, if you use a rule in the `srcs` attribute of a
- `genrule`.
-
-Use the `files` provider to specify the default outputs of a rule.
-If left unspecified, it will contain all the declared outputs.
-
-```python
-def _impl(ctx):
- # ...
- return struct(files=set([file1, file2]))
-```
-
-This can be useful for exposing files generated with
-[ctx.new_file](lib/ctx.html#new_file). You can also have "implicit
-outputs", i.e., files that are declared in the rule, but not in the default
-outputs (like `_deploy.jar` in `java_binary`).
-
-## Actions
-
-There are three ways to create actions:
-
-* [ctx.action](lib/ctx.html#action), to run a command.
-* [ctx.file_action](lib/ctx.html#file_action), to write a string to a file.
-* [ctx.template_action](lib/ctx.html#template_action), to generate a file from a template.
-
-Actions take a set (which can be empty) of input files and generate a (non-empty)
-set of output files.
-The set of input and output files must be known during the analysis phase. It
-might depend on the value of attributes and information from dependencies, but
-it cannot depend on the result of the execution. For example, if your action
-runs the unzip command, you must specify which files you expect to be inflated
-(before running unzip).
-
-Actions are comparable to pure functions: They should depend only on the
-provided inputs, and avoid accessing computer information, username, clock,
-network, or I/O devices (except for reading inputs and writing outputs).
-
-**If an action generates a file that is not listed in its outputs**: This is
-fine, but the file will be ignored and cannot be used by other rules.
-
-**If an action does not generate a file that is listed in its outputs**: This is
-an execution error and the build will fail. This happens for instance when a
-compilation fails.
-
-**If an action generates an unknown number of outputs and you want to keep them
-all**, you must group them in a single file (e.g., a zip, tar, or other
-archive format). This way, you will be able to deterministically declare your
-outputs.
-
-**If an action does not list a file it uses as an input**, the action execution
-will most likely result in an error. The file is not guaranteed to be available
-to the action, so if it **is** there, it's due to coincidence or error.
-
-**If an action lists a file as an input, but does not use it**: This is fine.
-However, it can affect action execution order, resulting in sub-optimal
-performance.
-
-Dependencies are resolved by Bazel, which will decide which actions are
-executed. It is an error if there is a cycle in the dependency graph. Creating
-an action does not guarantee that it will be executed: It depends on whether
-its outputs are needed for the build.
-
-## Configurations
-
-By default, a target is built in the target configuration. For each label
-attribute, you can decide whether the dependency should be built in the same
-configuration, or in the host configuration.
-
-In general, sources, dependent libraries, and executables that will be needed at
-runtime can use the same configuration.
-
-Tools that are executed as part of the build (e.g., compilers, code generators)
-should be built for the host configuration. In this case, specify `cfg="host"`
-in the attribute.
-
-The configuration `"data"` is present for legacy reasons and should be used for
-the `data` attributes.
-
-
-## <a name="fragments"></a> Configuration Fragments
-
-Rules may access configuration fragments such as `cpp`, `java` and `jvm`.
-However, all required fragments must be declared in order to avoid access
-errors:
-
-```python
-def impl(ctx):
- # Using ctx.fragments.cpp would lead to an error since it was not declared.
- x = ctx.fragments.java
- ...
-
-my_rule = rule(
- implementation=impl,
- fragments=["java"], # Required fragments of the target configuration
- host_fragments=["java"], # Required fragments of the host configuration
- ...
-)
-```
-
-`ctx.fragments` only provides configuration fragments for the target
-configuration. If you want to access fragments for the host configuration,
-use `ctx.host_fragments` instead.
-
-## Providers
-
-Providers are used to access information from other rules. A rule depending on
-another rule has access to the data the latter provides. These data can be e.g.
-output files, the libraries the dependent rule is using to link or compile, or
-anything the depending rule should know about. Using providers is the only way
-to exchange data between rules.
-
-A rule can only access data provided by its direct dependencies, not that of
-transitive dependencies: if rule `top` depends on `middle`, and `middle` depends
-on `bottom`, then `middle` is a direct dependency of `top` and `bottom` is a
-transitive dependency of `top`. In this scenario `top` can only access data
-provided by `middle`. If `middle` also provides the data that `bottom` provided
-to it, then and only then can `top` access it.
-
-The following data types can be passed using providers:
-
-* `bool`
-* `integer`
-* `string`
-* `file`
-* `label`
-* `None`
-* anything composed of these types and `lists`, `dicts`, `sets` or `structs`
-
-Providers are created from the return value of the rule implementation function:
-
-```python
-def rule_implementation(ctx):
- ...
- return struct(
- transitive_data=set(["a", "b", "c"])
- )
-```
-
-A dependent rule might access these data as struct fields of the `target` being
-depended upon:
-
-```python
-def dependent_rule_implementation(ctx):
- ...
- s = set()
- for dep_target in ctx.attr.deps:
- # Use `print(dir(dep_target))` to see the list of providers.
- s += dep_target.transitive_data
- ...
-```
-
-Providers are only available during the analysis phase. Examples of usage:
-
-* [mandatory providers](cookbook.md#mandatory-providers)
-* [optional providers](cookbook.md#optional-providers)
-
-## Runfiles
-
-Runfiles are a set of files used by the (often executable) output of a rule
-during runtime (as opposed to build time, i.e. when the binary itself is
-generated).
-During execution, Bazel creates a directory tree containing symlinks pointing to
-the runfiles, staging the environment for the binary so it can access the
-runfiles during runtime.
-
-Runfiles can be added manually during rule creation and/or collected
-transitively from the rule's dependencies:
-
-```python
-def rule_implementation(ctx):
- ...
- transitive_runfiles = set()
- for dep in ctx.attr.special_dependencies:
- transitive_runfiles += dep.transitive_runtime_files
-
- runfiles = ctx.runfiles(
- # Add some files manually.
- files=[ctx.file.some_data_file],
- # Add transitive files from dependencies manually.
- transitive_files=transitive_runfiles,
- # Collect runfiles from the common locations: transitively from srcs,
- # deps and data attributes.
- collect_default=True,
- )
- # Add a field named "runfiles" to the return struct in order to actually
- # create the symlink tree.
- return struct(runfiles=runfiles)
-```
-
-Note that non-executable rule outputs can also have runfiles. For example, a
-library might need some external files during runtime, and every dependent
-binary should know about them.
-
-Also note that if an action uses an executable, the executable's runfiles can
-be used when the action executes.
-
-Normally, the relative path of a file in the runfiles tree is the same as the
-relative path of that file in the source tree or generated output tree. If these
-need to be different for some reason, you can specify the `root_symlinks` or
-`symlinks` arguments. The `root_symlinks` is a dictionary mapping paths to
-files, where the paths are relative to the root of the runfiles directory. The
-`symlinks` dictionary is the same, but paths are implicitly prefixed with the
-name of the workspace.
-
-```python
- ...
- runfiles = ctx.runfiles(
- root_symlinks={"some/path/here.foo": ctx.file.some_data_file2}
- symlinks={"some/path/here.bar": ctx.file.some_data_file3}
- )
- # Creates something like:
- # sometarget.runfiles/
- # some/
- # path/
- # here.foo -> some_data_file2
- # <workspace_name>/
- # some/
- # path/
- # here.bar -> some_data_file3
-```
-
-If `symlinks` or `root_symlinks` is used, be careful not to map two different
-files to the same path in the runfiles tree. This will cause the build to fail
-with an error describing the conflict. To fix, you will need to modify your
-`ctx.runfiles` arguments to remove the collision. This checking will be done for
-any targets using your rule, as well as targets of any kind that depend on those
-targets.
-
-## Instrumented files
-
-Instrumented files are a set of files used by the coverage command. A rule can
-use the `instrumented_files` provider to provide information about which files
-should be used for measuring coverage.
-
-```python
-def rule_implementation(ctx):
- ...
- return struct(instrumented_files=struct(
- # Optional: File extensions used to filter files from source_attributes.
- # If not provided, then all files from source_attributes will be
- # added to instrumented files, if an empty list is provided, then
- # no files from source attributes will be added.
- extensions=["ext1", "ext2"],
- # Optional: Attributes that contain source files for this rule.
- source_attributes=["srcs"],
- # Optional: Attributes for dependencies that could include instrumented
- # files.
- dependency_attributes=["data", "deps"]))
-```
-
-## Executable rules
-
-An executable rule is a rule that users can run using `bazel run`.
-
-To make a rule executable, set `executable=True` in the
-[rule function](lib/globals.html#rule). During the analysis
-phase, the rule must generate the output file `ctx.outputs.executable`.
-[See example](cookbook.md#outputs-executable)
-
-## Test rules
-
-Test rules are run using `bazel test`.
-
-To create a test rule, set `test=True` in the
-[rule function](lib/globals.html#rule). The name of the rule must
-also end with `_test`. Test rules are implicitly executable, which means they
-must generate the output file `ctx.outputs.executable`.
-
-Test rules inherit the following attributes: `args`, `flaky`, `local`,
-`shard_count`, `size`, `timeout`.