aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/analysis/extra/ExtraAction.java
diff options
context:
space:
mode:
authorGravatar ulfjack <ulfjack@google.com>2017-08-10 12:29:25 +0200
committerGravatar Marcel Hlopko <hlopko@google.com>2017-08-10 13:48:24 +0200
commit9220eec3c8359907284edd78191467b6df7ae4d0 (patch)
tree708e5137e89439b413b516cd2d6aea4cb3158a09 /src/main/java/com/google/devtools/build/lib/analysis/extra/ExtraAction.java
parent3a5002f119fe1d37d897445f21f3ad650caf83c6 (diff)
Move extra action stuff to analysis.extra
This is part of splitting up the build-base library into separate libraries for analysis, exec, and rules. PiperOrigin-RevId: 164835678
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/analysis/extra/ExtraAction.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/extra/ExtraAction.java182
1 files changed, 182 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/extra/ExtraAction.java b/src/main/java/com/google/devtools/build/lib/analysis/extra/ExtraAction.java
new file mode 100644
index 0000000000..8c4d14aa79
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/analysis/extra/ExtraAction.java
@@ -0,0 +1,182 @@
+// 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.analysis.extra;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import com.google.devtools.build.lib.actions.AbstractAction;
+import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionEnvironment;
+import com.google.devtools.build.lib.actions.ActionExecutionContext;
+import com.google.devtools.build.lib.actions.ActionExecutionException;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CompositeRunfilesSupplier;
+import com.google.devtools.build.lib.actions.RunfilesSupplier;
+import com.google.devtools.build.lib.actions.SpawnActionContext;
+import com.google.devtools.build.lib.analysis.actions.CommandLine;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.collect.nestedset.Order;
+import com.google.devtools.build.lib.util.Preconditions;
+import com.google.devtools.build.lib.vfs.FileSystemUtils;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+import javax.annotation.Nullable;
+
+/**
+ * Action used by extra_action rules to create an action that shadows an existing action. Runs a
+ * command-line using {@link SpawnActionContext} for executions.
+ */
+public final class ExtraAction extends SpawnAction {
+ private final Action shadowedAction;
+ private final boolean createDummyOutput;
+ private final ImmutableSet<Artifact> extraActionInputs;
+
+ /**
+ * A long way to say (ExtraAction xa) -> xa.getShadowedAction().
+ */
+ public static final Function<ExtraAction, Action> GET_SHADOWED_ACTION =
+ new Function<ExtraAction, Action>() {
+ @Nullable
+ @Override
+ public Action apply(@Nullable ExtraAction extraAction) {
+ return extraAction != null ? extraAction.getShadowedAction() : null;
+ }
+ };
+
+ ExtraAction(
+ ImmutableSet<Artifact> extraActionInputs,
+ RunfilesSupplier runfilesSupplier,
+ Collection<Artifact> outputs,
+ Action shadowedAction,
+ boolean createDummyOutput,
+ CommandLine argv,
+ ActionEnvironment env,
+ Map<String, String> executionInfo,
+ CharSequence progressMessage,
+ String mnemonic) {
+ super(
+ shadowedAction.getOwner(),
+ ImmutableList.<Artifact>of(),
+ createInputs(shadowedAction.getInputs(), ImmutableList.<Artifact>of(), extraActionInputs),
+ outputs,
+ AbstractAction.DEFAULT_RESOURCE_SET,
+ argv,
+ false,
+ env,
+ ImmutableMap.copyOf(executionInfo),
+ progressMessage,
+ new CompositeRunfilesSupplier(shadowedAction.getRunfilesSupplier(), runfilesSupplier),
+ mnemonic,
+ false,
+ null);
+ this.shadowedAction = shadowedAction;
+ this.createDummyOutput = createDummyOutput;
+
+ this.extraActionInputs = extraActionInputs;
+ if (createDummyOutput) {
+ // Expecting just a single dummy file in the outputs.
+ Preconditions.checkArgument(outputs.size() == 1, outputs);
+ }
+ }
+
+ @Override
+ public boolean discoversInputs() {
+ return shadowedAction.discoversInputs();
+ }
+
+ @Nullable
+ @Override
+ public Iterable<Artifact> discoverInputs(ActionExecutionContext actionExecutionContext)
+ throws ActionExecutionException, InterruptedException {
+ Preconditions.checkState(discoversInputs(), this);
+ // We depend on the outputs of actions doing input discovery and they should know their inputs
+ // after having been executed
+ Preconditions.checkState(shadowedAction.inputsDiscovered());
+
+ // We need to update our inputs to take account of any additional
+ // inputs the shadowed action may need to do its work.
+ Iterable<Artifact> oldInputs = getInputs();
+ updateInputs(
+ createInputs(
+ shadowedAction.getInputs(),
+ shadowedAction.getInputFilesForExtraAction(actionExecutionContext),
+ extraActionInputs));
+ return Sets.<Artifact>difference(
+ ImmutableSet.<Artifact>copyOf(getInputs()), ImmutableSet.<Artifact>copyOf(oldInputs));
+ }
+
+ private static NestedSet<Artifact> createInputs(
+ Iterable<Artifact> shadowedActionInputs,
+ Iterable<Artifact> inputFilesForExtraAction,
+ ImmutableSet<Artifact> extraActionInputs) {
+ NestedSetBuilder<Artifact> result = new NestedSetBuilder<>(Order.STABLE_ORDER);
+ for (Iterable<Artifact> inputSet : ImmutableList.of(
+ shadowedActionInputs, inputFilesForExtraAction)) {
+ if (inputSet instanceof NestedSet) {
+ result.addTransitive((NestedSet<Artifact>) inputSet);
+ } else {
+ result.addAll(inputSet);
+ }
+ }
+ return result.addAll(extraActionInputs).build();
+ }
+
+ @Override
+ public Iterable<Artifact> getAllowedDerivedInputs() {
+ return shadowedAction.getAllowedDerivedInputs();
+ }
+
+ /**
+ * @InheritDoc
+ *
+ * This method calls in to {@link AbstractAction#getInputFilesForExtraAction} and
+ * {@link Action#getExtraActionInfo} of the action being shadowed from the thread executing this
+ * ExtraAction. It assumes these methods are safe to call from a different thread than the thread
+ * responsible for the execution of the action being shadowed.
+ */
+ @Override
+ public void execute(ActionExecutionContext actionExecutionContext)
+ throws ActionExecutionException, InterruptedException {
+ // PHASE 2: execution of extra_action.
+
+ super.execute(actionExecutionContext);
+
+ // PHASE 3: create dummy output.
+ // If the user didn't specify output, we need to create dummy output
+ // to make blaze schedule this action.
+ if (createDummyOutput) {
+ for (Artifact output : getOutputs()) {
+ try {
+ FileSystemUtils.touchFile(output.getPath());
+ } catch (IOException e) {
+ throw new ActionExecutionException(e.getMessage(), e, this, false);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the action this extra action is 'shadowing'.
+ */
+ public Action getShadowedAction() {
+ return shadowedAction;
+ }
+}