Skip to content

Commit

Permalink
Revamp docs for ctx.outputs
Browse files Browse the repository at this point in the history
Explain the deprecation of ctx.outputs.executable.

RELNOTES: None
PiperOrigin-RevId: 187640408
  • Loading branch information
brandjon authored and Copybara-Service committed Mar 2, 2018
1 parent f442ad5 commit 864ac52
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 42 deletions.
49 changes: 27 additions & 22 deletions site/docs/skylark/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,17 +215,20 @@ analysis time.
A generated file that is addressable by a label is called a *predeclared
output*. There are multiple ways for a rule to introduce a predeclared output:

* If the rule declares an [`outputs`](lib/globals.html#rule.outputs) dict in its
call to `rule()`, then each entry in this dict becomes an output. The output's
label is chosen automatically as specified by the entry, usually by
substituting into a string template. This is the most common way to define
outputs.
[See example](https://github.com/bazelbuild/examples/blob/master/rules/default_outputs/extension.bzl)

* The rule can have an attribute of type [`output`](lib/attr.html#output) or
[`output_list`](lib/attr.html#output_list). In this case the user explicitly
chooses the label for the output when they instantiate the rule.
[See example](https://github.com/bazelbuild/examples/blob/master/rules/custom_outputs/extension.bzl)

* The rule can predeclare outputs using the [`outputs`](lib/globals.html#rule.outputs)
argument of the `rule()` function. The label for the output is chosen
automatically, usually by substituting into a template.
[See example](https://github.com/bazelbuild/examples/blob/master/rules/default_outputs/extension.bzl)

* If the rule is marked [`executable`](lib/globals.html#rule.executable) or
* **(Deprecated)** If the rule is marked
[`executable`](lib/globals.html#rule.executable) or
[`test`](lib/globals.html#rule.test), an output is created with the same name
as the rule instance itself. (Technically, the file has no label since it
would clash with the rule instance's own label, but it is still considered a
Expand All @@ -235,8 +238,9 @@ output*. There are multiple ways for a rule to introduce a predeclared output:
[See example](https://github.com/bazelbuild/examples/blob/master/rules/executable/executable.bzl)

All predeclared outputs can be accessed within the rule's implementation
function under the [`ctx.outputs`](lib/ctx.html#output) struct. Non-predeclared
outputs are created during analysis using the [`ctx.actions.declare_file`](lib/actions.html#declare_file)
function under the [`ctx.outputs`](lib/ctx.html#output) struct; see that page
for details and restrictions. Non-predeclared outputs are created during
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.

Expand Down Expand Up @@ -647,20 +651,21 @@ setting the respective [`executable`](lib/globals.html#rule.executable) or
Test rules (but not necessarily their targets) must have names that end in
`_test`. Non-test rules must not have this suffix.

Both kinds of rules automatically predeclare an output file, which is made
available to the rule implementation function under the name
`ctx.outputs.executable`. The rule implementation function should produce an
action that will generate a corresponding executable file on the file system.
This means that if you use `ctx.actions.write()` to produce the file, then you
should pass `is_executable=True`; and if you use `ctx.actions.run()` or
`ctx.actions.run_shell()` instead, then you should ensure that the binary or
script being invoked sets the executable bit when it creates the file.

By default, this executable is what will be invoked by the `run` or `test`
commands. Alternatively, you can override this behavior by passing a different
file to the `executable` argument of a returned `DefaultInfo` provider. In that
case, you should not attempt to create an action that has
`ctx.outputs.executable` as an input or output.
Both kinds of rules must produce an executable output file (which may or may not
be predeclared) that will be invoked by the `run` or `test` commands. To tell
Bazel which of a rule's outputs to use as this executable, pass it as the
`executable` argument of a returned `DefaultInfo` provider.

The action that generates this file must set the executable bit on the file. For
a `ctx.actions.run()` or `ctx.actions.run_shell()` action this should be done by
the underlying tool that is invoked by the action. For a `ctx.actions.write()`
action it is done by passing the argument `is_executable=True`.

As legacy behavior, executable rules have a special `ctx.outputs.executable`
predeclared output. This file serves as the default executable if you do not
specify one using `DefaultInfo`; it must not be used otherwise. This output
mechanism is deprecated because it does not support customizing the executable
file's name at analysis time.

See examples of an [executable rule](https://github.com/bazelbuild/examples/blob/master/rules/executable/executable.bzl)
and a [test rule](https://github.com/bazelbuild/examples/blob/master/rules/test_rule/line_length.bzl).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -412,9 +412,24 @@ public Provider invoke(String doc, Object fields, Location location) throws Eval
noneable = true,
defaultValue = "None",
doc =
"outputs of this rule. "
+ "It is a dictionary mapping from string to a template name. "
+ "For example: <code>{\"ext\": \"%{name}.ext\"}</code>. <br>"
"A schema for defining predeclared outputs. Unlike <a href='attr.html#output'><code>"
+ "output</code></a> and <a href='attr.html#output_list'><code>output_list</code>"
+ "</a>attributes, the user does not specify the labels for these files. See the "
+ "<a href='../rules.$DOC_EXT#files'>Rules page</a> for more on predeclared "
+ "outputs."
+ "<p>The value of this argument is a dictionary. Each entry creates a predeclared "
+ "output where the key is an identifier and the value helps determine the "
+ "output's label. In the rule's implementation function, the identifier becomes "
+ "the field name used to access the output's <a href='File.html'><code>File</code>"
+ "</a> in <a href='ctx.html#outputs'><code>ctx.outputs</code></a>."
+ "<p>The output's label has the same package as the rule, and the part after the "
+ "package is determined by the dict entry's value. If this value is a string, "
+ "then it is interpreted as a template, where substitution placeholders of the "
+ "form <code>\"%{ATTR}\"</code> are replaced by the value of the string attribute "
+ "named <code>ATTR</code>. (For this purpose, the rule's <code>name</code> is "
+ "also considered an attribute.) For example, the outputs dict "
+ "<code>{\"bin\": \"%{name}.exe\"} predeclares an output with"
+ "</code>. <br>"
+ "The dictionary key becomes an attribute in <code>ctx.outputs</code>. "
+ "Similar to computed dependency rule attributes, you can also specify the "
+ "name of a function that returns the dictionary. This function can access "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,23 +161,32 @@ public final class SkylarkRuleContext implements SkylarkValue {
+ "attr struct, but their values will be single lists with all the branches of the split "
+ "merged together.";
public static final String OUTPUTS_DOC =
"A pseudo-struct containing all the pre-declared output files."
+ " It is generated the following way:<br>"
+ "<ul>" + ""
+ "<li>For every entry in the rule's <code>outputs</code> dict an attr is generated with "
+ "the same name and the corresponding <code>file</code> value."
+ "<li>For every output type attribute a struct attribute is generated with the "
+ "same name and the corresponding <code>file</code> value or <code>None</code>, "
+ "if no value is specified in the rule."
+ "<li>For every output list type attribute a struct attribute is generated with the "
+ "same name and corresponding <code>list</code> of <code>file</code>s value "
+ "(an empty list if no value is specified in the rule).</li>"
+ "<li>DEPRECATED: If the rule is marked as <code>executable=True</code>, a field "
+ "\"executable\" can be accessed. That will declare the rule's default executable "
+ "<code>File</code> value. The recommended alternative is to declare an executable with "
+ "<a href=\"actions.html#declare_file\"><code>ctx.actions.declare_file</code></a> "
+ "and return it as the <code>executable</code> field of the rule's "
+ "<a href=\"globals.html#DefaultInfo\"><code>DefaultInfo</code></a> provider."
"A pseudo-struct containing all the predeclared output files, represented by "
+ "<a href='File.html'><code>File</code></a> objects. See the "
+ "<a href='../rules.$DOC_EXT#files'>Rules page</a> for more information and examples."
+ "<p>This field does not exist on aspect contexts, since aspects do not have "
+ "predeclared outputs."
+ "<p>The fields of this object are defined as follows. It is an error if two outputs "
+ "produce the same field name or have the same label."
+ "<ul>"
+ "<li>If the rule declares an <a href='globals.html#rule.outputs'><code>outputs</code>"
+ "</a> dict, then for every entry in the dict, there is a field whose name is the key "
+ "and whose value is the corresponding <code>File</code>."
+ "<li>For every attribute of type <a href='attr.html#output'><code>attr.output</code>"
+ "</a> that the rule declares, there is a field whose name is the attribute's name. "
+ "If the target specified a label for that attribute, then the field value is the "
+ "corresponding <code>File</code>; otherwise the field value is <code>None</code>."
+ "<li>For every attribute of type <a href='attr.html#output_list'><code>attr.output_list"
+ "</code></a> that the rule declares, there is a field whose name is the attribute's "
+ "name. The field value is a list of <code>File</code> objects corresponding to the "
+ "labels given for that attribute in the target, or an empty list if the attribute was "
+ "not specified in the target."
+ "<li><b>(Deprecated)</b> If the rule is marked <a href='globals.html#rule.executable'>"
+ "<code>executable</code></a> or <a href='globals.html#rule.test'><code>test</code></a>,"
+ "there is a field named <code>\"executable\"</code>, which is the default executable. "
+ "It is recommended that instead of using this, you pass another file (either "
+ "predeclared or not) to the <code>executable</code> arg of "
+ "<a href='globals.html#DefaultInfo'><code>DefaultInfo</code></a>."
+ "</ul>";
public static final Function<Attribute, Object> ATTRIBUTE_VALUE_EXTRACTOR_FOR_ASPECT =
new Function<Attribute, Object>() {
Expand Down

0 comments on commit 864ac52

Please sign in to comment.