// 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.ImmutableList; 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 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(boolean includeActionCmdLine) { this(/* actionGraphTargets= */ ImmutableList.of("..."), includeActionCmdLine); } public ActionGraphDump(List 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 fixedEnvironment = spawnAction.getEnvironment().getFixedEnv(); for (Map.Entry 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 inputs = action.getInputs(); if (!(inputs instanceof NestedSet)) { inputs = NestedSetBuilder.wrap(Order.STABLE_ORDER, inputs); } NestedSetView nestedSetView = new NestedSetView<>((NestedSet) 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 actions = configuredTargetValue.getActions(); for (ActionAnalysisMetadata action : actions) { dumpSingleAction(configuredTarget, action); } } public ActionGraphContainer build() { return actionGraphBuilder.build(); } }