| // 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.auto.value.AutoValue; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.eventbus.SubscriberExceptionHandler; |
| import com.google.devtools.build.lib.analysis.AnalysisResult; |
| 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.ConfiguredTarget; |
| import com.google.devtools.build.lib.analysis.ServerDirectories; |
| import com.google.devtools.build.lib.analysis.ViewCreationFailedException; |
| 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.exec.ModuleActionContextRegistry; |
| import com.google.devtools.build.lib.exec.SpawnStrategyRegistry; |
| import com.google.devtools.build.lib.packages.Package.Builder.PackageSettings; |
| import com.google.devtools.build.lib.packages.PackageLoadingListener; |
| import com.google.devtools.build.lib.packages.PackageOverheadEstimator; |
| import com.google.devtools.build.lib.packages.PackageValidator; |
| import com.google.devtools.build.lib.skyframe.PrecomputedValue; |
| import com.google.devtools.build.lib.util.AbruptExitException; |
| import com.google.devtools.build.lib.util.DetailedExitCode; |
| 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.build.lib.vfs.PathFragment; |
| import com.google.devtools.common.options.OptionsBase; |
| import com.google.devtools.common.options.OptionsParsingResult; |
| import com.google.devtools.common.options.OptionsProvider; |
| 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(OptionsParsingResult 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 |
| * @param realExecRootBase absolute path fragment of the actual, underlying execution root |
| */ |
| public ModuleFileSystem getFileSystem( |
| OptionsParsingResult startupOptions, PathFragment realExecRootBase) |
| throws AbruptExitException { |
| return null; |
| } |
| |
| @Nullable |
| public FileSystem getFileSystemForBuildArtifacts(FileSystem fileSystem) { |
| return null; |
| } |
| |
| /** Tuple returned by {@link #getFileSystem}. */ |
| @AutoValue |
| public abstract static class ModuleFileSystem { |
| public abstract FileSystem fileSystem(); |
| |
| /** Non-null if this filesystem virtualizes the execroot folder. */ |
| @Nullable |
| abstract Path virtualExecRootBase(); |
| |
| public static ModuleFileSystem create( |
| FileSystem fileSystem, @Nullable Path virtualExecRootBase) { |
| return new AutoValue_BlazeModule_ModuleFileSystem(fileSystem, virtualExecRootBase); |
| } |
| |
| public static ModuleFileSystem create(FileSystem fileSystem) { |
| return create(fileSystem, /*virtualExecRootBase=*/ null); |
| } |
| } |
| |
| /** |
| * Returns handler for {@link com.google.common.eventbus.EventBus} subscriber and async thread |
| * exceptions. For async thread exceptions, {@link |
| * SubscriberExceptionHandler#handleException(Throwable, |
| * com.google.common.eventbus.SubscriberExceptionContext)} will be called with null {@link |
| * com.google.common.eventbus.SubscriberExceptionContext}. If all modules return null, a handler |
| * that crashes on all async exceptions and files bug reports for all EventBus subscriber |
| * exceptions will be used. |
| */ |
| public SubscriberExceptionHandler getEventBusAndAsyncExceptionHandler() { |
| 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 directories the install directory |
| * @throws AbruptExitException to shut down the server immediately |
| */ |
| public void blazeStartup( |
| OptionsParsingResult 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(OptionsParsingResult 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 |
| * OptionsParsingResult}. |
| * |
| * @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(); |
| } |
| |
| /** |
| * Called after Bazel analyzes the build's top-level targets. This is called once per build if |
| * --analyze is enabled. Modules can override this to perform extra checks on analysis results. |
| * |
| * @param env the command environment |
| * @param request the build request |
| * @param buildOptions the build's top-level options |
| * @param analysisResult the build's analysis result |
| */ |
| public void afterAnalysis( |
| CommandEnvironment env, |
| BuildRequest request, |
| BuildOptions buildOptions, |
| AnalysisResult analysisResult) |
| throws InterruptedException, ViewCreationFailedException {} |
| |
| /** |
| * Called after Bazel analyzes a single top-level target. |
| * |
| * @param env the command environment |
| * @param request the build request |
| * @param buildOptions the build's top-level options |
| * @param configuredTarget the analyzed top-level target |
| */ |
| public void afterTopLevelTargetAnalysis( |
| CommandEnvironment env, |
| BuildRequest request, |
| BuildOptions buildOptions, |
| ConfiguredTarget configuredTarget) |
| throws InterruptedException, ViewCreationFailedException {} |
| |
| /** |
| * 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 AbruptExitException {} |
| |
| /** |
| * Registers any action contexts this module provides with the execution phase. They will be |
| * available for {@linkplain |
| * com.google.devtools.build.lib.actions.ActionContext.ActionContextRegistry#getContext querying} |
| * to actions and other action contexts. |
| * |
| * <p>This method is invoked before actions are executed but after {@link #executorInit}. |
| * |
| * @param registryBuilder builder with which to register action contexts |
| * @param env environment for the current command |
| * @param buildRequest the current build request |
| * @throws AbruptExitException if there are fatal issues creating or registering action contexts |
| */ |
| public void registerActionContexts( |
| ModuleActionContextRegistry.Builder registryBuilder, |
| CommandEnvironment env, |
| BuildRequest buildRequest) |
| throws AbruptExitException {} |
| |
| /** |
| * Registers any spawn strategies this module provides with the execution phase. |
| * |
| * <p>This method is invoked before actions are executed but after {@link #executorInit}. |
| * |
| * @param registryBuilder builder with which to register strategies |
| * @param env environment for the current command |
| * @throws AbruptExitException if there are fatal issues creating or registering strategies |
| */ |
| public void registerSpawnStrategies( |
| SpawnStrategyRegistry.Builder registryBuilder, CommandEnvironment env) |
| throws AbruptExitException, InterruptedException {} |
| |
| /** |
| * Called after each command. |
| * |
| * @throws AbruptExitException modules can throw this exception to modify the command exit code |
| */ |
| public void afterCommand() throws AbruptExitException {} |
| |
| /** |
| * Called after {@link #afterCommand()}. This method can be used to close and cleanup resources |
| * specific to the command. |
| * |
| * <p>This method must not throw any exceptions, report any errors or generate any stdout/stderr. |
| * Any of the above will make Bazel crash occasionally. Please use {@link #afterCommand()} |
| * instead. |
| */ |
| public void commandComplete() {} |
| |
| /** |
| * 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(DetailedExitCode exitCode) {} |
| |
| /** |
| * Returns true if the module will arrange for a {@code BuildMetricsEvent} to be posted after the |
| * build completes. |
| * |
| * <p>The Blaze runtime ensures that it has exactly one module for which this method returns true, |
| * substituting its own module if none is supplied explicitly. |
| * |
| * <p>It is an error if multiple modules return true. |
| */ |
| public boolean postsBuildMetricsEvent() { |
| return false; |
| } |
| |
| /** |
| * Returns a {@link QueryRuntimeHelper.Factory} that will be used by the query, cquery, and aquery |
| * commands. |
| * |
| * <p>It is an error if multiple modules return non-null values. |
| */ |
| public QueryRuntimeHelper.Factory getQueryRuntimeHelperFactory() { |
| return null; |
| } |
| |
| /** |
| * Returns {@link PackageSettings} for creating packages. |
| * |
| * <p>Called once during server startup some time after {@link #serverInit}. |
| * |
| * <p>Note that only one helper per Bazel/Blaze runtime is allowed. |
| */ |
| @Nullable |
| public PackageSettings getPackageSettings() { |
| return null; |
| } |
| |
| /** |
| * Returns a {@link PackageValidator} to be used to validate loaded packages, or null if the |
| * module does not provide any validator. |
| * |
| * <p>Called once during server startup some time after {@link #serverInit}. |
| * |
| * <p>Note that only one instance per Bazel/Blaze runtime is allowed. |
| */ |
| @Nullable |
| public PackageValidator getPackageValidator() { |
| return null; |
| } |
| |
| /** |
| * Returns a {@link PackageOverheadEstimator} to be used to estimate the cost of loaded packages, |
| * or null if the module does not provide any such functionality. |
| * |
| * <p>Called once during server startup some time after {@link #serverInit}. |
| * |
| * <p>Note that only one instance per Bazel/Blaze runtime is allowed |
| */ |
| @Nullable |
| public PackageOverheadEstimator getPackageOverheadEstimator() { |
| return null; |
| } |
| |
| /** |
| * Returns a {@link PackageLoadingListener} for observing successful package loading, or null if |
| * the module does not provide any validator. |
| * |
| * <p>Called once during server startup some time after {@link #serverInit}. |
| */ |
| @Nullable |
| public PackageLoadingListener getPackageLoadingListener( |
| PackageSettings packageSettings, |
| ConfiguredRuleClassProvider ruleClassProvider, |
| FileSystem fs) { |
| return null; |
| } |
| |
| @Nullable |
| public String getSlowThreadInterruptMessageSuffix() { |
| 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(OptionsProvider 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. |
| * |
| * <p>Returns null when the package designated by the label does not exist. |
| */ |
| @Nullable |
| Path getFileFromWorkspace(Label label); |
| |
| /** Exits Blaze as early as possible by sending an interrupt to the command's main thread. */ |
| void exit(AbruptExitException exception); |
| } |
| |
| /** |
| * Provides additional precomputed values to inject into the skyframe graph. Called on every |
| * command execution. |
| */ |
| public ImmutableList<PrecomputedValue.Injected> getPrecomputedValues() { |
| return ImmutableList.of(); |
| } |
| |
| @Override |
| public String toString() { |
| return this.getClass().getSimpleName(); |
| } |
| } |