aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/runtime/BlazeModule.java
blob: 5f2bb66c2248f08cbf41a9c2a83aa0994a81001d (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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
// 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.runtime;

import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.ExecutorInitException;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.BlazeVersionInfo;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.analysis.ServerDirectories;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.analysis.test.CoverageReportActionFactory;
import com.google.devtools.build.lib.buildtool.BuildRequest;
import com.google.devtools.build.lib.clock.Clock;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.exec.ExecutorBuilder;
import com.google.devtools.build.lib.packages.NoSuchThingException;
import com.google.devtools.build.lib.packages.Package;
import com.google.devtools.build.lib.packages.PackageFactory;
import com.google.devtools.build.lib.packages.RuleClassProvider;
import com.google.devtools.build.lib.skyframe.PrecomputedValue;
import com.google.devtools.build.lib.util.AbruptExitException;
import com.google.devtools.build.lib.util.io.OutErr;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.OutputService;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsClassProvider;
import com.google.devtools.common.options.OptionsProvider;
import java.io.IOException;
import java.util.UUID;
import javax.annotation.Nullable;

/**
 * A module Bazel can load at the beginning of its execution. Modules are supplied with extension
 * points to augment the functionality at specific, well-defined places.
 *
 * <p>The constructors of individual Bazel modules should be empty. All work should be done in the
 * methods (e.g. {@link #blazeStartup}).
 */
public abstract class BlazeModule {

  /**
   * Returns the extra startup options this module contributes.
   *
   * <p>This method will be called at the beginning of Blaze startup (before {@link #globalInit}).
   * The startup options need to be parsed very early in the process, which requires this to be
   * separate from {@link #serverInit}.
   */
  public Iterable<Class<? extends OptionsBase>> getStartupOptions() {
    return ImmutableList.of();
  }

  /**
   * Called at the beginning of Bazel startup, before {@link #getFileSystem} and
   * {@link #blazeStartup}.
   *
   * @param startupOptions the server's startup options
   *
   * @throws AbruptExitException to shut down the server immediately
   */
  public void globalInit(OptionsProvider startupOptions) throws AbruptExitException {
  }

  /**
   * Returns the file system implementation used by Bazel. It is an error if more than one module
   * returns a file system. If all return null, the default unix file system is used.
   *
   * <p>This method will be called at the beginning of Bazel startup (in-between {@link #globalInit}
   * and {@link #blazeStartup}).
   *
   * @param startupOptions the server's startup options
   */
  public FileSystem getFileSystem(OptionsProvider startupOptions) throws AbruptExitException {
    return null;
  }

  /**
   * Called when Bazel starts up after {@link #getStartupOptions}, {@link #globalInit}, and {@link
   * #getFileSystem}.
   *
   * @param startupOptions the server's startup options
   * @param versionInfo the Bazel version currently running
   * @param instanceId the id of the current Bazel server
   * @param fileSystem
   * @param directories the install directory
   * @param clock the clock
   * @throws AbruptExitException to shut down the server immediately
   */
  public void blazeStartup(
      OptionsProvider startupOptions,
      BlazeVersionInfo versionInfo,
      UUID instanceId,
      FileSystem fileSystem,
      ServerDirectories directories,
      Clock clock)
      throws AbruptExitException {}

  /**
   * Called to initialize a new server ({@link BlazeRuntime}). Modules can override this method to
   * affect how the server is configured. This is called after the startup options have been
   * collected and parsed, and after the file system was setup.
   *
   * @param startupOptions the server startup options
   * @param builder builder class that collects the server configuration
   *
   * @throws AbruptExitException to shut down the server immediately
   */
  public void serverInit(OptionsProvider startupOptions, ServerBuilder builder)
      throws AbruptExitException {
  }

  /**
   * Sets up the configured rule class provider, which contains the built-in rule classes, aspects,
   * configuration fragments, and other things; called during Blaze startup (after {@link
   * #blazeStartup}).
   *
   * <p>Bazel only creates one provider per server, so it is not possible to have different contents
   * for different workspaces.
   *
   * @param builder the configured rule class provider builder
   */
  public void initializeRuleClasses(ConfiguredRuleClassProvider.Builder builder) {}

  /**
   * Called when Bazel initializes a new workspace; this is only called after {@link #serverInit},
   * and only if the server initialization was successful. Modules can override this method to
   * affect how the workspace is configured.
   *
   * @param runtime the blaze runtime
   * @param directories the workspace directories
   * @param builder the workspace builder
   */
  public void workspaceInit(
      BlazeRuntime runtime, BlazeDirectories directories, WorkspaceBuilder builder) {
  }

  /**
   * Called to notify modules that the given command is about to be executed. This allows capturing
   * the {@link com.google.common.eventbus.EventBus}, {@link Command}, or {@link OptionsProvider}.
   *
   * @param env the command
   * @throws AbruptExitException modules can throw this exception to abort the command
   */
  public void beforeCommand(CommandEnvironment env) throws AbruptExitException {
  }

  /**
   * Returns additional listeners to the console output stream. Called at the beginning of each
   * command (after #beforeCommand).
   */
  @SuppressWarnings("unused")
  @Nullable
  public OutErr getOutputListener() {
    return null;
  }

  /**
   * Returns the output service to be used. It is an error if more than one module returns an
   * output service.
   *
   * <p>This method will be called at the beginning of each command (after #beforeCommand).
   */
  @SuppressWarnings("unused")
  public OutputService getOutputService() throws AbruptExitException {
    return null;
  }

  /**
   * Returns extra options this module contributes to a specific command. Note that option
   * inheritance applies: if this method returns a non-empty list, then the returned options are
   * added to every command that depends on this command.
   *
   * <p>This method may be called at any time, and the returned value may be cached. Implementations
   * must be thread-safe and never return different lists for the same command object. Typical
   * implementations look like this:
   *
   * <pre>
   * return "build".equals(command.name())
   *     ? ImmutableList.<Class<? extends OptionsBase>>of(MyOptions.class)
   *     : ImmutableList.<Class<? extends OptionsBase>>of();
   * </pre>
   *
   * Note that this example adds options to all commands that inherit from the build command.
   *
   * <p>This method is also used to generate command-line documentation; in order to avoid
   * duplicated options descriptions, this method should never return the same options class for two
   * different commands if one of them inherits the other.
   *
   * <p>If you want to add options to all commands, override {@link #getCommonCommandOptions}
   * instead.
   *
   * @param command the command
   */
  public Iterable<Class<? extends OptionsBase>> getCommandOptions(Command command) {
    return ImmutableList.of();
  }

  /**
   * Returns extra options this module contributes to all commands.
   */
  public Iterable<Class<? extends OptionsBase>> getCommonCommandOptions() {
    return ImmutableList.of();
  }

  /**
   * Returns an instance of BuildOptions to be used to create {@link
   * BuildOptions.OptionsDiffForReconstruction} with. Only one installed Module should override
   * this.
   */
  public BuildOptions getDefaultBuildOptions(BlazeRuntime runtime) {
    return null;
  }

  /**
   * Called when Bazel initializes the action execution subsystem. This is called once per build if
   * action execution is enabled. Modules can override this method to affect how execution is
   * performed.
   *
   * @param env the command environment
   * @param request the build request
   * @param builder the builder to add action context providers and consumers to
   */
  public void executorInit(CommandEnvironment env, BuildRequest request, ExecutorBuilder builder)
      throws ExecutorInitException {}

  /**
   * Called after each command.
   */
  public void afterCommand() {
  }

  /**
   * Called when Blaze shuts down.
   *
   * <p>If you are also implementing {@link #blazeShutdownOnCrash()}, consider putting the common
   * shutdown code in the latter and calling that other hook from here.
   */
  public void blazeShutdown() {
  }

  /**
   * Called when Blaze shuts down due to a crash.
   *
   * <p>Modules may use this to flush pending state, but they must be careful to only do a minimal
   * number of things. Keep in mind that we are crashing so who knows what state we are in. Modules
   * rarely need to implement this.
   */
  public void blazeShutdownOnCrash() {}

  /**
   * Returns a helper that the {@link PackageFactory} will use during package loading. If the module
   * does not provide any helper, it should return null. Note that only one helper per Bazel/Blaze
   * runtime is allowed.
   */
  public Package.Builder.Helper getPackageBuilderHelper(RuleClassProvider ruleClassProvider) {
    return null;
  }

  /**
   * Optionally returns a provider for project files that can be used to bundle targets and
   * command-line options.
   */
  @Nullable
  public ProjectFile.Provider createProjectFileProvider() {
    return null;
  }

  /**
   * Optionally returns a factory to create coverage report actions; this is called once per build,
   * such that it can be affected by command options.
   *
   * <p>It is an error if multiple modules return non-null values.
   *
   * @param commandOptions the options for the current command
   */
  @Nullable
  public CoverageReportActionFactory getCoverageReportFactory(OptionsClassProvider commandOptions) {
    return null;
  }

  /**
   * Services provided for Blaze modules via BlazeRuntime.
   */
  public interface ModuleEnvironment {
    /**
     * Gets a file from the depot based on its label and returns the {@link Path} where it can
     * be found.
     */
    Path getFileFromWorkspace(Label label)
        throws NoSuchThingException, InterruptedException, IOException;

    /**
     * Exits Blaze as early as possible by sending an interrupt to the command's main thread.
     */
    void exit(AbruptExitException exception);
  }

  public ImmutableList<PrecomputedValue.Injected> getPrecomputedValues() {
    return ImmutableList.of();
  }

  @Override
  public String toString() {
    return this.getClass().getSimpleName();
  }
}