// 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.rules.extra; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.Runfiles; import com.google.devtools.build.lib.analysis.RunfilesProvider; import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; import com.google.devtools.build.lib.collect.ImmutableSortedKeyListMultimap; import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException; import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; import com.google.devtools.build.lib.syntax.Type; import java.util.ArrayList; import java.util.List; import java.util.Set; /** * Implementation for the 'action_listener' rule. */ public final class ActionListener implements RuleConfiguredTargetFactory { @Override public ConfiguredTarget create(RuleContext ruleContext) throws RuleErrorException { // This rule doesn't produce any output when listed as a build target. // Only when used via the --experimental_action_listener flag, // this rule instructs the build system to add additional outputs. List<ExtraActionSpec> extraActions; Multimap<String, ExtraActionSpec> extraActionMap; Set<String> mnemonics = Sets.newHashSet( ruleContext.attributes().get("mnemonics", Type.STRING_LIST)); extraActions = retrieveAndValidateExtraActions(ruleContext); ImmutableSortedKeyListMultimap.Builder<String, ExtraActionSpec> extraActionMapBuilder = ImmutableSortedKeyListMultimap.builder(); for (String mnemonic : mnemonics) { extraActionMapBuilder.putAll(mnemonic, extraActions); } extraActionMap = extraActionMapBuilder.build(); return new RuleConfiguredTargetBuilder(ruleContext) .add(RunfilesProvider.class, RunfilesProvider.simple(Runfiles.EMPTY)) .add(ExtraActionMapProvider.class, new ExtraActionMapProvider(extraActionMap)) .build(); } /** * Loads the targets listed in the 'extra_actions' attribute of this rule. * Validates these targets to be extra_actions indeed. And checks if the * blaze version number is in the range of the blaze_version restrictions on the rule. */ private List<ExtraActionSpec> retrieveAndValidateExtraActions(RuleContext ruleContext) { List<ExtraActionSpec> extraActions = new ArrayList<>(); for (TransitiveInfoCollection prerequisite : ruleContext.getPrerequisites("extra_actions", Mode.TARGET)) { ExtraActionSpec spec = prerequisite.getProvider(ExtraActionSpec.class); if (spec == null) { ruleContext.attributeError("extra_actions", String.format("target %s is not an " + "extra_action rule", prerequisite.getLabel().toString())); } else { extraActions.add(spec); } } if (extraActions.isEmpty()) { ruleContext.attributeWarning("extra_actions", "No extra_action is specified for this version of blaze."); } return extraActions; } }