com.google.devtools.build.lib.analysis.ExtraActionUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.google.devtools.build.lib.analysis.ExtraActionUtils.java

Source

// Copyright 2015 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;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.rules.extra.ExtraActionMapProvider;
import com.google.devtools.build.lib.rules.extra.ExtraActionSpec;
import java.util.List;
import java.util.Set;

/**
 * A collection of static methods related to ExtraActions.
 */
class ExtraActionUtils {
    /**
     * Scans {@code action_listeners} associated with this build to see if any
     * {@code extra_actions} should be added to this configured target. If any
     * action_listeners are present, a partial visit of the artifact/action graph
     * is performed (for as long as actions found are owned by this {@link
     * ConfiguredTarget}). Any actions that match the {@code action_listener}
     * get an {@code extra_action} associated. The output artifacts of the
     * extra_action are reported to the {@link AnalysisEnvironment} for
     * bookkeeping.
     */
    static ExtraActionArtifactsProvider createExtraActionProvider(
            Set<ActionAnalysisMetadata> actionsWithoutExtraAction, RuleContext ruleContext) {
        BuildConfiguration configuration = ruleContext.getConfiguration();
        if (configuration.isHostConfiguration()) {
            return ExtraActionArtifactsProvider.EMPTY;
        }

        ImmutableList<Artifact> extraActionArtifacts = ImmutableList.of();
        NestedSetBuilder<Artifact> builder = NestedSetBuilder.stableOrder();

        List<Label> actionListenerLabels = configuration.getActionListeners();
        if (!actionListenerLabels.isEmpty()
                && ruleContext.attributes().getAttributeDefinition(":action_listener") != null) {
            ExtraActionsVisitor visitor = new ExtraActionsVisitor(ruleContext,
                    computeMnemonicsToExtraActionMap(ruleContext));

            // The action list is modified within the body of the loop by the maybeAddExtraAction() call,
            // thus the copy
            for (ActionAnalysisMetadata action : ImmutableList
                    .copyOf(ruleContext.getAnalysisEnvironment().getRegisteredActions())) {
                if (!actionsWithoutExtraAction.contains(action)) {
                    visitor.maybeAddExtraAction(action);
                }
            }

            extraActionArtifacts = visitor.getAndResetExtraArtifacts();
            if (!extraActionArtifacts.isEmpty()) {
                builder.addAll(extraActionArtifacts);
            }
        }

        // Add extra action artifacts from dependencies
        for (ExtraActionArtifactsProvider provider : AnalysisUtils
                .getProviders(ruleContext.getConfiguredTargetMap().values(), ExtraActionArtifactsProvider.class)) {
            builder.addTransitive(provider.getTransitiveExtraActionArtifacts());
        }

        return ExtraActionArtifactsProvider.create(
                NestedSetBuilder.<Artifact>stableOrder().addAll(extraActionArtifacts).build(), builder.build());
    }

    /**
     * Populates the configuration specific mnemonicToExtraActionMap
     * based on all action_listers selected by the user (via the blaze option
     * {@code --experimental_action_listener=<target>}).
     */
    private static Multimap<String, ExtraActionSpec> computeMnemonicsToExtraActionMap(RuleContext ruleContext) {
        // We copy the multimap here every time. This could be expensive.
        Multimap<String, ExtraActionSpec> mnemonicToExtraActionMap = HashMultimap.create();
        for (TransitiveInfoCollection actionListener : ruleContext.getPrerequisites(":action_listener",
                Mode.HOST)) {
            ExtraActionMapProvider provider = actionListener.getProvider(ExtraActionMapProvider.class);
            if (provider == null) {
                ruleContext.ruleError(String.format(
                        "Unable to match experimental_action_listeners to this rule. "
                                + "Specified target %s is not an action_listener rule",
                        actionListener.getLabel().toString()));
            } else {
                mnemonicToExtraActionMap.putAll(provider.getExtraActionMap());
            }
        }
        return mnemonicToExtraActionMap;
    }
}