aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar twerth <twerth@google.com>2018-02-22 04:25:09 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2018-02-22 04:27:06 -0800
commit1d8ad1a1394926dcc8a2edd43ea554656e907c5a (patch)
tree871ddeb18a0e8f50103d28ae3b263a506721f998 /src
parentdaf78cc149c135514e557485007fffb058bd94f2 (diff)
Add option to dump the action graph.
Note that this dumps the current state in skyframe (which may contain more nodes than you're interested in): - bazel build --nobuild //interesting:targets - bazel dump --action_graph=/path/to/file - printproto --proto2 --raw_protocol_buffer --message=action_graph.ActionGraphContainer --multiline --proto=third_party/bazel/src/main/protobuf/action_graph.proto /path/to/file We'll add filtering options in a later CL. RELNOTES[NEW]: Add option to dump the action graph to a file: 'bazel dump --action_graph=/path/to/file'. PiperOrigin-RevId: 186597930
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/google/devtools/build/lib/BUILD2
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/AbstractConfiguredTarget.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/RuleConfiguredTarget.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/DumpCommand.java33
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutor.java253
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java3
-rw-r--r--src/main/protobuf/BUILD1
-rw-r--r--src/main/protobuf/action_graph.proto157
8 files changed, 451 insertions, 2 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD
index a72df83bb3..8bbea92b50 100644
--- a/src/main/java/com/google/devtools/build/lib/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/BUILD
@@ -529,6 +529,7 @@ java_library(
"//src/main/java/com/google/devtools/build/skyframe:skyframe-objects",
"//src/main/java/com/google/devtools/common/options",
"//src/main/java/com/google/devtools/common/options:invocation_policy",
+ "//src/main/protobuf:action_graph_java_proto",
"//src/main/protobuf:extra_actions_base_java_proto",
"//src/main/protobuf:invocation_policy_java_proto",
"//src/main/protobuf:test_status_java_proto",
@@ -1166,6 +1167,7 @@ java_library(
"//src/main/java/com/google/devtools/common/options",
"//src/main/java/com/google/devtools/common/options:invocation_policy",
"//src/main/protobuf:action_cache_java_proto",
+ "//src/main/protobuf:action_graph_java_proto",
"//src/main/protobuf:bazel_flags_java_proto",
"//src/main/protobuf:build_java_proto",
"//src/main/protobuf:command_line_java_proto",
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/AbstractConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/AbstractConfiguredTarget.java
index 395a83f316..ebd03bc811 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/AbstractConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/AbstractConfiguredTarget.java
@@ -195,7 +195,7 @@ public abstract class AbstractConfiguredTarget
@Nullable
protected abstract Info rawGetSkylarkProvider(Provider.Key providerKey);
- protected String getRuleClassString() {
+ public String getRuleClassString() {
return "";
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/RuleConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/RuleConfiguredTarget.java
index 89881c4d6c..dda8df5f19 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/RuleConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/RuleConfiguredTarget.java
@@ -131,7 +131,7 @@ public final class RuleConfiguredTarget extends AbstractConfiguredTarget {
}
@Override
- protected String getRuleClassString() {
+ public String getRuleClassString() {
return ruleClassString;
}
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/DumpCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/DumpCommand.java
index 87cddd7d3b..4fb164b2ef 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/DumpCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/DumpCommand.java
@@ -16,6 +16,7 @@ package com.google.devtools.build.lib.runtime.commands;
import static java.util.stream.Collectors.toList;
+import com.google.devtools.build.lib.actions.ActionGraphProtos.ActionGraphContainer;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.packages.Attribute;
@@ -40,6 +41,7 @@ import com.google.devtools.common.options.OptionEffectTag;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsProvider;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
@@ -102,6 +104,16 @@ public class DumpCommand implements BlazeCommand {
public boolean dumpActionCache;
@Option(
+ name = "action_graph",
+ defaultValue = "null",
+ category = "verbosity",
+ documentationCategory = OptionDocumentationCategory.OUTPUT_SELECTION,
+ effectTags = {OptionEffectTag.BAZEL_MONITORING},
+ help = "Dump action graph to the specified path."
+ )
+ public String dumpActionGraph;
+
+ @Option(
name = "rule_classes",
defaultValue = "false",
category = "verbosity",
@@ -175,6 +187,7 @@ public class DumpCommand implements BlazeCommand {
dumpOptions.dumpPackages
|| dumpOptions.dumpVfs
|| dumpOptions.dumpActionCache
+ || dumpOptions.dumpActionGraph != null
|| dumpOptions.dumpRuleClasses
|| dumpOptions.dumpRules
|| dumpOptions.skylarkMemory != null
@@ -217,6 +230,16 @@ public class DumpCommand implements BlazeCommand {
out.println();
}
+ if (dumpOptions.dumpActionGraph != null) {
+ try {
+ success &= dumpActionGraph(env.getSkyframeExecutor(), dumpOptions.dumpActionGraph, out);
+ } catch (IOException e) {
+ env.getReporter()
+ .error(
+ null, "Could not dump action graph to '" + dumpOptions.dumpActionGraph + "'", e);
+ }
+ }
+
if (dumpOptions.dumpRuleClasses) {
dumpRuleClasses(runtime, out);
out.println();
@@ -260,6 +283,16 @@ public class DumpCommand implements BlazeCommand {
return true;
}
+ private boolean dumpActionGraph(SkyframeExecutor executor, String path, PrintStream out)
+ throws IOException {
+ out.println("Dumping action graph to '" + path + "'");
+ ActionGraphContainer actionGraphContainer = executor.getActionGraphContainer();
+ FileOutputStream protoOutputStream = new FileOutputStream(path);
+ actionGraphContainer.writeTo(protoOutputStream);
+ protoOutputStream.close();
+ return true;
+ }
+
private boolean dumpSkyframe(SkyframeExecutor executor, boolean summarize, PrintStream out) {
executor.dump(summarize, out);
return true;
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutor.java
index 3f271b30c8..de51557e25 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutor.java
@@ -27,20 +27,35 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Range;
import com.google.common.collect.Sets;
+import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
+import com.google.devtools.build.lib.actions.ActionExecutionMetadata;
+import com.google.devtools.build.lib.actions.ActionGraphProtos;
+import com.google.devtools.build.lib.actions.ActionGraphProtos.ActionGraphContainer;
import com.google.devtools.build.lib.actions.ActionKeyContext;
+import com.google.devtools.build.lib.actions.ActionOwner;
+import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.BuildView;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.WorkspaceStatusAction.Factory;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoFactory;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
import com.google.devtools.build.lib.buildtool.BuildRequestOptions;
+import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+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.NestedSetView;
+import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.concurrent.Uninterruptibles;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.packages.AspectClass;
+import com.google.devtools.build.lib.packages.AspectDescriptor;
import com.google.devtools.build.lib.packages.BuildFileName;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.packages.NoSuchTargetException;
@@ -52,6 +67,7 @@ import com.google.devtools.build.lib.packages.SkylarkSemanticsOptions;
import com.google.devtools.build.lib.pkgcache.PackageCacheOptions;
import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
import com.google.devtools.build.lib.profiler.AutoProfiler;
+import com.google.devtools.build.lib.skyframe.AspectValue.AspectKey;
import com.google.devtools.build.lib.skyframe.DirtinessCheckerUtils.BasicFilesystemDirtinessChecker;
import com.google.devtools.build.lib.skyframe.DirtinessCheckerUtils.ExternalDirtinessChecker;
import com.google.devtools.build.lib.skyframe.DirtinessCheckerUtils.MissingDiffDirtinessChecker;
@@ -96,6 +112,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
@@ -760,6 +777,242 @@ public final class SequencedSkyframeExecutor extends SkyframeExecutor {
return new ArrayList<>(ruleStats.values());
}
+ private static class ActionGraphIdCache {
+ private final Map<Artifact, String> knownArtifacts = new HashMap<>();
+ private final Map<BuildConfiguration, String> knownConfigurations = new HashMap<>();
+ private final Map<Label, String> knownTargets = new HashMap<>();
+ private final Map<AspectDescriptor, String> knownAspectDescriptors = new HashMap<>();
+ private final Map<String, String> knownRuleClassStrings = new HashMap<>();
+ // The NestedSet is identified by their raw 'children' object since multiple NestedSetViews
+ // can point to the same object.
+ private final Map<Object, String> knownNestedSets = new HashMap<>();
+
+ private final ActionGraphContainer.Builder actionGraphBuilder;
+ private final ActionKeyContext actionKeyContext = new ActionKeyContext();
+
+ ActionGraphIdCache(ActionGraphContainer.Builder actionGraphBuilder) {
+ this.actionGraphBuilder = actionGraphBuilder;
+ }
+
+ public ActionKeyContext getActionKeyContext() {
+ return actionKeyContext;
+ }
+
+ public String ruleClassStringToId(String ruleClassString) {
+ if (!knownRuleClassStrings.containsKey(ruleClassString)) {
+ String targetId = String.valueOf(knownRuleClassStrings.size());
+ knownRuleClassStrings.put(ruleClassString, targetId);
+ ActionGraphProtos.RuleClass.Builder ruleClassBuilder =
+ ActionGraphProtos.RuleClass.newBuilder().setId(targetId).setName(ruleClassString);
+ actionGraphBuilder.addRuleClasses(ruleClassBuilder.build());
+ }
+ return knownRuleClassStrings.get(ruleClassString);
+ }
+
+ public String targetToId(Label label, String ruleClassString) {
+ if (!knownTargets.containsKey(label)) {
+ String targetId = String.valueOf(knownTargets.size());
+ knownTargets.put(label, targetId);
+ ActionGraphProtos.Target.Builder targetBuilder = ActionGraphProtos.Target.newBuilder();
+ targetBuilder.setId(targetId).setLabel(label.toString());
+ if (ruleClassString != null) {
+ targetBuilder.setRuleClassId(ruleClassStringToId(ruleClassString));
+ }
+ actionGraphBuilder.addTargets(targetBuilder.build());
+ }
+ return knownTargets.get(label);
+ }
+
+ public String configurationToId(BuildConfiguration buildConfiguration) {
+ if (!knownConfigurations.containsKey(buildConfiguration)) {
+ String configurationId = String.valueOf(knownConfigurations.size());
+ knownConfigurations.put(buildConfiguration, configurationId);
+ ActionGraphProtos.Configuration configurationProto =
+ ActionGraphProtos.Configuration.newBuilder()
+ .setMnemonic(buildConfiguration.getMnemonic())
+ .setPlatformName(buildConfiguration.getPlatformName())
+ .setId(configurationId)
+ .build();
+ actionGraphBuilder.addConfiguration(configurationProto);
+ }
+ return knownConfigurations.get(buildConfiguration);
+ }
+
+ public String artifactToId(Artifact artifact) {
+ if (!knownArtifacts.containsKey(artifact)) {
+ String artifactId = String.valueOf(knownArtifacts.size());
+ knownArtifacts.put(artifact, artifactId);
+ ActionGraphProtos.Artifact artifactProto =
+ ActionGraphProtos.Artifact.newBuilder()
+ .setId(artifactId)
+ .setExecPath(artifact.getExecPathString())
+ .setIsTreeArtifact(artifact.isTreeArtifact())
+ .build();
+ actionGraphBuilder.addArtifacts(artifactProto);
+ }
+ return knownArtifacts.get(artifact);
+ }
+
+ public String depSetToId(NestedSetView<Artifact> nestedSetView) {
+ if (!knownNestedSets.containsKey(nestedSetView.identifier())) {
+ String nestedSetId = String.valueOf(knownNestedSets.size());
+ knownNestedSets.put(nestedSetView.identifier(), nestedSetId);
+ ActionGraphProtos.DepSetOfFiles.Builder depSetBuilder =
+ ActionGraphProtos.DepSetOfFiles.newBuilder()
+ .setId(nestedSetId);
+ for (NestedSetView<Artifact> transitiveNestedSet : nestedSetView.transitives()) {
+ depSetBuilder.addTransitiveDepSetIds(depSetToId(transitiveNestedSet));
+ }
+ for (Artifact directArtifact : nestedSetView.directs()) {
+ depSetBuilder.addDirectArtifactIds(artifactToId(directArtifact));
+ }
+ actionGraphBuilder.addDepSetOfFiles(depSetBuilder.build());
+ }
+ return knownNestedSets.get(nestedSetView.identifier());
+ }
+
+ public String aspectDescriptorToId(AspectDescriptor aspectDescriptor) {
+ if (!knownAspectDescriptors.containsKey(aspectDescriptor)) {
+ String aspectDescriptorId = String.valueOf(knownAspectDescriptors.size());
+ knownAspectDescriptors.put(aspectDescriptor, aspectDescriptorId);
+ ActionGraphProtos.AspectDescriptor.Builder aspectDescriptorBuilder =
+ ActionGraphProtos.AspectDescriptor.newBuilder()
+ .setId(aspectDescriptorId)
+ .setName(aspectDescriptor.getAspectClass().getName());
+ for (Entry<String, String> parameter :
+ aspectDescriptor.getParameters().getAttributes().entries()) {
+ ActionGraphProtos.KeyValuePair.Builder keyValuePairBuilder =
+ ActionGraphProtos.KeyValuePair.newBuilder();
+ keyValuePairBuilder
+ .setKey(parameter.getKey())
+ .setValue(parameter.getValue());
+ aspectDescriptorBuilder.addParameters(keyValuePairBuilder.build());
+ }
+ actionGraphBuilder.addAspectDescriptors(aspectDescriptorBuilder.build());
+ }
+ return knownAspectDescriptors.get(aspectDescriptor);
+ }
+ }
+
+ @Override
+ public ActionGraphContainer getActionGraphContainer() {
+ ActionGraphContainer.Builder actionGraphBuilder = ActionGraphContainer.newBuilder();
+ ActionGraphIdCache actionGraphIdCache = new ActionGraphIdCache(actionGraphBuilder);
+ for (Map.Entry<SkyKey, ? extends NodeEntry> skyKeyAndNodeEntry :
+ memoizingEvaluator.getGraphMap().entrySet()) {
+ NodeEntry entry = skyKeyAndNodeEntry.getValue();
+ SkyKey key = skyKeyAndNodeEntry.getKey();
+ SkyFunctionName functionName = key.functionName();
+ try {
+ if (functionName.equals(SkyFunctions.CONFIGURED_TARGET)) {
+ dumpConfiguredTarget(actionGraphBuilder, actionGraphIdCache, entry);
+ } else if (functionName.equals(SkyFunctions.ASPECT)) {
+ dumpAspect(actionGraphBuilder, actionGraphIdCache, entry);
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new IllegalStateException("No interruption in sequenced evaluation", e);
+ }
+ }
+ return actionGraphBuilder.build();
+ }
+
+ private void dumpAspect(
+ ActionGraphContainer.Builder actionGraphBuilder,
+ ActionGraphIdCache actionGraphIdCache,
+ NodeEntry entry)
+ throws InterruptedException {
+ AspectValue aspectValue = (AspectValue) entry.getValue();
+ AspectKey aspectKey = aspectValue.getKey();
+ ConfiguredTargetValue value =
+ (ConfiguredTargetValue)
+ memoizingEvaluator.getExistingValue(aspectKey.getBaseConfiguredTargetKey());
+ ConfiguredTarget configuredTarget = value.getConfiguredTarget();
+ for (int i = 0; i < aspectValue.getNumActions(); i++) {
+ Action action = aspectValue.getAction(i);
+ dumpSingleAction(actionGraphIdCache, actionGraphBuilder, configuredTarget, action);
+ }
+ }
+
+ private void dumpConfiguredTarget(
+ ActionGraphContainer.Builder actionGraphBuilder,
+ ActionGraphIdCache actionGraphIdCache,
+ NodeEntry entry)
+ throws InterruptedException {
+ ConfiguredTargetValue ctValue = (ConfiguredTargetValue) entry.getValue();
+ ConfiguredTarget configuredTarget = ctValue.getConfiguredTarget();
+ List<ActionAnalysisMetadata> actions = ctValue.getActions();
+ for (ActionAnalysisMetadata action : actions) {
+ dumpSingleAction(actionGraphIdCache, actionGraphBuilder, configuredTarget, action);
+ }
+ }
+
+ private void dumpSingleAction(
+ ActionGraphIdCache actionGraphIdCache,
+ ActionGraphContainer.Builder actionGraphBuilder,
+ ConfiguredTarget configuredTarget,
+ ActionAnalysisMetadata action) {
+ Preconditions.checkState(configuredTarget instanceof RuleConfiguredTarget);
+ Label label = configuredTarget.getLabel();
+ String ruleClassString = ((RuleConfiguredTarget) configuredTarget).getRuleClassString();
+ ActionGraphProtos.Action.Builder actionBuilder =
+ ActionGraphProtos.Action.newBuilder()
+ .setMnemonic(action.getMnemonic())
+ .setTargetId(actionGraphIdCache.targetToId(label, ruleClassString));
+
+ if (action instanceof ActionExecutionMetadata) {
+ ActionExecutionMetadata actionExecutionMetadata = (ActionExecutionMetadata) action;
+ actionBuilder
+ .setActionKey(actionExecutionMetadata.getKey(actionGraphIdCache.getActionKeyContext()))
+ .setDiscoversInputs(actionExecutionMetadata.discoversInputs());
+ }
+
+ // store environment
+ if (action instanceof SpawnAction) {
+ SpawnAction spawnAction = (SpawnAction) action;
+ // TODO(twerth): This handles the fixed environemnt. We probably want to output the inherited
+ // environment as well.
+ ImmutableMap<String, String> fixedEnvironment = spawnAction.getEnvironment();
+ for (Entry<String, String> environmentVariable : fixedEnvironment.entrySet()) {
+ ActionGraphProtos.KeyValuePair.Builder keyValuePairBuilder =
+ ActionGraphProtos.KeyValuePair.newBuilder();
+ keyValuePairBuilder
+ .setKey(environmentVariable.getKey())
+ .setValue(environmentVariable.getValue());
+ actionBuilder.addEnvironmentVariables(keyValuePairBuilder.build());
+ }
+ }
+
+ ActionOwner actionOwner = action.getOwner();
+ if (actionOwner != null) {
+ BuildConfiguration buildConfiguration = (BuildConfiguration) actionOwner.getConfiguration();
+ actionBuilder.setConfigurationId(actionGraphIdCache.configurationToId(buildConfiguration));
+
+ // store aspect
+ for (AspectDescriptor aspectDescriptor : actionOwner.getAspectDescriptors()) {
+ actionBuilder.addAspectDescriptorIds(
+ actionGraphIdCache.aspectDescriptorToId(aspectDescriptor));
+ }
+ }
+
+ // store inputs
+ Iterable<Artifact> inputs = action.getInputs();
+ if (!(inputs instanceof NestedSet)) {
+ inputs = NestedSetBuilder.wrap(Order.STABLE_ORDER, inputs);
+ }
+ NestedSetView<Artifact> nestedSetView = new NestedSetView<>((NestedSet<Artifact>) inputs);
+ if (nestedSetView.directs().size() > 0 || nestedSetView.transitives().size() > 0) {
+ actionBuilder.addInputDepSetIds(actionGraphIdCache.depSetToId(nestedSetView));
+ }
+
+ // store outputs
+ for (Artifact artifact : action.getOutputs()) {
+ actionBuilder.addOutputIds(actionGraphIdCache.artifactToId(artifact));
+ }
+
+ actionGraphBuilder.addActions(actionBuilder.build());
+ }
+
/**
* In addition to calling the superclass method, deletes all ConfiguredTarget values from the
* Skyframe cache. This is done to save memory (e.g. on a configuration change); since the
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
index df71799ec8..afc787b54d 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
@@ -41,6 +41,7 @@ import com.google.devtools.build.lib.actions.ActionCacheChecker;
import com.google.devtools.build.lib.actions.ActionExecutionContextFactory;
import com.google.devtools.build.lib.actions.ActionExecutionStatusReporter;
import com.google.devtools.build.lib.actions.ActionGraph;
+import com.google.devtools.build.lib.actions.ActionGraphProtos.ActionGraphContainer;
import com.google.devtools.build.lib.actions.ActionInputFileCache;
import com.google.devtools.build.lib.actions.ActionInputPrefetcher;
import com.google.devtools.build.lib.actions.ActionKeyContext;
@@ -593,6 +594,8 @@ public abstract class SkyframeExecutor implements WalkableGraphFactory {
}
}
+ public abstract ActionGraphContainer getActionGraphContainer();
+
class BuildViewProvider {
/**
* Returns the current {@link SkyframeBuildView} instance.
diff --git a/src/main/protobuf/BUILD b/src/main/protobuf/BUILD
index d48de4388e..cdb557a374 100644
--- a/src/main/protobuf/BUILD
+++ b/src/main/protobuf/BUILD
@@ -14,6 +14,7 @@ exports_files(
FILES = [
"action_cache",
+ "action_graph",
"android_deploy_info",
"bazel_flags",
"build",
diff --git a/src/main/protobuf/action_graph.proto b/src/main/protobuf/action_graph.proto
new file mode 100644
index 0000000000..fdb49d79ca
--- /dev/null
+++ b/src/main/protobuf/action_graph.proto
@@ -0,0 +1,157 @@
+// Copyright 2018 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.
+
+syntax = "proto3";
+
+package action_graph;
+
+option java_package = "com.google.devtools.build.lib.actions";
+option java_outer_classname = "ActionGraphProtos";
+
+// Container for the action graph properties.
+message ActionGraphContainer {
+ repeated Artifact artifacts = 1;
+ repeated Action actions = 2;
+ repeated Target targets = 3;
+ repeated DepSetOfFiles dep_set_of_files = 4;
+ repeated Configuration configuration = 5;
+ repeated AspectDescriptor aspect_descriptors = 6;
+ repeated RuleClass rule_classes = 7;
+}
+
+// Represents a single artifact, whether it's a source file or a derived output
+// file.
+message Artifact {
+ // Identifier for this artifact; this is an opaque string, only valid for this
+ // particular dump of the action graph.
+ string id = 1;
+
+ // The relative path of the file within the execution root.
+ string exec_path = 2;
+
+ // True iff the artifact is a tree artifact, i.e. the above exec_path refers
+ // a directory.
+ bool is_tree_artifact = 3;
+}
+
+// Represents a single action, which is a function from Artifact(s) to
+// Artifact(s).
+message Action {
+ // The target that was responsible for the creation of the action.
+ string target_id = 1;
+
+ // The aspects that were responsible for the creation of the action (if any).
+ repeated string aspect_descriptor_ids = 2;
+
+ // Encodes all significant behavior that might affect the output. The key
+ // must change if the work performed by the execution of this action changes.
+ // Note that the key doesn't include checksums of the input files.
+ string action_key = 3;
+
+ // The mnemonic for this kind of action.
+ string mnemonic = 4;
+
+ // The configuration under which this action is executed.
+ string configuration_id = 5;
+
+ // The command line arguments of the action. This will be only set if
+ // explicitly requested.
+ repeated string arguments = 6;
+
+ // The list of environment variables to be set before executing the command.
+ repeated KeyValuePair environment_variables = 7;
+
+ // The set of input dep sets that the action depends upon. If the action does
+ // input discovery, the contents of this set might change during execution.
+ repeated string input_dep_set_ids = 8;
+
+ // The list of Artifact IDs that represent the output files that this action
+ // will generate.
+ repeated string output_ids = 9;
+
+ // True iff the action does input discovery during execution.
+ bool discovers_inputs = 10;
+}
+
+// Represents a single target (without configuration information) that is
+// associated with an action.
+message Target {
+ // Identifier for this target; this is an opaque string, only valid for this
+ // particular dump of the action graph.
+ string id = 1;
+
+ // Label of the target, e.g. //foo:bar.
+ string label = 2;
+
+ // Class of the rule.
+ string rule_class_id = 3;
+}
+
+message RuleClass {
+ // Identifier for this rule class; this is an opaque string, only valid for
+ // this particular dump of the action graph.
+ string id = 1;
+
+ // Name of the rule class, e.g. cc_library.
+ string name = 2;
+}
+
+// Represents an invocation specific descriptor of an aspect.
+message AspectDescriptor {
+ // Identifier for this aspect descriptor; this is an opaque string, only valid
+ // for the particular dump of the action graph.
+ string id = 1;
+
+ // The name of the corresponding aspect. For native aspects, it's the Java
+ // class name, for Skylark aspects it's the bzl file followed by a % sign
+ // followed by the name of the aspect.
+ string name = 2;
+
+ // The list of parameters bound to a particular invocation of that aspect on
+ // a target. Note that aspects can be executed multiple times on the same
+ // target in different order.
+ repeated KeyValuePair parameters = 3;
+}
+
+message DepSetOfFiles {
+ // Identifier for this named set of files; this is an opaque string, only
+ // valid for the particular dump of the action graph.
+ string id = 1;
+
+ // Other transitively included named set of files.
+ repeated string transitive_dep_set_ids = 2;
+
+ // The list of input artifact IDs that are immediately contained in this set.
+ repeated string direct_artifact_ids = 3;
+}
+
+message Configuration {
+ // Identifier for this configuration; this is an opaque string, only valid for
+ // the particular dump of the action graph.
+ string id = 1;
+
+ // The mnemonic representing the build configuration.
+ string mnemonic = 2;
+
+ // The platform string.
+ string platform_name = 3;
+}
+
+message KeyValuePair {
+ // The variable name.
+ string key = 1;
+
+ // The variable value.
+ string value = 2;
+}