blob: 8a513508b917a114d986c36edd942b8e3b466919 [file] [log] [blame]
// 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.actions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.Artifact.ArtifactExpander;
import com.google.devtools.build.lib.analysis.platform.PlatformInfo;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import java.util.Collection;
import java.util.LinkedHashMap;
import javax.annotation.Nullable;
/**
* An Analysis phase interface for an {@link Action} or Action-like object, containing only
* side-effect-free query methods for information needed during action analysis.
*/
public interface ActionAnalysisMetadata {
/**
* Return this key from {@link #getKey} to signify a failed key computation.
*
* <p>Actions that return this value should fail to execute.
*
* <p>Consumers must either gracefully handle multiple failed actions having the same key,
* (recommended), or check against this value explicitly.
*/
String KEY_ERROR = "1ea50e01-0349-4552-80cf-76cf520e8592";
/**
* Returns the owner of this executable if this executable can supply verbose information. This is
* typically the rule that constructed it; see ActionOwner class comment for details.
*/
ActionOwner getOwner();
/**
* Returns true if the action can be shared, i.e. multiple configured targets can create the same
* action.
*
* <p>In theory, these should not exist, but in practice, they do.
*/
boolean isShareable();
/**
* Returns a mnemonic (string constant) for this kind of action; written into the master log so
* that the appropriate parser can be invoked for the output of the action. Effectively a public
* method as the value is used by the extra_action feature to match actions.
*/
String getMnemonic();
/**
* Returns a string encoding all of the significant behaviour of this Action that might affect the
* output. The general contract of <code>getKey</code> is this: if the work to be performed by the
* execution of this action changes, the key must change.
*
* <p>As a corollary, the build system is free to omit the execution of an Action <code>a1</code>
* if (a) at some time in the past, it has already executed an Action <code>a0</code> with the
* same key as <code>a1</code>, (b) the names and contents of the input files listed by <code>
* a1.getInputs()</code> are identical to the names and contents of the files listed by <code>
* a0.getInputs()</code>, and (c) the names and values in the client environment of the variables
* listed by <code>a1.getClientEnvironmentVariables()</code> are identical to those listed by
* <code>a0.getClientEnvironmentVariables()</code>.
*
* <p>Examples of changes that should affect the key are:
*
* <ul>
* <li>Changes to the BUILD file that materially affect the rule which gave rise to this Action.
* <li>Changes to the command-line options, environment, or other global configuration resources
* which affect the behaviour of this kind of Action (other than changes to the names of the
* input/output files, which are handled externally).
* <li>An upgrade to the build tools which changes the program logic of this kind of Action
* (typically this is achieved by incorporating a UUID into the key, which is changed each
* time the program logic of this action changes).
* </ul>
*
* <p>Note the following exception: for actions that discover inputs, the key must change if any
* input names change or else action validation may falsely validate.
*
* <p>In case the {@link ArtifactExpander} is not provided, the key is not guaranteed to be
* correct. In fact, getting the key of an action is generally impossible until we have all the
* information necessary to execute the action. An example of this is when arguments to an action
* are defined as a lazy evaluation of Starlark over outputs of another action, after expanding
* directories. In such case, if the dependent action outputs a tree artifact, creating a truly
* unique key will depend on knowing the tree artifact contents. At analysis time, we only know
* about the tree artifact directory and we find what is in it only after we execute that action.
*/
String getKey(ActionKeyContext actionKeyContext, @Nullable ArtifactExpander artifactExpander)
throws InterruptedException;
/**
* Returns a pretty string representation of this action, suitable for use in progress messages or
* error messages.
*/
String prettyPrint();
/** Returns a description of this action. */
String describe();
/**
* Returns the tool Artifacts that this Action depends upon. May be empty. This is a subset of
* getInputs().
*
* <p>This may be used by spawn strategies to determine whether an external tool has not changed
* since the last time it was used and could thus be reused, or whether it has to be restarted.
*
* <p>See {@link AbstractAction#getTools()} for an explanation of why it's important that this set
* contains exactly the right set of artifacts in order for the build to stay correct and the
* worker strategy to work.
*/
NestedSet<Artifact> getTools();
/**
* Returns the input Artifacts that this Action depends upon. May be empty.
*
* <p>During execution, the {@link Iterable} returned by {@code getInputs} <em>must not</em> be
* concurrently modified before the value is fully read in {@code JavaDistributorDriver#exec} (via
* the {@code Iterable<ActionInput>} argument there). Violating this would require somewhat
* pathological behavior by the {@link Action}, since it would have to modify its inputs, as a
* list, say, without reassigning them. This should never happen with any Action subclassing
* AbstractAction, since AbstractAction's implementation of getInputs() returns an immutable
* iterable.
*/
NestedSet<Artifact> getInputs();
/**
* Returns the environment variables from the client environment that this action depends on. May
* be empty.
*
* <p>Warning: For optimization reasons, the available environment variables are restricted to
* those white-listed on the command line. If actions want to specify additional client
* environment variables to depend on, that restriction must be lifted in {@link
* com.google.devtools.build.lib.runtime.CommandEnvironment}.
*/
Collection<String> getClientEnvironmentVariables();
/**
* Returns the (unordered, immutable) set of output Artifacts that this action generates. (It
* would not make sense for this to be empty.)
*/
ImmutableSet<Artifact> getOutputs();
/**
* Returns input files that need to be present to allow extra_action rules to shadow this action
* correctly when run remotely. This is at least the normal inputs of the action, but may include
* other files as well. For example C(++) compilation may perform include file header scanning.
* This needs to be mirrored by the extra_action rule. Called by {@link
* com.google.devtools.build.lib.analysis.extra.ExtraAction} at execution time for actions that
* return true for {link #discoversInputs()}.
*
* @param actionExecutionContext Services in the scope of the action, like the Out/Err streams.
* @throws ActionExecutionException only when code called from this method throws that exception.
* @throws InterruptedException if interrupted
*/
NestedSet<Artifact> getInputFilesForExtraAction(ActionExecutionContext actionExecutionContext)
throws ActionExecutionException, InterruptedException;
/**
* Returns the set of output Artifacts that are required to be saved. This is used to identify
* items that would otherwise be potentially identified as orphaned (not consumed by any
* downstream {@link Action}s and potentially discarded during the build process.
*
* <p>Do not call unless you are in the business of identifying orphaned artifacts: otherwise just
* use {@link #getOutputs}.
*/
ImmutableSet<Artifact> getMandatoryOutputs();
/**
* Returns the "primary" input of this action, if applicable.
*
* <p>For example, a C++ compile action would return the .cc file which is being compiled,
* irrespective of the other inputs.
*
* <p>May return null.
*/
Artifact getPrimaryInput();
/**
* Returns the "primary" output of this action.
*
* <p>For example, the linked library would be the primary output of a LinkAction.
*
* <p>Never returns null.
*/
Artifact getPrimaryOutput();
/**
* Returns an iterable of input Artifacts that MUST exist prior to executing an action. In other
* words, in case when action is scheduled for execution, builder will ensure that all artifacts
* returned by this method are present in the filesystem (artifact.getPath().exists() is true) or
* action execution will be aborted with an error that input file does not exist. While in
* majority of cases this method will return all action inputs, for some actions (e.g.
* CppCompileAction) it can return a subset of inputs because that not all action inputs might be
* mandatory for action execution to succeed (e.g. header files retrieved from *.d file from the
* previous build).
*/
NestedSet<Artifact> getMandatoryInputs();
/**
* Returns true iff path prefix conflict (conflict where two actions generate two output artifacts
* with one of the artifact's path being the prefix for another) between this action and another
* action should be reported.
*/
boolean shouldReportPathPrefixConflict(ActionAnalysisMetadata action);
/** Returns the action type. Must not be {@code null}. */
MiddlemanType getActionType();
/** Returns a String to String map containing the execution properties of this action. */
ImmutableMap<String, String> getExecProperties();
/**
* Returns the {@link PlatformInfo} platform this action should be executed on. If the execution
* platform is {@code null}, then the host platform is assumed.
*/
@Nullable
PlatformInfo getExecutionPlatform();
/**
* Returns the execution requirements for this action, or an empty map if the action type does not
* have access to execution requirements.
*/
default ImmutableMap<String, String> getExecutionInfo() {
return getExecProperties();
}
static ImmutableMap<String, String> mergeMaps(
ImmutableMap<String, String> first, ImmutableMap<String, String> second) {
// Use a different type to allow overriding keys.
// TODO(jcater): When ImmutableMap.Builder.buildKeepingLast is in released guava, upgrade and
// use that.
LinkedHashMap<String, String> result = new LinkedHashMap<>();
result.putAll(first);
result.putAll(second);
return ImmutableMap.copyOf(result);
}
}