aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--site/docs/skylark/rules.md126
-rw-r--r--src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkAttrApi.java96
2 files changed, 132 insertions, 90 deletions
diff --git a/site/docs/skylark/rules.md b/site/docs/skylark/rules.md
index 8715a68574..4327199404 100644
--- a/site/docs/skylark/rules.md
+++ b/site/docs/skylark/rules.md
@@ -16,11 +16,30 @@ 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_).
+to execute the actions (called _implicit dependencies_).
Before creating or modifying any rule, make sure you are familiar with the
-[evaluation model](concepts.md) (understand the three phases of execution and the
-differences between macros and rules).
+[evaluation model](concepts.md). You must understand the three phases of
+execution and the differences between macros and rules.
+
+A few rules are built into Bazel itself. These *native rules*, such as
+`cc_library` and `java_binary`, provide some core support for certain languages.
+By defining your own rules, you can add similar support for languages and tools
+that Bazel does not support natively.
+
+Rules defined in .bzl files work just like native rules. For example, their
+targets have labels, can appear in `bazel query`, and get built whenever they
+are needed for a `bazel build` command or similar. When defining your own rule,
+you get to decide what attributes it supports and how it generates its outputs.
+
+The exact behavior of a rule during the
+[analysis phase](concepts.md#evaluation-model) is governed by its
+`implementation` function. This function does not run any external commands.
+Rather, it registers [actions](#actions) that will be used later during the
+execution phase to build the rule's outputs, if they are needed. Rules also
+produce and pass along information that may be useful to other rules, in the
+form of [providers](#providers).
+
<!-- [TOC] -->
@@ -39,24 +58,13 @@ The rule can then be loaded in `BUILD` files:
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](#actions)). During the [analysis phase](concepts.md#evaluation-model),
-no external command can be executed. Instead, actions are registered and
-will be run in the execution phase, if their output is needed for the build.
-
[See example](https://github.com/bazelbuild/examples/tree/master/rules/empty).
## 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. Create attributes using
-the [attr](lib/attr.html) module.
+An attribute is a rule argument, such as `srcs` or `deps`. You must list the
+names and schemas of all attributes when you define a rule. Attribute schemas
+are created using the [attr](lib/attr.html) module.
```python
sum = rule(
@@ -68,11 +76,6 @@ sum = rule(
)
```
-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`.
-
In a `BUILD` file, call the rule to create targets of this type:
```python
@@ -86,10 +89,32 @@ sum(
)
```
-Label attributes like `deps` above are used to declare dependencies. The target
-whose label is mentioned becomes a dependency of the target with the attribute.
-Therefore, `other-target` will be analyzed before `my-target`.
+Here `other-target` is a dependency of `my-target`, and therefore `other-target`
+will be analyzed first.
+
+There are two special kinds of attributes:
+
+* *Dependency attributes*, such as `attr.label` and `attr.label_list`,
+ declare a dependency from the target that owns the attribute to the target
+ whose label appears in the attribute's value. This kind of attribute forms the
+ basis of the target graph.
+
+* *Output attributes*, such as `attr.output` and `attr.output_list`, declare an
+ output file that the target generates. Although they refer to the output file
+ by label, they do not create a dependency relationship between targets. Output
+ attributes are used relatively rarely, in favor of other ways of declaring
+ output files that do not require the user to specify a label.
+
+Both dependency attributes and output attributes take in label values. These may
+be specified as either [`Label`](lib/Label.html) objects or as simple strings.
+If a string is given, it will be converted to a `Label` using the
+[constructor](lib/Label.html#Label). The repository, and possibly the path, will
+be resolved relative to the defined target.
+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`.
### <a name="private-attributes"></a> Private Attributes
@@ -152,11 +177,11 @@ of declaring and accessing attributes.
## Targets
-Each call to a build rule has the side effect of defining a new target (also
-called instantiating the rule). The dependencies of the new target are any other
-targets whose labels are mentioned in an attribute of type `attr.label` or
-`attr.label_list`. In the following example, the target `//mypkg:y` depends on
-the targets `//mypkg:x` and `//mypkg:z.foo`.
+Each call to a build rule returns no value but has the side effect of defining a
+new target; this is called instantiating the rule. The dependencies of the new
+target are any other targets whose labels are mentioned in its dependency
+attributes. In the following example, the target `//mypkg:y` depends on the
+targets `//mypkg:x` and `//mypkg:z.foo`.
```python
# //mypkg:BUILD
@@ -165,6 +190,8 @@ my_rule(
name = "x",
)
+# Assuming that my_rule has attributes "deps" and "srcs",
+# of type attr.label_list()
my_rule(
name = "y",
deps = [":x"],
@@ -172,16 +199,11 @@ my_rule(
)
```
-Targets are represented at analysis time as [`Target`](lib/Target.html) objects.
-These objects contain the information produced by analyzing a target -- in
-particular, its [providers](#providers).
-
-In a rule's implementation function, the current target's dependencies are
-accessed using `ctx.attr`, just like any other attribute's value. However,
-unlike other types, attributes of type `attr.label` and `attr.label_list` have
-the special behavior that each label value is replaced by its corresponding
-`Target` object. This allows the current target being analyzed to consume the
-providers of its dependencies.
+Dependencies are represented at analysis time as [`Target`](lib/Target.html)
+objects. These objects contain the information produced by analyzing a target --
+in particular, its [providers](#providers). The current target can access its
+dependencies' `Target` objects within its rule implementation function by using
+`ctx.attr`.
## Files
@@ -196,9 +218,9 @@ be an output of exactly one action. Source files cannot be the output of any
action.
Some files, including all source files, are addressable by labels. These files
-have `Target` objects associated with them. If a file's label is used in a
-`attr.label` or `attr.label_list` attribute (for example, in a `srcs`
-attribute), the `ctx.attr.<attr_name>` entry for it will contain the
+have `Target` objects associated with them. If a file's label appears within a
+dependency attribute (for example, in a `srcs` attribute of type
+`attr.label_list`), the `ctx.attr.<attr_name>` entry for it will contain the
corresponding `Target`. The `File` object can be obtained from this `Target`'s
`files` field. This allows the file to be referenced in both the target graph
and the action graph.
@@ -241,12 +263,12 @@ analysis using the [`ctx.actions.declare_file`](lib/actions.html#declare_file)
and [`ctx.actions.declare_directory`](lib/actions.html#declare_directory)
functions. Both kinds of outputs may be passed along in providers.
-Although the input files of a target -- those files passed through attributes of
-`attr.label` and `attr.label_list` type -- can be accessed indirectly via
-`ctx.attr`, it is more convenient to use `ctx.file` and `ctx.files`. For output
-files that are predeclared using attributes of `attr.output` or
-`attr.output_list` type, `ctx.attr` will only return the label, and you must use
-`ctx.outputs` to get the actual `File` object.
+Although the input files of a target -- those files passed through dependency
+attributes -- can be accessed indirectly via `ctx.attr`, it is more convenient
+to use `ctx.file` and `ctx.files`. For output files that are predeclared using
+output attributes (attributes of type `attr.output` or `attr.output_list`),
+`ctx.attr` will only return the label, and you must use `ctx.outputs` to get the
+actual `File` object.
[See example of predeclared outputs](https://github.com/bazelbuild/examples/blob/master/rules/predeclared_outputs/hash.bzl)
@@ -327,9 +349,9 @@ tool, the label attribute will specify a transition to the host configuration.
This causes the tool and all of its dependencies to be built for the host
machine, assuming those dependencies do not themselves have transitions.
-For each [label attribute](lib/attr.html#label), you can decide whether the
-dependency should be built in the same configuration, or transition to the host
-configuration (using `cfg`). If a label attribute has the flag
+For each dependency attribute, you can decide whether the dependency target
+should be built in the same configuration, or transition to the host
+configuration (using `cfg`). If a dependency attribute has the flag
`executable=True`, the configuration must be set explicitly.
[See example](https://github.com/bazelbuild/examples/blob/master/rules/actions_run/execute.bzl)
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkAttrApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkAttrApi.java
index edc3fb8165..1da54ba761 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkAttrApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkAttrApi.java
@@ -39,17 +39,44 @@ import com.google.devtools.build.lib.syntax.UserDefinedFunction;
namespace = true,
category = SkylarkModuleCategory.BUILTIN,
doc =
- "Module for creating new attributes. "
- + "They are only for use with <a href=\"globals.html#rule\">rule</a> or "
- + "<a href=\"globals.html#aspect\">aspect</a>. "
- + "<a href=\"https://github.com/bazelbuild/examples/tree/master/rules/"
- + "attributes/printer.bzl\">See example of use</a>.")
+ "This is a top-level module for defining the attribute schemas of a rule or aspect. Each "
+ + "function returns an object representing the schema of a single attribute. These "
+ + "objects are used as the values of the <code>attrs</code> dictionary argument of "
+ + "<a href=\"globals.html#rule\"><code>rule()</code></a> and "
+ + "<a href=\"globals.html#aspect\"><code>aspect()</code></a>."
+ + ""
+ + "<p>See the Rules page for more on "
+ + "<a href='../rules.$DOC_EXT#attributes'>defining</a> and "
+ + "<a href='../rules.$DOC_EXT#implementation-function'>using</a> attributes.")
public interface SkylarkAttrApi extends SkylarkValue {
+ // dependency and output attributes
+ static final String LABEL_PARAGRAPH =
+ "<p>This attribute contains <a href='Label.html'><code>Label</code></a> values. If a string "
+ + "is supplied in place of a <code>Label</code>, it will be converted using the "
+ + "<a href='Label.html#Label'>label constructor</a>. The relative parts of the label "
+ + "path, including the (possibly renamed) repository, are resolved with respect to the "
+ + "instantiated target's package.";
+
+ // attr.label, attr.label_list, attr.label_keyed_string_dict
+ static final String DEPENDENCY_ATTR_TEXT =
+ LABEL_PARAGRAPH
+ + "<p>At analysis time (within the rule's implementation function), when retrieving the "
+ + "attribute value from <code>ctx.attr</code>, labels are replaced by the corresponding "
+ + "<a href='Target.html'><code>Target</code></a>s. This allows you to access the "
+ + "providers of the currrent target's dependencies.";
+
+ // attr.output, attr.output_list
+ static final String OUTPUT_ATTR_TEXT =
+ LABEL_PARAGRAPH
+ + "<p>At analysis time, the corresponding <a href='File.html'><code>File</code></a> can "
+ + "be retrieved using <code>ctx.outputs</code>.";
+
static final String ALLOW_FILES_ARG = "allow_files";
static final String ALLOW_FILES_DOC =
- "Whether File targets are allowed. Can be True, False (default), or a list of file "
- + "extensions that are allowed (for example, <code>[\".cc\", \".cpp\"]</code>).";
+ "Whether <code>File</code> targets are allowed. Can be <code>True</code>, <code>False</code> "
+ + "(default), or a list of file extensions that are allowed (for example, "
+ + "<code>[\".cc\", \".cpp\"]</code>).";
static final String ALLOW_RULES_ARG = "allow_rules";
static final String ALLOW_RULES_DOC =
@@ -62,6 +89,7 @@ public interface SkylarkAttrApi extends SkylarkValue {
+ "attribute.";
static final String CONFIGURATION_ARG = "cfg";
+ // TODO(bazel-team): Update when new Skylark-based configuration framework is implemented.
static final String CONFIGURATION_DOC =
"<a href=\"../rules.$DOC_EXT#configurations\">Configuration</a> of the attribute. It can be "
+ "either <code>\"host\"</code> or <code>\"target\"</code>.";
@@ -76,7 +104,7 @@ public interface SkylarkAttrApi extends SkylarkValue {
static final String EXECUTABLE_ARG = "executable";
static final String EXECUTABLE_DOC =
- "True if the label has to be executable. This means the label must refer to an "
+ "True if the dependency has to be executable. This means the label must refer to an "
+ "executable file, or to a rule that outputs an executable file. Access the label "
+ "with <code>ctx.executable.&lt;attribute_name&gt;</code>.";
@@ -88,7 +116,7 @@ public interface SkylarkAttrApi extends SkylarkValue {
static final String NON_EMPTY_ARG = "non_empty";
static final String NON_EMPTY_DOC =
- "True if the attribute must not be empty. Deprecated: Use allow_empty instead.";
+ "True if the attribute must not be empty. Deprecated: Use <code>allow_empty</code> instead.";
static final String ALLOW_EMPTY_ARG = "allow_empty";
static final String ALLOW_EMPTY_DOC = "True if the attribute can be empty.";
@@ -110,7 +138,7 @@ public interface SkylarkAttrApi extends SkylarkValue {
@SkylarkCallable(
name = "int",
- doc = "Creates an attribute of type int.",
+ doc = "Creates a schema for an integer attribute.",
parameters = {
@Param(
name = DEFAULT_ARG,
@@ -158,7 +186,7 @@ public interface SkylarkAttrApi extends SkylarkValue {
@SkylarkCallable(
name = "string",
- doc = "Creates an attribute of type <a href=\"string.html\">string</a>.",
+ doc = "Creates a schema for a string attribute.",
parameters = {
@Param(
name = DEFAULT_ARG,
@@ -206,11 +234,8 @@ public interface SkylarkAttrApi extends SkylarkValue {
@SkylarkCallable(
name = "label",
doc =
- "Creates an attribute of type <a href=\"Target.html\">Target</a> which is the target "
- + "referred to by the label. "
- + "It is the only way to specify a dependency to another target. "
- + "If you need a dependency that the user cannot overwrite, "
- + "<a href=\"../rules.$DOC_EXT#private-attributes\">make the attribute private</a>.",
+ "Creates a schema for a label attribute. This is a dependency attribute."
+ + DEPENDENCY_ATTR_TEXT,
parameters = {
@Param(
name = DEFAULT_ARG,
@@ -335,8 +360,7 @@ public interface SkylarkAttrApi extends SkylarkValue {
@SkylarkCallable(
name = "string_list",
doc =
- "Creates an attribute which is a <a href=\"list.html\">list</a> of "
- + "<a href=\"string.html\">strings</a>.",
+ "Creates a schema for a list-of-strings attribute.",
parameters = {
@Param(
name = MANDATORY_ARG,
@@ -388,7 +412,7 @@ public interface SkylarkAttrApi extends SkylarkValue {
@SkylarkCallable(
name = "int_list",
- doc = "Creates an attribute which is a <a href=\"list.html\">list</a> of ints.",
+ doc = "Creates a schema for a list-of-integers attribute.",
parameters = {
@Param(
name = MANDATORY_ARG,
@@ -441,9 +465,8 @@ public interface SkylarkAttrApi extends SkylarkValue {
@SkylarkCallable(
name = "label_list",
doc =
- "Creates an attribute which is a <a href=\"list.html\">list</a> of type "
- + "<a href=\"Target.html\">Target</a> which are specified by the labels in the list. "
- + "See <a href=\"attr.html#label\">label</a> for more information.",
+ "Creates a schema for a list-of-labels attribute. This is a dependency attribute."
+ + DEPENDENCY_ATTR_TEXT,
parameters = {
@Param(
name = ALLOW_EMPTY_ARG,
@@ -556,10 +579,9 @@ public interface SkylarkAttrApi extends SkylarkValue {
@SkylarkCallable(
name = "label_keyed_string_dict",
doc =
- "Creates an attribute which is a <a href=\"dict.html\">dict</a>. Its keys are type "
- + "<a href=\"Target.html\">Target</a> and are specified by the label keys of the "
- + "input dict. Its values are <a href=\"string.html\">strings</a>. See "
- + "<a href=\"attr.html#label\">label</a> for more information.",
+ "Creates a schema for an attribute holding a dictionary, where the keys are labels and "
+ + "the values are strings. This is a dependency attribute."
+ + DEPENDENCY_ATTR_TEXT,
parameters = {
@Param(
name = ALLOW_EMPTY_ARG,
@@ -672,7 +694,7 @@ public interface SkylarkAttrApi extends SkylarkValue {
@SkylarkCallable(
name = "bool",
- doc = "Creates an attribute of type bool.",
+ doc = "Creates a schema for a boolean attribute.",
parameters = {
@Param(
name = DEFAULT_ARG,
@@ -708,9 +730,8 @@ public interface SkylarkAttrApi extends SkylarkValue {
@SkylarkCallable(
name = "output",
doc =
- "Creates an attribute of type output. "
- + "The user provides a file name (string) and the rule must create an action that "
- + "generates the file.",
+ "Creates a schema for an output (label) attribute."
+ + OUTPUT_ATTR_TEXT,
parameters = {
@Param(
name = DEFAULT_ARG,
@@ -747,8 +768,8 @@ public interface SkylarkAttrApi extends SkylarkValue {
@SkylarkCallable(
name = "output_list",
doc =
- "Creates an attribute which is a <a href=\"list.html\">list</a> of outputs. "
- + "See <a href=\"attr.html#output\">output</a> for more information.",
+ "Creates a schema for a list-of-outputs attribute."
+ + OUTPUT_ATTR_TEXT,
parameters = {
@Param(
name = ALLOW_EMPTY_ARG,
@@ -803,8 +824,8 @@ public interface SkylarkAttrApi extends SkylarkValue {
@SkylarkCallable(
name = "string_dict",
doc =
- "Creates an attribute of type <a href=\"dict.html\">dict</a>, mapping from "
- + "<a href=\"string.html\">string</a> to <a href=\"string.html\">string</a>.",
+ "Creates a schema for an attribute holding a dictionary, where the keys and values are "
+ + "strings.",
parameters = {
@Param(
name = ALLOW_EMPTY_ARG,
@@ -859,9 +880,8 @@ public interface SkylarkAttrApi extends SkylarkValue {
@SkylarkCallable(
name = "string_list_dict",
doc =
- "Creates an attribute of type <a href=\"dict.html\">dict</a>, mapping from "
- + "<a href=\"string.html\">string</a> to <a href=\"list.html\">list</a> of "
- + "<a href=\"string.html\">string</a>.",
+ "Creates a schema for an attribute holding a dictionary, where the keys are strings and "
+ + "the values are lists of strings.",
parameters = {
@Param(
name = ALLOW_EMPTY_ARG,
@@ -915,7 +935,7 @@ public interface SkylarkAttrApi extends SkylarkValue {
@SkylarkCallable(
name = "license",
- doc = "Creates an attribute of type license.",
+ doc = "Creates a schema for a license attribute.",
// TODO(bazel-team): Implement proper license support for Skylark.
parameters = {
// TODO(bazel-team): ensure this is the correct default value