aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/bazel/rules/common/BazelExtraActionRule.java
blob: 35fb4e0b80bab5e529808dba3d35a985c702595b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.bazel.rules.common;

import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition.HOST;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
import static com.google.devtools.build.lib.syntax.Type.BOOLEAN;
import static com.google.devtools.build.lib.syntax.Type.STRING;
import static com.google.devtools.build.lib.syntax.Type.STRING_LIST;

import com.google.devtools.build.lib.analysis.BaseRuleClasses;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleClass.Builder;
import com.google.devtools.build.lib.rules.extra.ExtraActionFactory;

/**
 * Rule definition for extra_action rule.
 */
public final class BazelExtraActionRule implements RuleDefinition {
  @Override
  public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
    /*<!-- #BLAZE_RULE(extra_action).NAME -->
    You may refer to this rule by <code>label</code> in the <code>extra_actions</code> argument
    of <a href="#action_listener"><code> action_listener</code></a> rules.
    <!-- #END_BLAZE_RULE.NAME -->*/
    return builder
        /*<!-- #BLAZE_RULE(extra_action).ATTRIBUTE(tools) -->
        A list of <code>tool</code> dependencies for this rule.
        ${SYNOPSIS}
        <p>
          See the definition of <a href="build-ref.html#deps">dependencies</a> for more information.
        </p>
        <p>
          The build system ensures these prerequisites are built before running the
          <code>extra_action</code> command; they are built using the
          <a href='bazel-user-manual.html#configurations'><code>host</code>configuration</a>, since
          they must run as a tool during the build itself. The path of an individual
          <code>tools</code> target <code>//x:y</code> can be obtained using
          <code>$(location //x:y)</code>.
        </p>
        <p>
          All tools and their data dependencies are consolidated into a single tree
          within which the command can use relative paths. The working directory will
          be the root of that unified tree.
        </p>
        <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
        .add(attr("tools", LABEL_LIST).cfg(HOST).allowedFileTypes().exec())
        /*<!-- #BLAZE_RULE(extra_action).ATTRIBUTE(out_templates) -->
         A list of templates for files generated by the <code>extra_action</code> command.
         ${SYNOPSIS}
         <p>
           The template can use the following variables:
           <ul>
             <li>
               $(ACTION_ID), an id uniquely identifying this <code>extra_action</code>.
               Used to generate a unique output file.
             </li>
           </ul>
         </p>
         <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
        .add(attr("out_templates", STRING_LIST))
        /*<!-- #BLAZE_RULE(extra_action).ATTRIBUTE(cmd) -->
         The command to run.
         ${SYNOPSIS}
         <p>
           Like <a href="#genrule.cmd">genrule cmd attribute</a> with the following differences:
         </p>
         <ol>
           <li>
             <p>
               No heuristic label expansion. Only labels using $(location ...) are expanded.
             </p>
           </li>
           <li>
             <p>
               An additional pass is applied to the string to replace all
               occurrences of the outputs created from the <code>out_templates</code>
               attribute. All occurrences of <code>$(output <i>out_template</i>)</code>
               are replaced with the path to the file denoted by <code>label</code>.
             </p>
             <p>
               E.g. out_template <code>$(ACTION_ID).analysis</code>
               can be matched with <code>$(output $(ACTION_ID).analysis)</code>.
             </p>
             <p>
               In effect, this is the same substitution as <code>$(location)</code>
               but with a different scope.
             </p>
           </li>
         </ol>
         <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
        .add(attr("cmd", STRING).mandatory())
        /*<!-- #BLAZE_RULE(extra_action).ATTRIBUTE(requires_action_output) -->
         Indicates this <code>extra_action</code> requires the output of the
         original action to be present as input to this <code>extra_action</code>.
         ${SYNOPSIS}
         <p>
           When true (default false), the extra_action can assume that the
           original action outputs are available as part of its inputs.
         </p>
         <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
        .add(attr("requires_action_output", BOOLEAN))
        .removeAttribute("deps")
        .removeAttribute(":action_listener")
        .build();
  }

  @Override
  public Metadata getMetadata() {
    return RuleDefinition.Metadata.builder()
        .name("extra_action")
        .ancestors(BaseRuleClasses.RuleBase.class)
        .factoryClass(ExtraActionFactory.class)
        .build();
  }
}

/*<!-- #BLAZE_RULE (NAME = extra_action, TYPE = LIBRARY, FAMILY = Extra Actions)[GENERIC_RULE] -->

${ATTRIBUTE_SIGNATURE}

<p>
  An <code>extra_action</code> rule doesn't produce any meaningful output
  when specified as a regular build target. Instead, it allows tool developers
  to insert additional actions into the build graph that shadow existing actions.
</p>

<p>
  See <a href="#action_listener"><code>action_listener</code></a> for details
  on how to enable <code>extra_action</code>s in Bazel.
</p>

<p>
  The <code>extra_action</code>s run as a command-line. The command-line tool gets
  access to a file containing a protocol buffer as $(EXTRA_ACTION_FILE)
  with detailed information on the original action it is shadowing.
  It also has access to all the input files the original action has access to.
</p>

${ATTRIBUTE_DEFINITION}

<!-- #END_BLAZE_RULE -->*/