blob: 6e1679c2771552f4c09f1f36ec19f03ce24135df [file] [log] [blame]
// 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.
package com.google.devtools.build.lib.skyframe.actiongraph;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
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.ActionKeyContext;
import com.google.devtools.build.lib.actions.ActionOwner;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.CommandLineExpansionException;
import com.google.devtools.build.lib.analysis.AnalysisProtos;
import com.google.devtools.build.lib.analysis.AnalysisProtos.ActionGraphContainer;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
import com.google.devtools.build.lib.buildeventstream.BuildEvent;
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.packages.AspectDescriptor;
import com.google.devtools.build.lib.skyframe.AspectValue;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetValue;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Encapsulates necessary functionality to dump the current skyframe state of the action graph to
* proto format.
*/
public class ActionGraphDump {
private final ActionGraphContainer.Builder actionGraphBuilder = ActionGraphContainer.newBuilder();
private final ActionKeyContext actionKeyContext = new ActionKeyContext();
private final Set<String> actionGraphTargets;
private final KnownRuleClassStrings knownRuleClassStrings;
private final KnownArtifacts knownArtifacts;
private final KnownConfigurations knownConfigurations;
private final KnownNestedSets knownNestedSets;
private final KnownAspectDescriptors knownAspectDescriptors;
private final KnownRuleConfiguredTargets knownRuleConfiguredTargets;
private final boolean includeActionCmdLine;
public ActionGraphDump(List<String> actionGraphTargets, boolean includeActionCmdLine) {
this.actionGraphTargets = ImmutableSet.copyOf(actionGraphTargets);
this.includeActionCmdLine = includeActionCmdLine;
knownRuleClassStrings = new KnownRuleClassStrings(actionGraphBuilder);
knownArtifacts = new KnownArtifacts(actionGraphBuilder);
knownConfigurations = new KnownConfigurations(actionGraphBuilder);
knownNestedSets = new KnownNestedSets(actionGraphBuilder, knownArtifacts);
knownAspectDescriptors = new KnownAspectDescriptors(actionGraphBuilder);
knownRuleConfiguredTargets = new KnownRuleConfiguredTargets(actionGraphBuilder,
knownRuleClassStrings);
}
public ActionKeyContext getActionKeyContext() {
return actionKeyContext;
}
private boolean includeInActionGraph(String labelString) {
if (actionGraphTargets.size() == 1
&& Iterables.getOnlyElement(actionGraphTargets).equals("...")) {
return true;
}
return actionGraphTargets.contains(labelString);
}
private void dumpSingleAction(ConfiguredTarget configuredTarget, ActionAnalysisMetadata action)
throws CommandLineExpansionException {
Preconditions.checkState(configuredTarget instanceof RuleConfiguredTarget);
RuleConfiguredTarget ruleConfiguredTarget = (RuleConfiguredTarget) configuredTarget;
AnalysisProtos.Action.Builder actionBuilder =
AnalysisProtos.Action.newBuilder()
.setMnemonic(action.getMnemonic())
.setTargetId(knownRuleConfiguredTargets.dataToId(ruleConfiguredTarget));
if (action instanceof ActionExecutionMetadata) {
ActionExecutionMetadata actionExecutionMetadata = (ActionExecutionMetadata) action;
actionBuilder
.setActionKey(actionExecutionMetadata.getKey(getActionKeyContext()))
.setDiscoversInputs(actionExecutionMetadata.discoversInputs());
}
// store environment
if (action instanceof SpawnAction) {
SpawnAction spawnAction = (SpawnAction) action;
// TODO(twerth): This handles the fixed environment. We probably want to output the inherited
// environment as well.
ImmutableMap<String, String> fixedEnvironment = spawnAction.getEnvironment();
for (Map.Entry<String, String> environmentVariable : fixedEnvironment.entrySet()) {
AnalysisProtos.KeyValuePair.Builder keyValuePairBuilder =
AnalysisProtos.KeyValuePair.newBuilder();
keyValuePairBuilder
.setKey(environmentVariable.getKey())
.setValue(environmentVariable.getValue());
actionBuilder.addEnvironmentVariables(keyValuePairBuilder.build());
}
if (includeActionCmdLine) {
actionBuilder.addAllArguments(spawnAction.getArguments());
}
}
ActionOwner actionOwner = action.getOwner();
if (actionOwner != null) {
BuildEvent event = actionOwner.getConfiguration();
actionBuilder.setConfigurationId(knownConfigurations.dataToId(event));
// store aspect
for (AspectDescriptor aspectDescriptor : actionOwner.getAspectDescriptors()) {
actionBuilder.addAspectDescriptorIds(knownAspectDescriptors.dataToId(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(knownNestedSets.dataToId(nestedSetView));
}
// store outputs
for (Artifact artifact : action.getOutputs()) {
actionBuilder.addOutputIds(knownArtifacts.dataToId(artifact));
}
actionGraphBuilder.addActions(actionBuilder.build());
}
public void dumpAspect(AspectValue aspectValue, ConfiguredTargetValue configuredTargetValue)
throws CommandLineExpansionException {
ConfiguredTarget configuredTarget = configuredTargetValue.getConfiguredTarget();
if (!includeInActionGraph(configuredTarget.getLabel().toString())) {
return;
}
for (int i = 0; i < aspectValue.getNumActions(); i++) {
Action action = aspectValue.getAction(i);
dumpSingleAction(configuredTarget, action);
}
}
public void dumpConfiguredTarget(ConfiguredTargetValue configuredTargetValue)
throws CommandLineExpansionException {
ConfiguredTarget configuredTarget = configuredTargetValue.getConfiguredTarget();
if (!includeInActionGraph(configuredTarget.getLabel().toString())) {
return;
}
List<ActionAnalysisMetadata> actions = configuredTargetValue.getActions();
for (ActionAnalysisMetadata action : actions) {
dumpSingleAction(configuredTarget, action);
}
}
public ActionGraphContainer build() {
return actionGraphBuilder.build();
}
}