blob: 78f23fe869a8e718ada1bc57861361489ac4aa41 [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2014 The Bazel Authors. All rights reserved.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package com.google.devtools.build.lib.analysis;
16
jhorvitz04816f52021-08-11 10:51:51 -070017import static com.google.common.collect.ImmutableList.toImmutableList;
Austin Schuhd1813532023-02-14 22:48:22 -080018import static com.google.devtools.build.lib.analysis.test.ExecutionInfo.DEFAULT_TEST_RUNNER_EXEC_GROUP;
jcater64534e22021-05-06 07:56:27 -070019import static com.google.devtools.build.lib.packages.ExecGroup.DEFAULT_EXEC_GROUP_NAME;
juliexxiaff580812020-04-30 15:01:09 -070020
Janak Ramakrishnan7857c792016-03-21 08:35:35 +000021import com.google.common.annotations.VisibleForTesting;
Yun Peng5c34e962016-02-22 15:13:19 +000022import com.google.common.base.Joiner;
Googler59480b92016-07-22 17:06:40 +000023import com.google.common.base.Optional;
tomlua155b532017-11-08 20:12:47 +010024import com.google.common.base.Preconditions;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010025import com.google.common.base.Predicate;
Yun Pengefd7ca12016-03-03 13:14:38 +000026import com.google.common.base.Predicates;
Florian Weikert082c0542015-08-06 10:24:29 +000027import com.google.common.collect.ImmutableCollection;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010028import com.google.common.collect.ImmutableList;
29import com.google.common.collect.ImmutableListMultimap;
30import com.google.common.collect.ImmutableMap;
31import com.google.common.collect.ImmutableSet;
Manuel Klimek6d9fb362015-04-30 12:50:55 +000032import com.google.common.collect.ImmutableSortedSet;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010033import com.google.common.collect.Iterables;
34import com.google.common.collect.ListMultimap;
janakrf3e6f252018-01-18 07:45:12 -080035import com.google.common.collect.Lists;
mjhalupkade47f212018-02-12 12:31:21 -080036import com.google.common.collect.Maps;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010037import com.google.common.collect.Multimaps;
38import com.google.common.collect.Sets;
Googler38349752023-01-11 09:02:30 -080039import com.google.common.collect.Streams;
Rumou Duan33bab462016-04-25 17:55:12 +000040import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
jhorvitz3daedc32020-07-22 18:33:55 -070041import com.google.devtools.build.lib.actions.ActionLookupKey;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010042import com.google.devtools.build.lib.actions.ActionOwner;
43import com.google.devtools.build.lib.actions.ActionRegistry;
44import com.google.devtools.build.lib.actions.Artifact;
cpeyserac09f0a2018-02-05 09:33:15 -080045import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
tomlu1cdcdf92018-01-16 11:07:51 -080046import com.google.devtools.build.lib.actions.ArtifactRoot;
lberkiee2dcae2018-03-28 05:49:04 -070047import com.google.devtools.build.lib.analysis.AliasProvider.TargetMode;
jcater645c42b2021-05-12 09:35:48 -070048import com.google.devtools.build.lib.analysis.ExecGroupCollection.InvalidExecGroupException;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010049import com.google.devtools.build.lib.analysis.actions.ActionConstructionContext;
jcater1865d892020-04-14 10:04:29 -070050import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoKey;
jhorvitz33f76482021-10-28 10:13:26 -070051import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
gregce79989f92021-02-01 07:01:55 -080052import com.google.devtools.build.lib.analysis.config.ConfigConditions;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010053import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
jcatera666f002020-04-14 14:55:20 -070054import com.google.devtools.build.lib.analysis.config.Fragment;
jcater0a1e9eb2019-12-17 09:58:38 -080055import com.google.devtools.build.lib.analysis.platform.ConstraintValueInfo;
John Cater15c90b32017-12-18 08:34:40 -080056import com.google.devtools.build.lib.analysis.platform.PlatformInfo;
Googler928e0fe2023-01-18 02:31:45 -080057import com.google.devtools.build.lib.analysis.platform.ToolchainInfo;
brandjonf1cc4dd2021-02-01 08:53:40 -080058import com.google.devtools.build.lib.analysis.starlark.StarlarkRuleContext;
ulfjack01bf32e2017-11-02 17:50:07 -040059import com.google.devtools.build.lib.analysis.stringtemplate.TemplateContext;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000060import com.google.devtools.build.lib.cmdline.Label;
dslomovfd62e762017-09-19 16:55:53 +020061import com.google.devtools.build.lib.cmdline.RepositoryName;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010062import com.google.devtools.build.lib.collect.ImmutableSortedKeyListMultimap;
63import com.google.devtools.build.lib.collect.nestedset.NestedSet;
brandjonbfd332e2020-12-17 14:56:04 -080064import com.google.devtools.build.lib.events.Event;
dslomov44d15712017-12-20 05:42:28 -080065import com.google.devtools.build.lib.packages.Aspect;
Dmitry Lomov15756522016-12-16 16:52:37 +000066import com.google.devtools.build.lib.packages.AspectDescriptor;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010067import com.google.devtools.build.lib.packages.Attribute;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010068import com.google.devtools.build.lib.packages.AttributeMap;
brandjonbfd332e2020-12-17 14:56:04 -080069import com.google.devtools.build.lib.packages.BazelStarlarkContext;
Lukacs Berkiffa73ad2015-09-18 11:40:12 +000070import com.google.devtools.build.lib.packages.BuildType;
cparsons2d67cf92018-05-24 14:02:09 -070071import com.google.devtools.build.lib.packages.BuiltinProvider;
Michael Staibb51251e2015-09-29 23:31:51 +000072import com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy;
cparsons78927792017-10-11 00:14:19 +020073import com.google.devtools.build.lib.packages.ConfiguredAttributeMapper;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010074import com.google.devtools.build.lib.packages.ImplicitOutputsFunction;
dslomovde965ac2017-07-31 21:07:51 +020075import com.google.devtools.build.lib.packages.Info;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010076import com.google.devtools.build.lib.packages.OutputFile;
Googler720dc5f2022-09-16 03:43:51 -070077import com.google.devtools.build.lib.packages.Package;
gregce79989f92021-02-01 07:01:55 -080078import com.google.devtools.build.lib.packages.Package.ConfigSettingVisibilityPolicy;
cushon34ff85e2017-11-15 08:59:27 -080079import com.google.devtools.build.lib.packages.PackageSpecification.PackageGroupContents;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010080import com.google.devtools.build.lib.packages.RawAttributeMapper;
dslomovc13bb392017-08-02 23:29:54 +020081import com.google.devtools.build.lib.packages.RequiredProviders;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010082import com.google.devtools.build.lib.packages.Rule;
83import com.google.devtools.build.lib.packages.RuleClass;
brandjonf1cc4dd2021-02-01 08:53:40 -080084import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
Googler995ef632019-09-04 12:25:41 -070085import com.google.devtools.build.lib.packages.SymbolGenerator;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010086import com.google.devtools.build.lib.packages.Target;
87import com.google.devtools.build.lib.packages.TargetUtils;
Googlerc5fcc862019-09-06 16:17:47 -070088import com.google.devtools.build.lib.packages.Type;
89import com.google.devtools.build.lib.packages.Type.LabelClass;
adonovan028e1ad2020-09-07 07:09:59 -070090import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions;
janakr9c101402018-03-10 06:48:59 -080091import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010092import com.google.devtools.build.lib.util.FileTypeSet;
cparsons0623d3c2018-10-23 16:06:30 -070093import com.google.devtools.build.lib.util.OS;
Greg Estrend5353252016-08-11 22:13:31 +000094import com.google.devtools.build.lib.util.OrderedSetMultimap;
Googlere49cd592016-07-29 19:32:38 +000095import com.google.devtools.build.lib.util.StringUtil;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010096import com.google.devtools.build.lib.vfs.FileSystemUtils;
97import com.google.devtools.build.lib.vfs.PathFragment;
Kurt Alfred Kluever4192ca62022-07-05 06:30:29 -070098import com.google.errorprone.annotations.CanIgnoreReturnValue;
gregce31e44792020-04-27 09:10:40 -070099import java.util.ArrayList;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100100import java.util.Collection;
101import java.util.HashMap;
102import java.util.HashSet;
Dmitry Lomovfd2bdc32016-10-07 08:52:10 +0000103import java.util.LinkedHashSet;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100104import java.util.List;
105import java.util.Map;
106import java.util.Set;
dslomov44d15712017-12-20 05:42:28 -0800107import java.util.stream.Collectors;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100108import javax.annotation.Nullable;
adonovan450c7ad2020-09-14 13:00:21 -0700109import net.starlark.java.eval.EvalException;
brandjonbfd332e2020-12-17 14:56:04 -0800110import net.starlark.java.eval.Mutability;
brandjon4f331eb2021-02-01 09:09:39 -0800111import net.starlark.java.eval.Starlark;
adonovan450c7ad2020-09-14 13:00:21 -0700112import net.starlark.java.eval.StarlarkSemantics;
brandjonbfd332e2020-12-17 14:56:04 -0800113import net.starlark.java.eval.StarlarkThread;
adonovan450c7ad2020-09-14 13:00:21 -0700114import net.starlark.java.syntax.Location;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100115
116/**
Lukacs Berki2300cd62016-05-19 11:06:37 +0000117 * The totality of data available during the analysis of a rule.
Janak Ramakrishnan81c5bd82016-03-22 20:07:43 +0000118 *
jcater02ce2a62020-04-07 08:06:00 -0700119 * <p>These objects should not outlast the analysis phase. Do not pass them to {@link
120 * com.google.devtools.build.lib.actions.Action} objects or other persistent objects. There are
121 * internal tests to ensure that RuleContext objects are not persisted that check the name of this
122 * class, so update those tests if you change this class's name.
Lukacs Berki2300cd62016-05-19 11:06:37 +0000123 *
ulfjack26d0e492017-08-07 13:42:33 +0200124 * @see com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100125 */
126public final class RuleContext extends TargetContext
brandjonbfd332e2020-12-17 14:56:04 -0800127 implements ActionConstructionContext, ActionRegistry, RuleErrorConsumer, AutoCloseable {
Carmi Grushko33aa3062016-11-11 02:45:29 +0000128
jcater0de10972020-04-07 12:15:05 -0700129 /** Custom dependency validation logic. */
130 public interface PrerequisiteValidator {
131 /**
132 * Checks whether the rule in {@code contextBuilder} is allowed to depend on {@code
133 * prerequisite} through the attribute {@code attribute}.
134 *
135 * <p>Can be used for enforcing any organization-specific policies about the layout of the
136 * workspace.
137 */
138 void validate(
139 Builder contextBuilder, ConfiguredTargetAndData prerequisite, Attribute attribute);
140 }
141
ilist67c99362022-01-04 02:39:00 -0800142 private static final String TOOL_CONFIGURATION_PROGRESS_TAG = "for tool";
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100143
144 private final Rule rule;
dslomov44d15712017-12-20 05:42:28 -0800145 /**
brandjonf1cc4dd2021-02-01 08:53:40 -0800146 * A list of all aspects applied to the target. If this {@code RuleContext} is for a rule
147 * implementation, {@code aspects} is an empty list.
dslomov44d15712017-12-20 05:42:28 -0800148 *
brandjonf1cc4dd2021-02-01 08:53:40 -0800149 * <p>Otherwise, the last aspect in the list is the one that this {@code RuleContext} is for.
dslomov44d15712017-12-20 05:42:28 -0800150 */
151 private final ImmutableList<Aspect> aspects;
brandjonf1cc4dd2021-02-01 08:53:40 -0800152
Dmitry Lomov15756522016-12-16 16:52:37 +0000153 private final ImmutableList<AspectDescriptor> aspectDescriptors;
janakr9c101402018-03-10 06:48:59 -0800154 private final ListMultimap<String, ConfiguredTargetAndData> targetMap;
Lukacs Berki7894c182016-05-10 12:07:01 +0000155 private final ImmutableMap<Label, ConfigMatchingProvider> configConditions;
Greg Estren7f534232016-12-01 21:38:25 +0000156 private final AspectAwareAttributeMapper attributes;
Googler993f1de2018-02-20 02:31:10 -0800157 private final ImmutableSet<String> enabledFeatures;
158 private final ImmutableSet<String> disabledFeatures;
Michael Staib8824d5e2016-01-20 21:37:05 +0000159 private final String ruleClassNameForLogging;
Michael Staibb51251e2015-09-29 23:31:51 +0000160 private final ConfigurationFragmentPolicy configurationFragmentPolicy;
jhorvitz2cdb6472021-10-06 14:22:36 -0700161 private final ConfiguredRuleClassProvider ruleClassProvider;
cparsonse8d450c2018-10-04 16:01:53 -0700162 private final RuleErrorConsumer reporter;
juliexxiab5f9d742020-04-09 13:07:13 -0700163 @Nullable private final ToolchainCollection<ResolvedToolchainContext> toolchainContexts;
jcater645c42b2021-05-12 09:35:48 -0700164 private final ExecGroupCollection execGroupCollection;
jhorvitz8128f522021-08-18 17:33:43 -0700165 @Nullable private final RequiredConfigFragmentsProvider requiredConfigFragments;
Googler720dc5f2022-09-16 03:43:51 -0700166 @Nullable private final NestedSet<Package> transitivePackagesForRunfileRepoMappingManifest;
gregce31e44792020-04-27 09:10:40 -0700167 private final List<Expander> makeVariableExpanders = new ArrayList<>();
Michajlo Matijkiwe64bfce2016-07-18 14:37:08 +0000168
juliexxiaff580812020-04-30 15:01:09 -0700169 /** Map of exec group names to ActionOwners. */
170 private final Map<String, ActionOwner> actionOwners = new HashMap<>();
171
jhorvitz3daedc32020-07-22 18:33:55 -0700172 private final SymbolGenerator<ActionLookupKey> actionOwnerSymbolGenerator;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100173
174 /* lazily computed cache for Make variables, computed from the above. See get... method */
175 private transient ConfigurationMakeVariableContext configurationMakeVariableContext = null;
176
brandjonbfd332e2020-12-17 14:56:04 -0800177 /**
178 * Thread used for any Starlark evaluation during analysis, e.g. rule implementation function for
179 * a Starlark-defined rule, or Starlarkified helper logic for native rules that have been
180 * partially migrated to {@code @_builtins}.
181 */
182 private final StarlarkThread starlarkThread;
brandjonf1cc4dd2021-02-01 08:53:40 -0800183 /**
184 * The {@code ctx} object passed to a Starlark-defined rule's or aspect's implementation function.
185 * This object may outlive the analysis phase, e.g. if it is returned in a provider.
186 *
187 * <p>Initialized explicitly by calling {@link #initStarlarkRuleContext}. Native rules that do not
188 * pass this object to {@code @_builtins} might avoid the cost of initializing this object, but
189 * for everyone else it's mandatory.
190 */
191 @Nullable private StarlarkRuleContext starlarkRuleContext;
brandjonbfd332e2020-12-17 14:56:04 -0800192
Dmitry Lomovace678e2015-12-16 15:10:20 +0000193 private RuleContext(
194 Builder builder,
Nathan Harmatafcb17112016-04-13 16:56:58 +0000195 AttributeMap attributes,
janakr9c101402018-03-10 06:48:59 -0800196 ListMultimap<String, ConfiguredTargetAndData> targetMap,
jhorvitz2cdb6472021-10-06 14:22:36 -0700197 ExecGroupCollection execGroupCollection) {
lpino5fe7ed02018-07-18 05:55:23 -0700198 super(
199 builder.env,
200 builder.target.getAssociatedRule(),
201 builder.configuration,
202 builder.prerequisiteMap.get(null),
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100203 builder.visibility);
lpino5fe7ed02018-07-18 05:55:23 -0700204 this.rule = builder.target.getAssociatedRule();
dslomov44d15712017-12-20 05:42:28 -0800205 this.aspects = builder.aspects;
jhorvitz2cdb6472021-10-06 14:22:36 -0700206 this.aspectDescriptors = aspects.stream().map(Aspect::getDescriptor).collect(toImmutableList());
Michael Staibb51251e2015-09-29 23:31:51 +0000207 this.configurationFragmentPolicy = builder.configurationFragmentPolicy;
jhorvitz2cdb6472021-10-06 14:22:36 -0700208 this.ruleClassProvider = builder.ruleClassProvider;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100209 this.targetMap = targetMap;
jhorvitz2cdb6472021-10-06 14:22:36 -0700210 this.configConditions = builder.configConditions.asProviders();
brandjon45ce5452022-02-02 11:52:06 -0800211 this.attributes = new AspectAwareAttributeMapper(attributes, builder.aspectAttributes);
Googler993f1de2018-02-20 02:31:10 -0800212 Set<String> allEnabledFeatures = new HashSet<>();
213 Set<String> allDisabledFeatures = new HashSet<>();
214 getAllFeatures(allEnabledFeatures, allDisabledFeatures);
215 this.enabledFeatures = ImmutableSortedSet.copyOf(allEnabledFeatures);
216 this.disabledFeatures = ImmutableSortedSet.copyOf(allDisabledFeatures);
jhorvitz2cdb6472021-10-06 14:22:36 -0700217 this.ruleClassNameForLogging = builder.getRuleClassNameForLogging();
jhorvitz2cdb6472021-10-06 14:22:36 -0700218 this.actionOwnerSymbolGenerator = new SymbolGenerator<>(builder.actionOwnerSymbol);
219 this.reporter = builder.reporter;
220 this.toolchainContexts = builder.toolchainContexts;
jcater645c42b2021-05-12 09:35:48 -0700221 this.execGroupCollection = execGroupCollection;
jhorvitz2cdb6472021-10-06 14:22:36 -0700222 this.requiredConfigFragments = builder.requiredConfigFragments;
Googler720dc5f2022-09-16 03:43:51 -0700223 this.transitivePackagesForRunfileRepoMappingManifest =
224 builder.transitivePackagesForRunfileRepoMappingManifest;
jhorvitz2cdb6472021-10-06 14:22:36 -0700225 this.starlarkThread = createStarlarkThread(builder.mutability); // uses above state
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100226 }
227
Googler993f1de2018-02-20 02:31:10 -0800228 private void getAllFeatures(Set<String> allEnabledFeatures, Set<String> allDisabledFeatures) {
Manuel Klimek6d9fb362015-04-30 12:50:55 +0000229 Set<String> globallyEnabled = new HashSet<>();
230 Set<String> globallyDisabled = new HashSet<>();
231 parseFeatures(getConfiguration().getDefaultFeatures(), globallyEnabled, globallyDisabled);
232 Set<String> packageEnabled = new HashSet<>();
233 Set<String> packageDisabled = new HashSet<>();
jhorvitz04816f52021-08-11 10:51:51 -0700234 parseFeatures(rule.getPackage().getFeatures(), packageEnabled, packageDisabled);
Googler8e3afcc2017-12-20 08:10:21 -0800235 Set<String> ruleEnabled = new HashSet<>();
236 Set<String> ruleDisabled = new HashSet<>();
237 if (attributes().has("features", Type.STRING_LIST)) {
238 parseFeatures(attributes().get("features", Type.STRING_LIST), ruleEnabled, ruleDisabled);
239 }
Googler993f1de2018-02-20 02:31:10 -0800240
Googler8e3afcc2017-12-20 08:10:21 -0800241 Set<String> ruleDisabledFeatures =
242 Sets.union(ruleDisabled, Sets.difference(packageDisabled, ruleEnabled));
Googler993f1de2018-02-20 02:31:10 -0800243 allDisabledFeatures.addAll(Sets.union(ruleDisabledFeatures, globallyDisabled));
Googler993f1de2018-02-20 02:31:10 -0800244
Manuel Klimek6d9fb362015-04-30 12:50:55 +0000245 Set<String> packageFeatures =
246 Sets.difference(Sets.union(globallyEnabled, packageEnabled), packageDisabled);
Googler8e3afcc2017-12-20 08:10:21 -0800247 Set<String> ruleFeatures =
248 Sets.difference(Sets.union(packageFeatures, ruleEnabled), ruleDisabled);
Googler993f1de2018-02-20 02:31:10 -0800249 allEnabledFeatures.addAll(Sets.difference(ruleFeatures, globallyDisabled));
Manuel Klimek6d9fb362015-04-30 12:50:55 +0000250 }
251
jhorvitz04816f52021-08-11 10:51:51 -0700252 private static void parseFeatures(
253 Iterable<String> features, Set<String> enabled, Set<String> disabled) {
Manuel Klimek6d9fb362015-04-30 12:50:55 +0000254 for (String feature : features) {
255 if (feature.startsWith("-")) {
256 disabled.add(feature.substring(1));
257 } else if (feature.equals("no_layering_check")) {
258 // TODO(bazel-team): Remove once we do not have BUILD files left that contain
259 // 'no_layering_check'.
jhorvitz04816f52021-08-11 10:51:51 -0700260 disabled.add("layering_check");
Manuel Klimek6d9fb362015-04-30 12:50:55 +0000261 } else {
262 enabled.add(feature);
263 }
264 }
265 }
266
jhorvitz2cdb6472021-10-06 14:22:36 -0700267 public boolean isAllowTagsPropagation() {
268 return getAnalysisEnvironment()
269 .getStarlarkSemantics()
270 .getBool(BuildLanguageOptions.EXPERIMENTAL_ALLOW_TAGS_PROPAGATION);
271 }
272
dslomovfd62e762017-09-19 16:55:53 +0200273 public RepositoryName getRepository() {
274 return rule.getRepository();
275 }
276
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100277 @Override
tomlu1cdcdf92018-01-16 11:07:51 -0800278 public ArtifactRoot getBinDirectory() {
Googler0617f2c2020-10-22 08:43:54 -0700279 return getConfiguration().getBinDirectory(getLabel().getRepository());
dslomovfd62e762017-09-19 16:55:53 +0200280 }
281
janakrf2c93912022-03-08 01:40:32 -0800282 @SuppressWarnings("Unused") // Goal is to migrate here.
283 public ArtifactRoot getBuildInfoDirectory() {
284 return getConfiguration().getBuildInfoDirectory(getLabel().getRepository());
Googler36fa3852020-10-13 13:30:14 -0700285 }
286
Googler4e7b1e52020-10-09 11:58:45 -0700287 public ArtifactRoot getGenfilesDirectory() {
Googler0617f2c2020-10-22 08:43:54 -0700288 return getConfiguration().getGenfilesDirectory(getLabel().getRepository());
Googler4e7b1e52020-10-09 11:58:45 -0700289 }
290
Googler36fa3852020-10-13 13:30:14 -0700291 public ArtifactRoot getCoverageMetadataDirectory() {
Googler0617f2c2020-10-22 08:43:54 -0700292 return getConfiguration().getCoverageMetadataDirectory(getLabel().getRepository());
Googler36fa3852020-10-13 13:30:14 -0700293 }
294
295 public ArtifactRoot getTestLogsDirectory() {
Googler0617f2c2020-10-22 08:43:54 -0700296 return getConfiguration().getTestLogsDirectory(getLabel().getRepository());
Googler36fa3852020-10-13 13:30:14 -0700297 }
298
Googler4e7b1e52020-10-09 11:58:45 -0700299 public PathFragment getBinFragment() {
Googler0617f2c2020-10-22 08:43:54 -0700300 return getConfiguration().getBinFragment(getLabel().getRepository());
Googler4e7b1e52020-10-09 11:58:45 -0700301 }
302
303 public PathFragment getGenfilesFragment() {
Googler0617f2c2020-10-22 08:43:54 -0700304 return getConfiguration().getGenfilesFragment(getLabel().getRepository());
Googler4e7b1e52020-10-09 11:58:45 -0700305 }
306
dslomovfd62e762017-09-19 16:55:53 +0200307 @Override
tomlu1cdcdf92018-01-16 11:07:51 -0800308 public ArtifactRoot getMiddlemanDirectory() {
Googler0617f2c2020-10-22 08:43:54 -0700309 return getConfiguration().getMiddlemanDirectory(getLabel().getRepository());
dslomovfd62e762017-09-19 16:55:53 +0200310 }
cparsons88821922017-10-11 01:21:46 +0200311
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100312 public Rule getRule() {
313 return rule;
314 }
315
dslomov44d15712017-12-20 05:42:28 -0800316 public ImmutableList<Aspect> getAspects() {
317 return aspects;
318 }
319
320 /**
jhorvitzb6590822021-08-13 15:18:27 -0700321 * If this target's configuration suppresses analysis failures, this returns a list of strings,
322 * where each string corresponds to a description of an error that occurred during processing this
323 * target.
cparsonse8d450c2018-10-04 16:01:53 -0700324 *
325 * @throws IllegalStateException if this target's configuration does not suppress analysis
326 * failures (if {@code getConfiguration().allowAnalysisFailures()} is false)
327 */
328 public List<String> getSuppressedErrorMessages() {
jhorvitzb6590822021-08-13 15:18:27 -0700329 Preconditions.checkState(
330 getConfiguration().allowAnalysisFailures(),
cparsonse8d450c2018-10-04 16:01:53 -0700331 "Error messages can only be retrieved via RuleContext if allow_analysis_failures is true");
jhorvitzb6590822021-08-13 15:18:27 -0700332 Preconditions.checkState(
333 reporter instanceof SuppressingErrorReporter, "Unexpected error reporter");
cparsonse8d450c2018-10-04 16:01:53 -0700334 return ((SuppressingErrorReporter) reporter).getErrorMessages();
335 }
336
337 /**
jhorvitzb6590822021-08-13 15:18:27 -0700338 * If this <code>RuleContext</code> is for an aspect implementation, returns that aspect. (it is
339 * the last aspect in the list of aspects applied to a target; all other aspects are the ones main
340 * aspect sees as specified by its "required_aspect_providers") Otherwise returns <code>null
341 * </code>.
dslomov44d15712017-12-20 05:42:28 -0800342 */
343 @Nullable
344 public Aspect getMainAspect() {
Googler38349752023-01-11 09:02:30 -0800345 return Streams.findLast(aspects.stream()).orElse(null);
dslomov44d15712017-12-20 05:42:28 -0800346 }
347
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100348 /**
Michael Staib8824d5e2016-01-20 21:37:05 +0000349 * Returns a rule class name suitable for log messages, including an aspect name if applicable.
350 */
351 public String getRuleClassNameForLogging() {
352 return ruleClassNameForLogging;
353 }
354
jhorvitzb6590822021-08-13 15:18:27 -0700355 /** Returns the workspace name for the rule. */
Kristina Chodorow91876f02015-02-27 17:14:12 +0000356 public String getWorkspaceName() {
Googlerf7d370a2021-01-19 08:17:23 -0800357 return rule.getPackage().getWorkspaceName();
Kristina Chodorow91876f02015-02-27 17:14:12 +0000358 }
359
jhorvitzb6590822021-08-13 15:18:27 -0700360 /** The configuration conditions that trigger this rule's configurable attributes. */
gregce593f7f92017-09-19 02:02:21 +0200361 public ImmutableMap<Label, ConfigMatchingProvider> getConfigConditions() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100362 return configConditions;
363 }
364
jhorvitzb6590822021-08-13 15:18:27 -0700365 /** All aspects applied to the rule. */
Dmitry Lomov503c2f72017-02-23 08:55:47 +0000366 public ImmutableList<AspectDescriptor> getAspectDescriptors() {
367 return aspectDescriptors;
368 }
369
370 /**
Greg Estren7f534232016-12-01 21:38:25 +0000371 * Accessor for the attributes of the rule and its aspects.
372 *
373 * <p>The rule's native attributes can be queried both on their structure / existence and values
374 * Aspect attributes can only be queried on their structure.
375 *
376 * <p>This should be the sole interface for reading rule/aspect attributes in {@link RuleContext}.
377 * Don't expose other access points through new public methods.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100378 */
379 public AttributeMap attributes() {
380 return attributes;
381 }
382
cparsons0dcffc52017-10-13 23:40:31 +0200383 @Override
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100384 public boolean hasErrors() {
cparsons146b9ff2019-06-21 09:45:14 -0700385 return reporter.hasErrors();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100386 }
Michajlo Matijkiwe64bfce2016-07-18 14:37:08 +0000387
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100388 /**
389 * Returns an immutable map from attribute name to list of configured targets for that attribute.
390 */
391 public ListMultimap<String, ? extends TransitiveInfoCollection> getConfiguredTargetMap() {
janakr9c101402018-03-10 06:48:59 -0800392 return Multimaps.transformValues(targetMap, ConfiguredTargetAndData::getConfiguredTarget);
janakrf3e6f252018-01-18 07:45:12 -0800393 }
394
janakr65866212018-03-10 22:30:33 -0800395 /**
396 * Returns an immutable map from attribute name to list of {@link ConfiguredTargetAndData} objects
397 * for that attribute.
398 */
399 public ListMultimap<String, ConfiguredTargetAndData> getConfiguredTargetAndDataMap() {
400 return targetMap;
401 }
402
jcater0b8280e2020-08-25 08:23:03 -0700403 /** Returns the {@link ConfiguredTargetAndData} the given attribute. */
404 public List<ConfiguredTargetAndData> getPrerequisiteConfiguredTargets(String attributeName) {
405 return targetMap.get(attributeName);
mjhalupkade47f212018-02-12 12:31:21 -0800406 }
407
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100408 @Override
409 public ActionOwner getActionOwner() {
juliexxiaff580812020-04-30 15:01:09 -0700410 return getActionOwner(DEFAULT_EXEC_GROUP_NAME);
411 }
412
Austin Schuhd1813532023-02-14 22:48:22 -0800413 /**
414 * Returns a special action owner for test actions. Test actions should run on the target platform
415 * rather than the host platform. Note that the value is not cached (on the assumption that this
416 * method is only called once).
417 */
418 public ActionOwner getTestActionOwner() {
419 PlatformInfo testExecutionPlatform;
420 ImmutableMap<String, String> testExecProperties;
421
422 // If we have a toolchain, pull the target platform out of it.
423 if (toolchainContexts != null) {
424 // TODO(https://github.com/bazelbuild/bazel/issues/17466): This doesn't respect execution
425 // properties coming from the target's `exec_properties` attribute.
426 // src/test/java/com/google/devtools/build/lib/analysis/test/TestActionBuilderTest.java has a
427 // test to test for it when it gets figured out.
428 testExecutionPlatform = toolchainContexts.getTargetPlatform();
429 testExecProperties = testExecutionPlatform.execProperties();
430 } else {
431 testExecutionPlatform = null;
432 testExecProperties = getExecGroups().getExecProperties(DEFAULT_TEST_RUNNER_EXEC_GROUP);
433 }
434
435 ActionOwner actionOwner =
436 createActionOwner(
437 rule, aspectDescriptors, getConfiguration(), testExecProperties, testExecutionPlatform);
438
439 if (actionOwner == null) {
440 actionOwner = getActionOwner();
441 }
442 return actionOwner;
443 }
444
juliexxiaff580812020-04-30 15:01:09 -0700445 @Override
juliexxia2c97d382020-06-12 10:16:26 -0700446 @Nullable
juliexxiaff580812020-04-30 15:01:09 -0700447 public ActionOwner getActionOwner(String execGroup) {
448 if (actionOwners.containsKey(execGroup)) {
449 return actionOwners.get(execGroup);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100450 }
juliexxia2c97d382020-06-12 10:16:26 -0700451 if (toolchainContexts != null && !toolchainContexts.hasToolchainContext(execGroup)) {
452 return null;
453 }
juliexxiaff580812020-04-30 15:01:09 -0700454 ActionOwner actionOwner =
455 createActionOwner(
456 rule,
457 aspectDescriptors,
458 getConfiguration(),
jhorvitz04816f52021-08-11 10:51:51 -0700459 execGroupCollection.getExecProperties(execGroup),
jcater645c42b2021-05-12 09:35:48 -0700460 getExecutionPlatform(execGroup));
juliexxiaff580812020-04-30 15:01:09 -0700461 actionOwners.put(execGroup, actionOwner);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100462 return actionOwner;
463 }
464
465 /**
janakreaff19c2019-01-31 13:59:40 -0800466 * An opaque symbol generator to be used when identifying objects by their action owner/index of
467 * creation. Only needed if an object needs to know whether it was created by the same action
468 * owner in the same order as another object. Each symbol must call {@link
469 * SymbolGenerator#generate} separately to obtain a unique object.
470 */
471 public SymbolGenerator<?> getSymbolGenerator() {
472 return actionOwnerSymbolGenerator;
473 }
474
jhorvitzb6590822021-08-13 15:18:27 -0700475 /** Returns a configuration fragment for this this target. */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100476 @Nullable
Googlercba99e32022-12-20 13:33:49 -0800477 public <T extends Fragment> T getFragment(Class<T> fragment) {
478 return getFragment(fragment, fragment.getSimpleName(), "");
Florian Weikertd2a24612015-09-07 14:35:23 +0000479 }
480
481 @Nullable
jhorvitz04816f52021-08-11 10:51:51 -0700482 private <T extends Fragment> T getFragment(
Googlercba99e32022-12-20 13:33:49 -0800483 Class<T> fragment, String name, String additionalErrorMessage) {
jhorvitz33f76482021-10-28 10:13:26 -0700484 // TODO(bazel-team): The fragments can also be accessed directly through
485 // BuildConfigurationValue. Can we lock that down somehow?
jhorvitz04816f52021-08-11 10:51:51 -0700486 Preconditions.checkArgument(
Googlercba99e32022-12-20 13:33:49 -0800487 isLegalFragment(fragment),
488 "%s has to declare '%s' as a required fragment in order to access it.%s",
jhorvitz04816f52021-08-11 10:51:51 -0700489 ruleClassNameForLogging,
490 name,
Florian Weikertd2a24612015-09-07 14:35:23 +0000491 additionalErrorMessage);
Googlercba99e32022-12-20 13:33:49 -0800492 return getConfiguration().getFragment(fragment);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100493 }
494
Florian Weikert082c0542015-08-06 10:24:29 +0000495 @Nullable
Googlercba99e32022-12-20 13:33:49 -0800496 public Fragment getStarlarkFragment(String name) throws EvalException {
497 Class<? extends Fragment> fragmentClass = getConfiguration().getStarlarkFragmentByName(name);
Florian Weikertd2a24612015-09-07 14:35:23 +0000498 if (fragmentClass == null) {
499 return null;
500 }
adonovanb8eae2d2019-12-09 15:11:06 -0800501 try {
502 return getFragment(
503 fragmentClass,
504 name,
505 String.format(
Googlercba99e32022-12-20 13:33:49 -0800506 " Please update the 'fragments' argument of the rule definition "
507 + "(for example: fragments = [\"%1$s\"])",
508 name));
adonovanb8eae2d2019-12-09 15:11:06 -0800509 } catch (IllegalArgumentException ex) { // fishy
adonovana6287362020-08-07 07:15:30 -0700510 throw new EvalException(ex.getMessage());
adonovanb8eae2d2019-12-09 15:11:06 -0800511 }
Florian Weikert3f8aac92015-09-07 12:06:02 +0000512 }
513
Googlercba99e32022-12-20 13:33:49 -0800514 public ImmutableCollection<String> getStarlarkFragmentNames() {
515 return getConfiguration().getStarlarkFragmentNames();
Florian Weikert082c0542015-08-06 10:24:29 +0000516 }
517
Ulf Adamsea11fc52015-08-04 14:23:58 +0000518 public <T extends Fragment> boolean isLegalFragment(Class<T> fragment) {
Googlercba99e32022-12-20 13:33:49 -0800519 return ruleClassProvider.getFragmentRegistry().getUniversalFragments().contains(fragment)
520 || configurationFragmentPolicy.isLegalConfigurationFragment(fragment);
Ulf Adamsea11fc52015-08-04 14:23:58 +0000521 }
522
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100523 @Override
jhorvitz3daedc32020-07-22 18:33:55 -0700524 public ActionLookupKey getOwner() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100525 return getAnalysisEnvironment().getOwner();
526 }
527
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000528 public ImmutableList<Artifact> getBuildInfo(BuildInfoKey key) throws InterruptedException {
plf1f341a62019-04-01 14:02:14 -0700529 return getAnalysisEnvironment()
530 .getBuildInfo(
531 AnalysisUtils.isStampingEnabled(this, getConfiguration()), key, getConfiguration());
Ulf Adamsc272e0f2015-04-22 19:56:21 +0000532 }
533
Janak Ramakrishnan7857c792016-03-21 08:35:35 +0000534 @VisibleForTesting
Carmi Grushko33aa3062016-11-11 02:45:29 +0000535 public static ActionOwner createActionOwner(
536 Rule rule,
Dmitry Lomov15756522016-12-16 16:52:37 +0000537 ImmutableList<AspectDescriptor> aspectDescriptors,
jhorvitz33f76482021-10-28 10:13:26 -0700538 BuildConfigurationValue configuration,
jcater645c42b2021-05-12 09:35:48 -0700539 ImmutableMap<String, String> execProperties,
540 @Nullable PlatformInfo executionPlatform) {
Carmi Grushko4665e702016-11-09 21:51:27 +0000541 return ActionOwner.create(
Janak Ramakrishnan7857c792016-03-21 08:35:35 +0000542 rule.getLabel(),
Dmitry Lomov15756522016-12-16 16:52:37 +0000543 aspectDescriptors,
Janak Ramakrishnan7857c792016-03-21 08:35:35 +0000544 rule.getLocation(),
545 configuration.getMnemonic(),
546 rule.getTargetKind(),
547 configuration.checksum(),
shahan50f99d52018-03-10 05:14:09 -0800548 configuration.toBuildEvent(),
ilist67c99362022-01-04 02:39:00 -0800549 configuration.isToolConfiguration() ? TOOL_CONFIGURATION_PROGRESS_TAG : null,
jcater645c42b2021-05-12 09:35:48 -0700550 execProperties,
John Caterec5d2ed2018-01-04 11:52:21 -0800551 executionPlatform);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100552 }
553
554 @Override
janakrd4591972021-04-14 08:37:06 -0700555 public void registerAction(ActionAnalysisMetadata action) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100556 getAnalysisEnvironment().registerAction(action);
557 }
558
559 /**
jhorvitzb6590822021-08-13 15:18:27 -0700560 * Convenience function for subclasses to report non-attribute-specific errors in the current
561 * rule.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100562 */
563 @Override
564 public void ruleError(String message) {
Florian Weikertb8a6a942015-09-25 12:36:08 +0000565 reporter.ruleError(message);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100566 }
Michajlo Matijkiwe64bfce2016-07-18 14:37:08 +0000567
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100568 /**
jhorvitzb6590822021-08-13 15:18:27 -0700569 * Convenience function for subclasses to report non-attribute-specific warnings in the current
570 * rule.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100571 */
572 @Override
573 public void ruleWarning(String message) {
Florian Weikertb8a6a942015-09-25 12:36:08 +0000574 reporter.ruleWarning(message);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100575 }
576
577 /**
jhorvitzb6590822021-08-13 15:18:27 -0700578 * Convenience function for subclasses to report attribute-specific errors in the current rule.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100579 *
jhorvitzb6590822021-08-13 15:18:27 -0700580 * <p>If the name of the attribute starts with <code>$</code> it is replaced with a string <code>
581 * (an implicit dependency)</code>.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100582 */
583 @Override
584 public void attributeError(String attrName, String message) {
Florian Weikertb8a6a942015-09-25 12:36:08 +0000585 reporter.attributeError(attrName, message);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100586 }
587
Chris Parsons4dfb22c2016-05-23 17:39:42 +0000588 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100589 * Like attributeError, but does not mark the configured target as errored.
590 *
jhorvitzb6590822021-08-13 15:18:27 -0700591 * <p>If the name of the attribute starts with <code>$</code> it is replaced with a string <code>
592 * (an implicit dependency)</code>.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100593 */
594 @Override
595 public void attributeWarning(String attrName, String message) {
Florian Weikertb8a6a942015-09-25 12:36:08 +0000596 reporter.attributeWarning(attrName, message);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100597 }
598
599 /**
jhorvitzb6590822021-08-13 15:18:27 -0700600 * Returns an artifact beneath the root of either the "bin" or "genfiles" tree, whose path is
601 * based on the name of this target and the current configuration. The choice of which tree to use
602 * is based on the rule with which this target (which must be an OutputFile or a Rule) is
603 * associated.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100604 */
605 public Artifact createOutputArtifact() {
cparsons0623d3c2018-10-23 16:06:30 -0700606 Target target = getTarget();
jhorvitzb6590822021-08-13 15:18:27 -0700607 PathFragment rootRelativePath =
608 getPackageDirectory().getRelative(PathFragment.create(target.getName()));
cparsons0623d3c2018-10-23 16:06:30 -0700609
610 return internalCreateOutputArtifact(rootRelativePath, target, OutputFile.Kind.FILE);
611 }
612
613 /**
Googlerbf155342022-06-24 11:17:23 -0700614 * Returns the output artifact of an {@link OutputFile} of this target.
615 *
616 * @see #createOutputArtifact()
617 */
618 public Artifact createOutputArtifact(OutputFile out) {
619 PathFragment packageRelativePath =
620 getPackageDirectory().getRelative(PathFragment.create(out.getName()));
621 return internalCreateOutputArtifact(packageRelativePath, out, out.getKind());
622 }
623
624 /**
jhorvitzb6590822021-08-13 15:18:27 -0700625 * Returns an artifact beneath the root of either the "bin" or "genfiles" tree, whose path is
626 * based on the name of this target and the current configuration, with a script suffix
627 * appropriate for the current host platform. ({@code .cmd} for Windows, otherwise {@code .sh}).
628 * The choice of which tree to use is based on the rule with which this target (which must be an
629 * OutputFile or a Rule) is associated.
cparsons0623d3c2018-10-23 16:06:30 -0700630 */
631 public Artifact createOutputArtifactScript() {
632 Target target = getTarget();
633 // TODO(laszlocsomor): Use the execution platform, not the host platform.
634 boolean isExecutedOnWindows = OS.getCurrent() == OS.WINDOWS;
635
636 String fileExtension = isExecutedOnWindows ? ".cmd" : ".sh";
637
jhorvitzb6590822021-08-13 15:18:27 -0700638 PathFragment rootRelativePath =
639 getPackageDirectory().getRelative(PathFragment.create(target.getName() + fileExtension));
cparsons0623d3c2018-10-23 16:06:30 -0700640
641 return internalCreateOutputArtifact(rootRelativePath, target, OutputFile.Kind.FILE);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100642 }
643
644 /**
jhorvitzb6590822021-08-13 15:18:27 -0700645 * Implementation for {@link #createOutputArtifact()} and {@link
646 * #createOutputArtifact(OutputFile)}. This is private so that {@link
647 * #createOutputArtifact(OutputFile)} can have a more specific signature.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100648 */
jhorvitzb6590822021-08-13 15:18:27 -0700649 private Artifact internalCreateOutputArtifact(
650 PathFragment rootRelativePath, Target target, OutputFile.Kind outputFileKind) {
Lukacs Berki4a89a9b2015-07-29 06:54:07 +0000651 Preconditions.checkState(
652 target.getLabel().getPackageIdentifier().equals(getLabel().getPackageIdentifier()),
653 "Creating output artifact for target '%s' in different package than the rule '%s' "
jhorvitzb6590822021-08-13 15:18:27 -0700654 + "being analyzed",
655 target.getLabel(),
656 getLabel());
tomlu1cdcdf92018-01-16 11:07:51 -0800657 ArtifactRoot root = getBinOrGenfilesDirectory();
cparsons0623d3c2018-10-23 16:06:30 -0700658
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -0700659 switch (outputFileKind) {
660 case FILE:
cparsons0623d3c2018-10-23 16:06:30 -0700661 return getDerivedArtifact(rootRelativePath, root);
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -0700662 case FILESET:
cparsons0623d3c2018-10-23 16:06:30 -0700663 return getAnalysisEnvironment().getFilesetArtifact(rootRelativePath, root);
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -0700664 default:
665 throw new IllegalStateException();
666 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100667 }
668
669 /**
tomlu1cdcdf92018-01-16 11:07:51 -0800670 * Returns the root of either the "bin" or "genfiles" tree, based on this target and the current
671 * configuration. The choice of which tree to use is based on the rule with which this target
672 * (which must be an OutputFile or a Rule) is associated.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100673 */
David Ostrovskya1388772020-07-08 12:11:01 -0700674 @Override
tomlu1cdcdf92018-01-16 11:07:51 -0800675 public ArtifactRoot getBinOrGenfilesDirectory() {
Googler482c26d2021-05-18 08:29:51 -0700676 return rule.outputsToBindir()
Googler0617f2c2020-10-22 08:43:54 -0700677 ? getConfiguration().getBinDirectory(getLabel().getRepository())
678 : getConfiguration().getGenfilesDirectory(getLabel().getRepository());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100679 }
680
Lukacs Berki4a89a9b2015-07-29 06:54:07 +0000681 /**
tomlu1cdcdf92018-01-16 11:07:51 -0800682 * Creates an artifact in a directory that is unique to the package that contains the rule, thus
683 * guaranteeing that it never clashes with artifacts created by rules in other packages.
Lukacs Berki4a89a9b2015-07-29 06:54:07 +0000684 */
Carmi Grushkof414b4e2016-06-23 20:35:27 +0000685 public Artifact getBinArtifact(String relative) {
nharmatab4060b62017-04-04 17:11:39 +0000686 return getBinArtifact(PathFragment.create(relative));
Kristina Chodorowf8a1ae62016-08-11 14:44:40 +0000687 }
688
689 public Artifact getBinArtifact(PathFragment relative) {
Carmi Grushkof414b4e2016-06-23 20:35:27 +0000690 return getPackageRelativeArtifact(
Googler0617f2c2020-10-22 08:43:54 -0700691 relative, getConfiguration().getBinDirectory(getLabel().getRepository()));
Carmi Grushkof414b4e2016-06-23 20:35:27 +0000692 }
693
694 /**
695 * Creates an artifact in a directory that is unique to the package that contains the rule, thus
696 * guaranteeing that it never clashes with artifacts created by rules in other packages.
697 */
698 public Artifact getGenfilesArtifact(String relative) {
nharmatab4060b62017-04-04 17:11:39 +0000699 return getGenfilesArtifact(PathFragment.create(relative));
Kristina Chodorowf8a1ae62016-08-11 14:44:40 +0000700 }
701
702 public Artifact getGenfilesArtifact(PathFragment relative) {
Carmi Grushkof414b4e2016-06-23 20:35:27 +0000703 return getPackageRelativeArtifact(
Googler0617f2c2020-10-22 08:43:54 -0700704 relative, getConfiguration().getGenfilesDirectory(getLabel().getRepository()));
Carmi Grushkof414b4e2016-06-23 20:35:27 +0000705 }
706
plfb74df042018-10-31 02:15:10 -0700707 @Override
tomlu1cdcdf92018-01-16 11:07:51 -0800708 public Artifact getShareableArtifact(PathFragment rootRelativePath, ArtifactRoot root) {
Lukacs Berki21a04f22015-08-20 13:31:24 +0000709 return getAnalysisEnvironment().getDerivedArtifact(rootRelativePath, root);
710 }
711
asteinb0de45462018-05-17 08:07:12 -0700712 @Override
janakr658d47f2019-05-29 11:11:30 -0700713 public Artifact.DerivedArtifact getPackageRelativeArtifact(
714 PathFragment relative, ArtifactRoot root) {
Googler38349752023-01-11 09:02:30 -0800715 return getPackageRelativeArtifact(relative, root, /* contentBasedPath= */ false);
gregce11f3b0e2019-06-07 17:12:06 -0700716 }
717
718 /**
719 * Same as {@link #getPackageRelativeArtifact(PathFragment, ArtifactRoot)} but includes the option
720 * option to use a content-based path for this artifact (see {@link
jhorvitz33f76482021-10-28 10:13:26 -0700721 * BuildConfigurationValue#useContentBasedOutputPaths()}).
gregce11f3b0e2019-06-07 17:12:06 -0700722 */
723 private Artifact.DerivedArtifact getPackageRelativeArtifact(
724 PathFragment relative, ArtifactRoot root, boolean contentBasedPath) {
725 return getDerivedArtifact(getPackageDirectory().getRelative(relative), root, contentBasedPath);
Lukacs Berki4a89a9b2015-07-29 06:54:07 +0000726 }
727
janakr658d47f2019-05-29 11:11:30 -0700728 /**
729 * Creates an artifact in a directory that is unique to the package that contains the rule, thus
730 * guaranteeing that it never clashes with artifacts created by rules in other packages.
731 */
732 public Artifact getPackageRelativeArtifact(String relative, ArtifactRoot root) {
Googler38349752023-01-11 09:02:30 -0800733 return getPackageRelativeArtifact(relative, root, /* contentBasedPath= */ false);
gregce11f3b0e2019-06-07 17:12:06 -0700734 }
735
736 /**
737 * Same as {@link #getPackageRelativeArtifact(String, ArtifactRoot)} but includes the option to
738 * use a content-based path for this artifact (see {@link
jhorvitz33f76482021-10-28 10:13:26 -0700739 * BuildConfigurationValue#useContentBasedOutputPaths()}).
gregce11f3b0e2019-06-07 17:12:06 -0700740 */
741 private Artifact getPackageRelativeArtifact(
742 String relative, ArtifactRoot root, boolean contentBasedPath) {
743 return getPackageRelativeArtifact(PathFragment.create(relative), root, contentBasedPath);
janakr658d47f2019-05-29 11:11:30 -0700744 }
745
asteinb0de45462018-05-17 08:07:12 -0700746 @Override
Lukacs Berki4a89a9b2015-07-29 06:54:07 +0000747 public PathFragment getPackageDirectory() {
Googler00217002020-10-27 06:41:26 -0700748 return getLabel()
749 .getPackageIdentifier()
750 .getPackagePath(getConfiguration().isSiblingRepositoryLayout());
Lukacs Berki4a89a9b2015-07-29 06:54:07 +0000751 }
752
753 /**
754 * Creates an artifact under a given root with the given root-relative path.
755 *
756 * <p>Verifies that it is in the root-relative directory corresponding to the package of the rule,
757 * thus ensuring that it doesn't clash with other artifacts generated by other rules using this
758 * method.
759 */
Ulf Adams3ab82f72015-09-04 12:10:53 +0000760 @Override
janakr658d47f2019-05-29 11:11:30 -0700761 public Artifact.DerivedArtifact getDerivedArtifact(
762 PathFragment rootRelativePath, ArtifactRoot root) {
Googler38349752023-01-11 09:02:30 -0800763 return getDerivedArtifact(rootRelativePath, root, /* contentBasedPath= */ false);
gregce11f3b0e2019-06-07 17:12:06 -0700764 }
765
766 /**
767 * Same as {@link #getDerivedArtifact(PathFragment, ArtifactRoot)} but includes the option to use
768 * a content-based path for this artifact (see {@link
jhorvitz33f76482021-10-28 10:13:26 -0700769 * BuildConfigurationValue#useContentBasedOutputPaths()}).
gregce11f3b0e2019-06-07 17:12:06 -0700770 */
771 public Artifact.DerivedArtifact getDerivedArtifact(
772 PathFragment rootRelativePath, ArtifactRoot root, boolean contentBasedPath) {
jhorvitzb6590822021-08-13 15:18:27 -0700773 Preconditions.checkState(
774 rootRelativePath.startsWith(getPackageDirectory()),
Lukacs Berki4a89a9b2015-07-29 06:54:07 +0000775 "Output artifact '%s' not under package directory '%s' for target '%s'",
jhorvitzb6590822021-08-13 15:18:27 -0700776 rootRelativePath,
777 getPackageDirectory(),
778 getLabel());
gregce11f3b0e2019-06-07 17:12:06 -0700779 return getAnalysisEnvironment().getDerivedArtifact(rootRelativePath, root, contentBasedPath);
Lukacs Berki4a89a9b2015-07-29 06:54:07 +0000780 }
Michael Thvedte3b1cb72016-02-08 23:32:27 +0000781
plf441fd752019-02-06 01:28:18 -0800782 @Override
cpeyserac09f0a2018-02-05 09:33:15 -0800783 public SpecialArtifact getTreeArtifact(PathFragment rootRelativePath, ArtifactRoot root) {
jhorvitzb6590822021-08-13 15:18:27 -0700784 Preconditions.checkState(
785 rootRelativePath.startsWith(getPackageDirectory()),
Michael Thvedte3b1cb72016-02-08 23:32:27 +0000786 "Output artifact '%s' not under package directory '%s' for target '%s'",
jhorvitzb6590822021-08-13 15:18:27 -0700787 rootRelativePath,
788 getPackageDirectory(),
789 getLabel());
Michael Thvedte3b1cb72016-02-08 23:32:27 +0000790 return getAnalysisEnvironment().getTreeArtifact(rootRelativePath, root);
791 }
792
Lukacs Berki4a89a9b2015-07-29 06:54:07 +0000793 /**
allevato060a4482017-03-30 20:45:52 +0000794 * Creates a tree artifact in a directory that is unique to the package that contains the rule,
795 * thus guaranteeing that it never clashes with artifacts created by rules in other packages.
796 */
tomlu1cdcdf92018-01-16 11:07:51 -0800797 public Artifact getPackageRelativeTreeArtifact(PathFragment relative, ArtifactRoot root) {
allevato060a4482017-03-30 20:45:52 +0000798 return getTreeArtifact(getPackageDirectory().getRelative(relative), root);
799 }
800
801 /**
Lukacs Berki4a89a9b2015-07-29 06:54:07 +0000802 * Creates an artifact in a directory that is unique to the rule, thus guaranteeing that it never
803 * clashes with artifacts created by other rules.
804 */
805 public Artifact getUniqueDirectoryArtifact(
tomlu1cdcdf92018-01-16 11:07:51 -0800806 String uniqueDirectory, String relative, ArtifactRoot root) {
nharmatab4060b62017-04-04 17:11:39 +0000807 return getUniqueDirectoryArtifact(uniqueDirectory, PathFragment.create(relative), root);
Lukacs Berki4a89a9b2015-07-29 06:54:07 +0000808 }
809
asteinb0de45462018-05-17 08:07:12 -0700810 @Override
811 public Artifact getUniqueDirectoryArtifact(String uniqueDirectorySuffix, String relative) {
812 return getUniqueDirectoryArtifact(uniqueDirectorySuffix, relative, getBinOrGenfilesDirectory());
813 }
814
ahumesky4b00ab12018-11-15 16:23:46 -0800815 @Override
816 public Artifact getUniqueDirectoryArtifact(String uniqueDirectorySuffix, PathFragment relative) {
817 return getUniqueDirectoryArtifact(uniqueDirectorySuffix, relative, getBinOrGenfilesDirectory());
818 }
819
plf727a07d2019-02-01 02:27:35 -0800820 @Override
Lukacs Berki4a89a9b2015-07-29 06:54:07 +0000821 public Artifact getUniqueDirectoryArtifact(
tomlu1cdcdf92018-01-16 11:07:51 -0800822 String uniqueDirectory, PathFragment relative, ArtifactRoot root) {
Lukacs Berki4a89a9b2015-07-29 06:54:07 +0000823 return getDerivedArtifact(getUniqueDirectory(uniqueDirectory).getRelative(relative), root);
824 }
825
Googler03083852015-12-06 18:31:53 +0000826 /**
Carmi Grushko8e589dc2016-12-01 02:28:42 +0000827 * Returns true iff the rule, or any attached aspect, has an attribute with the given name and
828 * type.
829 */
830 public boolean isAttrDefined(String attrName, Type<?> type) {
Greg Estren7f534232016-12-01 21:38:25 +0000831 return attributes().has(attrName, type);
Carmi Grushko8e589dc2016-12-01 02:28:42 +0000832 }
833
834 /**
jhorvitzb6590822021-08-13 15:18:27 -0700835 * Returns the dependencies through a {@code LABEL_DICT_UNARY} attribute as a map from a string to
836 * a {@link TransitiveInfoCollection}.
Lukacs Berki8bdae762016-07-13 14:58:54 +0000837 */
838 public Map<String, TransitiveInfoCollection> getPrerequisiteMap(String attributeName) {
Greg Estren7f534232016-12-01 21:38:25 +0000839 Preconditions.checkState(attributes().has(attributeName, BuildType.LABEL_DICT_UNARY));
Lukacs Berki8bdae762016-07-13 14:58:54 +0000840
841 ImmutableMap.Builder<String, TransitiveInfoCollection> result = ImmutableMap.builder();
842 Map<String, Label> dict = attributes().get(attributeName, BuildType.LABEL_DICT_UNARY);
843 Map<Label, ConfiguredTarget> labelToDep = new HashMap<>();
janakr9c101402018-03-10 06:48:59 -0800844 for (ConfiguredTargetAndData dep : targetMap.get(attributeName)) {
Googlerf5924702022-12-08 14:55:42 -0800845 labelToDep.put(dep.getTargetLabel(), dep.getConfiguredTarget());
Lukacs Berki8bdae762016-07-13 14:58:54 +0000846 }
847
848 for (Map.Entry<String, Label> entry : dict.entrySet()) {
849 result.put(entry.getKey(), Preconditions.checkNotNull(labelToDep.get(entry.getValue())));
850 }
851
Googler92ce1152022-02-01 06:37:06 -0800852 return result.buildOrThrow();
Lukacs Berki8bdae762016-07-13 14:58:54 +0000853 }
854
855 /**
Googler46b285a2020-03-06 13:33:24 -0800856 * Returns the prerequisites keyed by their configuration transition keys. If the split transition
mjhalupkade47f212018-02-12 12:31:21 -0800857 * is not active (e.g. split() returned an empty list), the key is an empty Optional.
858 */
859 public Map<Optional<String>, ? extends List<? extends TransitiveInfoCollection>>
860 getSplitPrerequisites(String attributeName) {
861 return Maps.transformValues(
862 getSplitPrerequisiteConfiguredTargetAndTargets(attributeName),
janakr9c101402018-03-10 06:48:59 -0800863 (ctatList) -> Lists.transform(ctatList, ConfiguredTargetAndData::getConfiguredTarget));
mjhalupkade47f212018-02-12 12:31:21 -0800864 }
865
866 /**
Googler46b285a2020-03-06 13:33:24 -0800867 * Returns the prerequisites keyed by their transition keys. If the split transition is not active
868 * (e.g. split() returned an empty list), the key is an empty Optional.
janakr0758d352018-03-10 20:38:45 -0800869 */
870 public Map<Optional<String>, List<ConfiguredTargetAndData>>
mjhalupkade47f212018-02-12 12:31:21 -0800871 getSplitPrerequisiteConfiguredTargetAndTargets(String attributeName) {
jcater7ba83102020-09-10 11:05:29 -0700872 checkAttributeIsDependency(attributeName);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100873 // Use an ImmutableListMultimap.Builder here to preserve ordering.
janakr9c101402018-03-10 06:48:59 -0800874 ImmutableListMultimap.Builder<Optional<String>, ConfiguredTargetAndData> result =
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100875 ImmutableListMultimap.builder();
jcater0b8280e2020-08-25 08:23:03 -0700876 List<ConfiguredTargetAndData> deps = getPrerequisiteConfiguredTargets(attributeName);
janakr9c101402018-03-10 06:48:59 -0800877 for (ConfiguredTargetAndData t : deps) {
Googler3cc6cc32020-04-29 10:50:38 -0700878 ImmutableList<String> transitionKeys = t.getTransitionKeys();
879 if (transitionKeys.isEmpty()) {
880 // The split transition is not active, i.e. does not change build configurations.
Googlerfb55091b2020-09-29 20:41:18 -0700881 // TODO(jungjw): Investigate if we need to do a check here.
Googler3cc6cc32020-04-29 10:50:38 -0700882 return ImmutableMap.of(Optional.absent(), deps);
883 }
884 for (String key : transitionKeys) {
885 result.put(Optional.of(key), t);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100886 }
887 }
888 return Multimaps.asMap(result.build());
889 }
890
891 /**
jcaterf7d726f2020-04-13 10:34:54 -0700892 * Returns the specified provider of the prerequisite referenced by the attribute in the argument.
jcater3a9532d2020-08-26 06:09:28 -0700893 * If the attribute is empty or it does not support the specified provider, returns null.
894 */
jcater7ba83102020-09-10 11:05:29 -0700895 @Nullable
jcater3a9532d2020-08-26 06:09:28 -0700896 public <C extends TransitiveInfoProvider> C getPrerequisite(
897 String attributeName, Class<C> provider) {
jcater7ba83102020-09-10 11:05:29 -0700898 TransitiveInfoCollection prerequisite = getPrerequisite(attributeName);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100899 return prerequisite == null ? null : prerequisite.getProvider(provider);
900 }
901
902 /**
903 * Returns the transitive info collection that feeds into this target through the specified
jcater3a9532d2020-08-26 06:09:28 -0700904 * attribute. Returns null if the attribute is empty.
905 */
jcater7ba83102020-09-10 11:05:29 -0700906 @Nullable
907 public TransitiveInfoCollection getPrerequisite(String attributeName) {
908 ConfiguredTargetAndData result = getPrerequisiteConfiguredTargetAndData(attributeName);
janakr27bb6dd2018-03-10 19:10:00 -0800909 return result == null ? null : result.getConfiguredTarget();
910 }
911
912 /**
Googlerbf155342022-06-24 11:17:23 -0700913 * Returns the declared provider (native and Starlark) for the specified constructor under the
914 * specified attribute of this target in the BUILD file. May return null if there is no
915 * TransitiveInfoCollection under the specified attribute.
916 */
917 @Nullable
918 public <T extends Info> T getPrerequisite(String attributeName, BuiltinProvider<T> starlarkKey) {
919 TransitiveInfoCollection prerequisite = getPrerequisite(attributeName);
920 return prerequisite == null ? null : prerequisite.get(starlarkKey);
921 }
922
923 /**
janakr27bb6dd2018-03-10 19:10:00 -0800924 * Returns the {@link ConfiguredTargetAndData} that feeds ino this target through the specified
jcater3a9532d2020-08-26 06:09:28 -0700925 * attribute. Returns null if the attribute is empty.
926 */
jcater7ba83102020-09-10 11:05:29 -0700927 @Nullable
jcater3a9532d2020-08-26 06:09:28 -0700928 public ConfiguredTargetAndData getPrerequisiteConfiguredTargetAndData(String attributeName) {
jcater7ba83102020-09-10 11:05:29 -0700929 checkAttributeIsDependency(attributeName);
jcater0b8280e2020-08-25 08:23:03 -0700930 List<ConfiguredTargetAndData> elements = getPrerequisiteConfiguredTargets(attributeName);
jhorvitz04816f52021-08-11 10:51:51 -0700931 Preconditions.checkState(
932 elements.size() <= 1,
933 "%s attribute %s produces more than one prerequisite",
934 ruleClassNameForLogging,
935 attributeName);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100936 return elements.isEmpty() ? null : elements.get(0);
937 }
938
939 /**
dslomovde965ac2017-07-31 21:07:51 +0200940 * For a given attribute, returns all declared provider provided by targets of that attribute.
jhorvitz33f76482021-10-28 10:13:26 -0700941 * Each declared provider is keyed by the {@link BuildConfigurationValue} under which the provider
942 * was created.
dslomov4e9fa192017-07-12 14:59:07 +0200943 */
dslomovde965ac2017-07-31 21:07:51 +0200944 public <C extends Info>
jhorvitz33f76482021-10-28 10:13:26 -0700945 ImmutableListMultimap<BuildConfigurationValue, C> getPrerequisitesByConfiguration(
jcater3a9532d2020-08-26 06:09:28 -0700946 String attributeName, BuiltinProvider<C> provider) {
jcater7ba83102020-09-10 11:05:29 -0700947 checkAttributeIsDependency(attributeName);
jcaterb979f6e2020-08-25 08:54:38 -0700948 List<ConfiguredTargetAndData> ctatCollection = getPrerequisiteConfiguredTargets(attributeName);
jhorvitz33f76482021-10-28 10:13:26 -0700949 ImmutableListMultimap.Builder<BuildConfigurationValue, C> result =
950 ImmutableListMultimap.builder();
jcaterb979f6e2020-08-25 08:54:38 -0700951 for (ConfiguredTargetAndData prerequisite : ctatCollection) {
janakr12b78fe2018-03-10 18:06:56 -0800952 C prerequisiteProvider = prerequisite.getConfiguredTarget().get(provider);
dslomov4e9fa192017-07-12 14:59:07 +0200953 if (prerequisiteProvider != null) {
954 result.put(prerequisite.getConfiguration(), prerequisiteProvider);
955 }
956 }
957 return result.build();
958 }
959
960 /**
cparsonsb35c0a42018-08-20 11:37:41 -0700961 * Returns the list of transitive info collections that feed into this target through the
jcater3a9532d2020-08-26 06:09:28 -0700962 * specified attribute.
963 */
964 public List<? extends TransitiveInfoCollection> getPrerequisites(String attributeName) {
jcater1ae143b2020-09-10 11:38:09 -0700965 if (!attributes().has(attributeName)) {
966 return ImmutableList.of();
967 }
968
969 List<ConfiguredTargetAndData> prerequisiteConfiguredTargets;
Googler09cd1fc2021-04-05 17:57:11 -0700970 // android_binary, android_test, and android_binary_internal override deps to use a split
971 // transition.
jhorvitz04816f52021-08-11 10:51:51 -0700972 if ((rule.getRuleClass().equals("android_binary")
973 || rule.getRuleClass().equals("android_test")
974 || rule.getRuleClass().equals("android_binary_internal"))
jcater1ae143b2020-09-10 11:38:09 -0700975 && attributeName.equals("deps")
976 && attributes().getAttributeDefinition(attributeName).getTransitionFactory().isSplit()) {
977 // TODO(b/168038145): Restore legacy behavior of returning the prerequisites from the first
978 // portion of the split transition.
979 // Callers should be identified, cleaned up, and this check removed.
980 Map<Optional<String>, List<ConfiguredTargetAndData>> map =
981 getSplitPrerequisiteConfiguredTargetAndTargets(attributeName);
982 prerequisiteConfiguredTargets =
983 map.isEmpty() ? ImmutableList.of() : map.entrySet().iterator().next().getValue();
984 } else {
985 prerequisiteConfiguredTargets = getPrerequisiteConfiguredTargets(attributeName);
986 }
987
cparsonsb35c0a42018-08-20 11:37:41 -0700988 return Lists.transform(
jcater1ae143b2020-09-10 11:38:09 -0700989 prerequisiteConfiguredTargets, ConfiguredTargetAndData::getConfiguredTarget);
cparsonsb35c0a42018-08-20 11:37:41 -0700990 }
991
992 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100993 * Returns all the providers of the specified type that are listed under the specified attribute
994 * of this target in the BUILD file.
995 */
ulfjack6c3908c2019-12-18 05:03:36 -0800996 public <C extends TransitiveInfoProvider> List<C> getPrerequisites(
jcater3a9532d2020-08-26 06:09:28 -0700997 String attributeName, Class<C> classType) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100998 AnalysisUtils.checkProvider(classType);
jcater7ba83102020-09-10 11:05:29 -0700999 return AnalysisUtils.getProviders(getPrerequisites(attributeName), classType);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001000 }
1001
1002 /**
gregceca48e9a2020-04-14 08:54:38 -07001003 * Returns all the declared providers (native and Starlark) for the specified constructor under
1004 * the specified attribute of this target in the BUILD file.
Sergio Campamafd931432016-12-09 21:47:35 +00001005 */
ulfjack6c3908c2019-12-18 05:03:36 -08001006 public <T extends Info> List<T> getPrerequisites(
jcater3a9532d2020-08-26 06:09:28 -07001007 String attributeName, BuiltinProvider<T> starlarkKey) {
jcater7ba83102020-09-10 11:05:29 -07001008 return AnalysisUtils.getProviders(getPrerequisites(attributeName), starlarkKey);
cparsons2d67cf92018-05-24 14:02:09 -07001009 }
cparsonsabeb8512018-06-11 12:44:06 -07001010 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001011 * Returns all the providers of the specified type that are listed under the specified attribute
1012 * of this target in the BUILD file, and that contain the specified provider.
1013 */
jcaterf7d726f2020-04-13 10:34:54 -07001014 public <C extends TransitiveInfoProvider>
1015 Iterable<? extends TransitiveInfoCollection> getPrerequisitesIf(
jcater3a9532d2020-08-26 06:09:28 -07001016 String attributeName, Class<C> classType) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001017 AnalysisUtils.checkProvider(classType);
jcater7ba83102020-09-10 11:05:29 -07001018 return AnalysisUtils.filterByProvider(getPrerequisites(attributeName), classType);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001019 }
1020
1021 /**
dslomov73527c32017-07-27 17:35:46 +02001022 * Returns all the providers of the specified type that are listed under the specified attribute
1023 * of this target in the BUILD file, and that contain the specified provider.
1024 */
dslomovde965ac2017-07-31 21:07:51 +02001025 public <C extends Info> Iterable<? extends TransitiveInfoCollection> getPrerequisitesIf(
jcater3a9532d2020-08-26 06:09:28 -07001026 String attributeName, BuiltinProvider<C> classType) {
jcater7ba83102020-09-10 11:05:29 -07001027 return AnalysisUtils.filterByProvider(getPrerequisites(attributeName), classType);
Googler7ac77232019-06-04 14:26:47 -07001028 }
1029
1030 /**
jcaterf7d726f2020-04-13 10:34:54 -07001031 * Returns the prerequisite referred to by the specified attribute. Also checks whether the
1032 * attribute is marked as executable and that the target referred to can actually be executed.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001033 *
jcater3a9532d2020-08-26 06:09:28 -07001034 * @param attributeName the name of the attribute
1035 * @return the {@link FilesToRunProvider} interface of the prerequisite.
1036 */
1037 @Nullable
1038 public FilesToRunProvider getExecutablePrerequisite(String attributeName) {
Greg Estren7f534232016-12-01 21:38:25 +00001039 Attribute ruleDefinition = attributes().getAttributeDefinition(attributeName);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001040
jhorvitz04816f52021-08-11 10:51:51 -07001041 Preconditions.checkNotNull(
1042 ruleDefinition, "%s attribute %s is not defined", ruleClassNameForLogging, attributeName);
1043 Preconditions.checkState(
1044 ruleDefinition.isExecutable(),
1045 "%s attribute %s is not configured to be executable",
1046 ruleClassNameForLogging,
1047 attributeName);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001048
jcater7ba83102020-09-10 11:05:29 -07001049 TransitiveInfoCollection prerequisite = getPrerequisite(attributeName);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001050 if (prerequisite == null) {
1051 return null;
1052 }
1053
1054 FilesToRunProvider result = prerequisite.getProvider(FilesToRunProvider.class);
1055 if (result == null || result.getExecutable() == null) {
1056 attributeError(
1057 attributeName, prerequisite.getLabel() + " does not refer to a valid executable target");
1058 }
1059 return result;
1060 }
1061
ulfjack08ff9b82017-09-28 04:08:06 -04001062 public void initConfigurationMakeVariableContext(
1063 Iterable<? extends MakeVariableSupplier> makeVariableSuppliers) {
brandjon96e223a2021-02-01 09:05:36 -08001064 Preconditions.checkState(
1065 configurationMakeVariableContext == null,
1066 "Attempted to init an already initialized Make var context (did you call"
1067 + " initConfigurationMakeVariableContext() after accessing ctx.var?)");
ulfjack08ff9b82017-09-28 04:08:06 -04001068 configurationMakeVariableContext =
1069 new ConfigurationMakeVariableContext(
jhorvitz04816f52021-08-11 10:51:51 -07001070 this, rule.getPackage(), getConfiguration(), makeVariableSuppliers);
ulfjack08ff9b82017-09-28 04:08:06 -04001071 }
1072
1073 public void initConfigurationMakeVariableContext(MakeVariableSupplier... makeVariableSuppliers) {
1074 initConfigurationMakeVariableContext(ImmutableList.copyOf(makeVariableSuppliers));
1075 }
1076
ulfjack01bf32e2017-11-02 17:50:07 -04001077 public Expander getExpander(TemplateContext templateContext) {
gregce31e44792020-04-27 09:10:40 -07001078 Expander expander = new Expander(this, templateContext);
1079 makeVariableExpanders.add(expander);
1080 return expander;
Liam Miller-Cushonce6a7b22016-02-03 18:12:36 +00001081 }
1082
ulfjack07860132017-09-29 08:59:44 -04001083 public Expander getExpander() {
gregce31e44792020-04-27 09:10:40 -07001084 Expander expander = new Expander(this, getConfigurationMakeVariableContext());
1085 makeVariableExpanders.add(expander);
1086 return expander;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001087 }
1088
Googlera45a8e02019-05-13 11:17:02 -07001089 public Expander getExpander(ImmutableMap<Label, ImmutableCollection<Artifact>> labelMap) {
gregce31e44792020-04-27 09:10:40 -07001090 Expander expander = new Expander(this, getConfigurationMakeVariableContext(), labelMap);
1091 makeVariableExpanders.add(expander);
1092 return expander;
Googlera45a8e02019-05-13 11:17:02 -07001093 }
1094
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001095 /**
ulfjack08ff9b82017-09-28 04:08:06 -04001096 * Returns a cached context that maps Make variable names (string) to values (string) without any
1097 * extra {@link MakeVariableSupplier}.
brandjon96e223a2021-02-01 09:05:36 -08001098 *
1099 * <p>CAUTION: If there's no context, this will initialize the context with no
1100 * MakeVariableSuppliers. Call {@link #initConfigurationMakeVariableContext} first if you want to
1101 * register suppliers.
hlopkoa4778052017-05-26 11:37:28 +02001102 */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001103 public ConfigurationMakeVariableContext getConfigurationMakeVariableContext() {
1104 if (configurationMakeVariableContext == null) {
jhorvitz04816f52021-08-11 10:51:51 -07001105 initConfigurationMakeVariableContext(ImmutableList.of());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001106 }
1107 return configurationMakeVariableContext;
1108 }
1109
jhorvitz2cdb6472021-10-06 14:22:36 -07001110 private StarlarkThread createStarlarkThread(Mutability mutability) {
brandjonbfd332e2020-12-17 14:56:04 -08001111 AnalysisEnvironment env = getAnalysisEnvironment();
jhorvitz2cdb6472021-10-06 14:22:36 -07001112 StarlarkThread thread = new StarlarkThread(mutability, env.getStarlarkSemantics());
brandjonbfd332e2020-12-17 14:56:04 -08001113 thread.setPrintHandler(Event.makeDebugPrintHandler(env.getEventHandler()));
1114 new BazelStarlarkContext(
1115 BazelStarlarkContext.Phase.ANALYSIS,
jhorvitz2cdb6472021-10-06 14:22:36 -07001116 ruleClassProvider.getToolsRepository(),
Googler38349752023-01-11 09:02:30 -08001117 /* fragmentNameToClass= */ null,
brandjonbfd332e2020-12-17 14:56:04 -08001118 getSymbolGenerator(),
ajurkowskid5fd56e2021-08-19 13:56:16 -07001119 getLabel(),
Googler38349752023-01-11 09:02:30 -08001120 /* networkAllowlistForTests= */ null)
brandjonbfd332e2020-12-17 14:56:04 -08001121 .storeInThread(thread);
1122 return thread;
1123 }
1124
1125 public StarlarkThread getStarlarkThread() {
1126 return starlarkThread;
1127 }
1128
1129 /**
ilist2c158fb2021-11-30 00:19:59 -08001130 * Initializes the StarlarkRuleContext for use and returns it. No-op if already initialized.
brandjonf1cc4dd2021-02-01 08:53:40 -08001131 *
1132 * <p>Throws RuleErrorException on failure.
1133 */
1134 public StarlarkRuleContext initStarlarkRuleContext() throws RuleErrorException {
ilist2c158fb2021-11-30 00:19:59 -08001135 if (starlarkRuleContext == null) {
1136 AspectDescriptor descriptor =
1137 aspects.isEmpty() ? null : Iterables.getLast(aspects).getDescriptor();
1138 this.starlarkRuleContext = new StarlarkRuleContext(this, descriptor);
1139 }
brandjonf1cc4dd2021-02-01 08:53:40 -08001140 return starlarkRuleContext;
1141 }
1142
1143 public StarlarkRuleContext getStarlarkRuleContext() {
1144 Preconditions.checkNotNull(starlarkRuleContext, "Must call initStarlarkRuleContext() first");
1145 return starlarkRuleContext;
1146 }
1147
1148 /**
brandjon4f331eb2021-02-01 09:09:39 -08001149 * Retrieves the {@code @_builtins}-defined Starlark object registered in the {@code
1150 * exported_to_java} mapping under the given name.
1151 *
1152 * <p>Reports and raises a rule error if no symbol by that name is defined.
1153 */
1154 public Object getStarlarkDefinedBuiltin(String name)
1155 throws RuleErrorException, InterruptedException {
1156 Object result = getAnalysisEnvironment().getStarlarkDefinedBuiltins().get(name);
1157 if (result == null) {
1158 throwWithRuleError(
1159 String.format(
1160 "(Internal error) No symbol named '%s' defined in the @_builtins exported_to_java"
1161 + " dict",
1162 name));
1163 }
1164 return result;
1165 }
1166
1167 /**
1168 * Calls a Starlark function in this rule's Starlark thread with the given positional and keyword
1169 * arguments. On failure, calls {@link #throwWithRuleError} with the Starlark stack trace.
1170 *
1171 * <p>This convenience method avoids the need to catch EvalException when the failure would just
1172 * immediately terminate rule analysis anyway.
1173 */
1174 public Object callStarlarkOrThrowRuleError(
1175 Object func, List<Object> args, Map<String, Object> kwargs)
1176 throws RuleErrorException, InterruptedException {
1177 try {
1178 return Starlark.call(starlarkThread, func, args, kwargs);
1179 } catch (EvalException e) {
jhorvitzb6590822021-08-13 15:18:27 -07001180 throw throwWithRuleError(e.getMessageWithStack());
brandjon4f331eb2021-02-01 09:09:39 -08001181 }
1182 }
1183
1184 /**
brandjonbfd332e2020-12-17 14:56:04 -08001185 * Prepares Starlark objects created during this target's analysis for use by others. Freezes
1186 * mutability, clears expensive references.
1187 */
1188 @Override
1189 public void close() {
1190 starlarkThread.mutability().freeze();
brandjonf1cc4dd2021-02-01 08:53:40 -08001191 if (starlarkRuleContext != null) {
1192 starlarkRuleContext.nullify();
Googler5c8d1d02023-02-20 06:57:32 -08001193 starlarkRuleContext = null;
brandjonf1cc4dd2021-02-01 08:53:40 -08001194 }
brandjonbfd332e2020-12-17 14:56:04 -08001195 }
1196
John Cater13263f72017-05-24 19:06:47 +02001197 @Nullable
jcaterdf7689d2021-10-14 11:28:53 -07001198 public Label targetPlatform() {
1199 if (toolchainContexts == null) {
1200 return null;
1201 }
1202 PlatformInfo targetPlatform = toolchainContexts.getTargetPlatform();
1203 if (targetPlatform == null) {
1204 return null;
1205 }
1206 return targetPlatform.label();
1207 }
1208
Googler38349752023-01-11 09:02:30 -08001209 private boolean useAutoExecGroupsForRule() {
1210 if (attributes().has("$use_auto_exec_groups")) {
1211 return (boolean) attributes().get("$use_auto_exec_groups", Type.BOOLEAN);
1212 } else {
1213 return getConfiguration().useAutoExecGroups();
1214 }
1215 }
1216
1217 private boolean useAutoExecGroupsForAspect(Aspect aspect) {
1218 ImmutableMap<String, Attribute> aspectAttributes = aspect.getDefinition().getAttributes();
1219
1220 if (aspectAttributes.containsKey("$use_auto_exec_groups")) {
1221 return (boolean) aspectAttributes.get("$use_auto_exec_groups").getDefaultValueUnchecked();
1222 } else {
1223 return getConfiguration().useAutoExecGroups();
1224 }
1225 }
1226
1227 public boolean useAutoExecGroups() {
1228 Aspect aspect = getMainAspect();
1229
1230 if (aspect == null) {
1231 return useAutoExecGroupsForRule();
1232 } else {
1233 return useAutoExecGroupsForAspect(aspect);
1234 }
1235 }
1236
Googler928e0fe2023-01-18 02:31:45 -08001237 /**
1238 * Returns the toolchain context from the default exec group. Important note: In case automatic
Googler48adeaa2023-01-25 09:48:40 -08001239 * exec groups are enabled, use `getToolchainInfo(Label toolchainType)` function.
Googler928e0fe2023-01-18 02:31:45 -08001240 */
jcaterdf7689d2021-10-14 11:28:53 -07001241 @Nullable
John Catercdfa9ca2019-04-05 12:32:09 -07001242 public ResolvedToolchainContext getToolchainContext() {
juliexxiab5f9d742020-04-09 13:07:13 -07001243 return toolchainContexts == null ? null : toolchainContexts.getDefaultToolchainContext();
1244 }
1245
1246 @Nullable
juliexxiaff580812020-04-30 15:01:09 -07001247 private ResolvedToolchainContext getToolchainContext(String execGroup) {
1248 return toolchainContexts == null ? null : toolchainContexts.getToolchainContext(execGroup);
1249 }
1250
Googler928e0fe2023-01-18 02:31:45 -08001251 /**
1252 * Returns the toolchain info from the default exec group in case automatic exec groups are not
1253 * enabled. If they are enabled, retrieves toolchain info from the corresponding automatic exec
1254 * group.
1255 */
1256 @Nullable
1257 public ToolchainInfo getToolchainInfo(Label toolchainType) {
1258 ResolvedToolchainContext toolchainContext;
1259 if (useAutoExecGroups()) {
1260 toolchainContext = toolchainContexts.getToolchainContext(toolchainType.toString());
1261 } else {
1262 toolchainContext = getToolchainContext();
1263 }
1264 return toolchainContext == null ? null : toolchainContext.forToolchainType(toolchainType);
1265 }
1266
juliexxiaff580812020-04-30 15:01:09 -07001267 public boolean hasToolchainContext(String execGroup) {
1268 return toolchainContexts != null && toolchainContexts.hasToolchainContext(execGroup);
1269 }
1270
1271 @Nullable
juliexxia0a0a13b2020-04-21 15:55:00 -07001272 public ToolchainCollection<ResolvedToolchainContext> getToolchainContexts() {
juliexxiab5f9d742020-04-09 13:07:13 -07001273 return toolchainContexts;
John Catereca28402017-05-17 21:44:12 +02001274 }
1275
jcater645c42b2021-05-12 09:35:48 -07001276 public ExecGroupCollection getExecGroups() {
1277 return execGroupCollection;
1278 }
1279
jcater0a1e9eb2019-12-17 09:58:38 -08001280 public boolean targetPlatformHasConstraint(ConstraintValueInfo constraintValue) {
juliexxiacede76b2020-09-23 13:49:34 -07001281 if (toolchainContexts == null || toolchainContexts.getTargetPlatform() == null) {
jcater0a1e9eb2019-12-17 09:58:38 -08001282 return false;
1283 }
juliexxiab5f9d742020-04-09 13:07:13 -07001284 // All toolchain contexts should have the same target platform so we access via the default.
juliexxiacede76b2020-09-23 13:49:34 -07001285 return toolchainContexts.getTargetPlatform().constraints().hasConstraintValue(constraintValue);
jcater0a1e9eb2019-12-17 09:58:38 -08001286 }
1287
jhorvitz2cdb6472021-10-06 14:22:36 -07001288 public ConfiguredRuleClassProvider getRuleClassProvider() {
1289 return ruleClassProvider;
gregce6acfe4e2018-05-25 08:38:39 -07001290 }
1291
Googler5c8d1d02023-02-20 06:57:32 -08001292 /**
1293 * Returns the configuration fragments this rule uses if it should be included for this rule.
1294 * Otherwise it returns null.
1295 */
1296 @Nullable
jhorvitz6f63d442021-08-19 10:47:16 -07001297 public RequiredConfigFragmentsProvider getRequiredConfigFragments() {
Googler5c8d1d02023-02-20 06:57:32 -08001298 if (requiredConfigFragments == null) {
1299 return null;
1300 }
1301
jhorvitz6f63d442021-08-19 10:47:16 -07001302 RequiredConfigFragmentsProvider.Builder merged = null;
jhorvitz09e3c532021-10-04 16:30:39 -07001303
1304 // Add variables accessed through ctx.var, if this is a Starlark rule.
1305 if (starlarkRuleContext != null) {
1306 for (String makeVariable : starlarkRuleContext.lookedUpVariables()) {
1307 if (isUserDefinedMakeVariable(makeVariable)) {
jhorvitz6f63d442021-08-19 10:47:16 -07001308 if (merged == null) {
1309 merged = RequiredConfigFragmentsProvider.builder().merge(requiredConfigFragments);
1310 }
1311 merged.addDefine(makeVariable);
gregce31e44792020-04-27 09:10:40 -07001312 }
1313 }
1314 }
jhorvitz09e3c532021-10-04 16:30:39 -07001315
1316 // Add variables accessed through Make variable substitution.
1317 for (Expander makeVariableExpander : makeVariableExpanders) {
1318 for (String makeVariable : makeVariableExpander.lookedUpVariables()) {
1319 if (isUserDefinedMakeVariable(makeVariable)) {
1320 if (merged == null) {
1321 merged = RequiredConfigFragmentsProvider.builder().merge(requiredConfigFragments);
1322 }
1323 merged.addDefine(makeVariable);
1324 }
1325 }
1326 }
1327
jhorvitz6f63d442021-08-19 10:47:16 -07001328 return merged == null ? requiredConfigFragments : merged.build();
gregce966dc232019-10-18 15:34:07 -07001329 }
1330
Googler720dc5f2022-09-16 03:43:51 -07001331 /**
1332 * Returns the set of transitive packages. This is only intended to be used to create the repo
1333 * mapping manifest for the runfiles tree. Can be null if transitive packages are not tracked (see
1334 * {@link
1335 * com.google.devtools.build.lib.skyframe.SkyframeExecutor#shouldStoreTransitivePackagesInLoadingAndAnalysis}).
1336 */
1337 @Nullable
1338 public NestedSet<Package> getTransitivePackagesForRunfileRepoMappingManifest() {
1339 return transitivePackagesForRunfileRepoMappingManifest;
1340 }
1341
jhorvitz09e3c532021-10-04 16:30:39 -07001342 private boolean isUserDefinedMakeVariable(String makeVariable) {
1343 // User-defined make values may be set either in "--define foo=bar" or in a vardef in the rule's
1344 // package. Both are equivalent for these purposes, since in both cases setting
1345 // "--define foo=bar" impacts the rule's output.
1346 return rule.getPackage().getMakeEnvironment().containsKey(makeVariable)
1347 || getConfiguration().getCommandLineBuildVariables().containsKey(makeVariable);
1348 }
1349
jcater7ba83102020-09-10 11:05:29 -07001350 private void checkAttributeIsDependency(String attributeName) {
Greg Estren7f534232016-12-01 21:38:25 +00001351 Attribute attributeDefinition = attributes.getAttributeDefinition(attributeName);
jhorvitz04816f52021-08-11 10:51:51 -07001352 Preconditions.checkNotNull(
1353 attributeDefinition,
1354 "%s: %s attribute %s is not defined",
1355 rule.getLocation(),
1356 ruleClassNameForLogging,
1357 attributeName);
1358 Preconditions.checkState(
1359 attributeDefinition.getType().getLabelClass() == LabelClass.DEPENDENCY,
1360 "%s attribute %s is not a label type attribute",
1361 ruleClassNameForLogging,
1362 attributeName);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001363 }
1364
juliexxia6fe70c22020-05-18 14:38:42 -07001365 @Override
1366 @Nullable
1367 public PlatformInfo getExecutionPlatform() {
1368 if (getToolchainContext() == null) {
1369 return null;
1370 }
1371 return getToolchainContext().executionPlatform();
1372 }
1373
1374 @Override
1375 @Nullable
1376 public PlatformInfo getExecutionPlatform(String execGroup) {
jhorvitz04816f52021-08-11 10:51:51 -07001377 if (toolchainContexts == null) {
juliexxia6fe70c22020-05-18 14:38:42 -07001378 return null;
1379 }
1380 ResolvedToolchainContext toolchainContext = getToolchainContext(execGroup);
1381 return toolchainContext == null ? null : toolchainContext.executionPlatform();
1382 }
1383
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001384 /**
jcaterf7d726f2020-04-13 10:34:54 -07001385 * For the specified attribute "attributeName" (which must be of type list(label)), resolve all
1386 * the labels into ConfiguredTargets (for the configuration appropriate to the attribute) and
1387 * return their build artifacts as a {@link PrerequisiteArtifacts} instance.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001388 *
1389 * @param attributeName the name of the attribute to traverse
1390 */
jcater3a9532d2020-08-26 06:09:28 -07001391 public PrerequisiteArtifacts getPrerequisiteArtifacts(String attributeName) {
jcater7ba83102020-09-10 11:05:29 -07001392 return PrerequisiteArtifacts.get(this, attributeName);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001393 }
1394
1395 /**
jcaterf7d726f2020-04-13 10:34:54 -07001396 * For the specified attribute "attributeName" (which must be of type label), resolves the
1397 * ConfiguredTarget and returns its single build artifact.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001398 *
jcaterf7d726f2020-04-13 10:34:54 -07001399 * <p>If the attribute is optional, has no default and was not specified, then null will be
1400 * returned. Note also that null is returned (and an attribute error is raised) if there wasn't
1401 * exactly one build artifact for the target.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001402 */
jcater3a9532d2020-08-26 06:09:28 -07001403 public Artifact getPrerequisiteArtifact(String attributeName) {
jcater7ba83102020-09-10 11:05:29 -07001404 TransitiveInfoCollection target = getPrerequisite(attributeName);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001405 return transitiveInfoCollectionToArtifact(attributeName, target);
1406 }
1407
Googler7b649f92022-07-06 05:12:46 -07001408 @Nullable
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001409 private Artifact transitiveInfoCollectionToArtifact(
1410 String attributeName, TransitiveInfoCollection target) {
1411 if (target != null) {
ulfjack8d8f62f2019-12-05 15:03:53 -08001412 NestedSet<Artifact> artifacts = target.getProvider(FileProvider.class).getFilesToBuild();
1413 if (artifacts.isSingleton()) {
1414 return artifacts.getSingleton();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001415 } else {
1416 attributeError(attributeName, target.getLabel() + " expected a single artifact");
1417 }
1418 }
1419 return null;
1420 }
1421
1422 /**
jhorvitzb6590822021-08-13 15:18:27 -07001423 * Returns the sole file in the "srcs" attribute. Reports an error and (possibly) returns null if
1424 * "srcs" does not identify a single file of the expected type.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001425 */
Googler7b649f92022-07-06 05:12:46 -07001426 @Nullable
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001427 public Artifact getSingleSource(String fileTypeName) {
jcater7ba83102020-09-10 11:05:29 -07001428 List<Artifact> srcs = PrerequisiteArtifacts.get(this, "srcs").list();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001429 switch (srcs.size()) {
jhorvitzb6590822021-08-13 15:18:27 -07001430 case 0: // error already issued by getSrc()
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001431 return null;
jhorvitzb6590822021-08-13 15:18:27 -07001432 case 1: // ok
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001433 return Iterables.getOnlyElement(srcs);
jhorvitzb6590822021-08-13 15:18:27 -07001434 default:
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001435 attributeError("srcs", "only a single " + fileTypeName + " is allowed here");
1436 return srcs.get(0);
1437 }
1438 }
1439
1440 public Artifact getSingleSource() {
jhorvitz04816f52021-08-11 10:51:51 -07001441 return getSingleSource(ruleClassNameForLogging + " source file");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001442 }
1443
1444 /**
jhorvitz04816f52021-08-11 10:51:51 -07001445 * Returns a path fragment qualified by the rule name and unique fragment to disambiguate
1446 * artifacts produced from the source file appearing in multiple rules.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001447 *
1448 * <p>For example "pkg/dir/name" -> "pkg/&lt;fragment>/rule/dir/name.
1449 */
jhorvitz04816f52021-08-11 10:51:51 -07001450 public PathFragment getUniqueDirectory(String fragment) {
nharmata5e924af2017-05-02 18:16:23 +02001451 return getUniqueDirectory(PathFragment.create(fragment));
1452 }
1453
1454 /**
David Ostrovskya1388772020-07-08 12:11:01 -07001455 * Returns a path fragment qualified by the rule name and unique fragment to disambiguate
1456 * artifacts produced from the source file appearing in multiple rules.
nharmata5e924af2017-05-02 18:16:23 +02001457 *
1458 * <p>For example "pkg/dir/name" -> "pkg/&lt;fragment>/rule/dir/name.
1459 */
David Ostrovskya1388772020-07-08 12:11:01 -07001460 @Override
jhorvitz04816f52021-08-11 10:51:51 -07001461 public PathFragment getUniqueDirectory(PathFragment fragment) {
Googler7b644a62020-10-21 11:56:33 -07001462 return AnalysisUtils.getUniqueDirectory(
1463 getLabel(), fragment, getConfiguration().isSiblingRepositoryLayout());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001464 }
1465
1466 /**
jhorvitzb6590822021-08-13 15:18:27 -07001467 * Check that all targets that were specified as sources are from the same package as this rule.
1468 * Output a warning or an error for every target that is imported from a different package.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001469 */
1470 public void checkSrcsSamePackage(boolean onlyWarn) {
1471 PathFragment packageName = getLabel().getPackageFragment();
jcater7ba83102020-09-10 11:05:29 -07001472 for (Artifact srcItem : PrerequisiteArtifacts.get(this, "srcs").list()) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001473 if (!srcItem.isSourceArtifact()) {
1474 // In theory, we should not do this check. However, in practice, we
1475 // have a couple of rules that do not obey the "srcs must contain
1476 // files and only files" rule. Thus, we are stuck with this hack here :(
1477 continue;
1478 }
1479 Label associatedLabel = srcItem.getOwner();
1480 PathFragment itemPackageName = associatedLabel.getPackageFragment();
1481 if (!itemPackageName.equals(packageName)) {
jhorvitzb6590822021-08-13 15:18:27 -07001482 String message =
1483 "please do not import '"
1484 + associatedLabel
1485 + "' directly. "
1486 + "You should either move the file to this package or depend on "
1487 + "an appropriate rule there";
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001488 if (onlyWarn) {
1489 attributeWarning("srcs", message);
1490 } else {
1491 attributeError("srcs", message);
1492 }
1493 }
1494 }
1495 }
1496
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001497 /**
jhorvitzb6590822021-08-13 15:18:27 -07001498 * Returns the label to which the {@code NODEP_LABEL} attribute {@code attrName} refers, checking
1499 * that it is a valid label, and that it is referring to a local target. Reports a warning
1500 * otherwise.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001501 */
Googler7b649f92022-07-06 05:12:46 -07001502 @Nullable
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001503 public Label getLocalNodepLabelAttribute(String attrName) {
Lukacs Berkiffa73ad2015-09-18 11:40:12 +00001504 Label label = attributes().get(attrName, BuildType.NODEP_LABEL);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001505 if (label == null) {
1506 return null;
1507 }
1508
1509 if (!getTarget().getLabel().getPackageFragment().equals(label.getPackageFragment())) {
1510 attributeWarning(attrName, "does not reference a local rule");
1511 }
1512
1513 return label;
1514 }
1515
asteinb0de45462018-05-17 08:07:12 -07001516 @Override
Florian Weikert4b67d4f2015-09-14 13:35:34 +00001517 public Artifact getImplicitOutputArtifact(ImplicitOutputsFunction function)
1518 throws InterruptedException {
Googler38349752023-01-11 09:02:30 -08001519 return getImplicitOutputArtifact(function, /* contentBasedPath= */ false);
gregce11f3b0e2019-06-07 17:12:06 -07001520 }
1521
1522 /**
1523 * Same as {@link #getImplicitOutputArtifact(ImplicitOutputsFunction)} but includes the option to
1524 * use a content-based path for this artifact (see {@link
jhorvitz33f76482021-10-28 10:13:26 -07001525 * BuildConfigurationValue#useContentBasedOutputPaths()}).
gregce11f3b0e2019-06-07 17:12:06 -07001526 */
1527 public Artifact getImplicitOutputArtifact(
1528 ImplicitOutputsFunction function, boolean contentBasedPath) throws InterruptedException {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001529 Iterable<String> result;
1530 try {
vladmos076977e2017-12-02 14:15:32 -08001531 result =
1532 function.getImplicitOutputs(
1533 getAnalysisEnvironment().getEventHandler(), RawAttributeMapper.of(rule));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001534 } catch (EvalException e) {
gregceca48e9a2020-04-14 08:54:38 -07001535 // It's ok as long as we don't use this method from Starlark.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001536 throw new IllegalStateException(e);
1537 }
gregce11f3b0e2019-06-07 17:12:06 -07001538 return getImplicitOutputArtifact(Iterables.getOnlyElement(result), contentBasedPath);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001539 }
1540
gregceca48e9a2020-04-14 08:54:38 -07001541 /** Only use from Starlark. Returns the implicit output artifact for a given output path. */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001542 public Artifact getImplicitOutputArtifact(String path) {
Googler38349752023-01-11 09:02:30 -08001543 return getImplicitOutputArtifact(path, /* contentBasedPath= */ false);
gregce11f3b0e2019-06-07 17:12:06 -07001544 }
1545
1546 /**
1547 * Same as {@link #getImplicitOutputArtifact(String)} but includes the option to use a a
1548 * content-based path for this artifact (see {@link
jhorvitz33f76482021-10-28 10:13:26 -07001549 * BuildConfigurationValue#useContentBasedOutputPaths()}).
gregce11f3b0e2019-06-07 17:12:06 -07001550 */
brandjond2582632021-01-29 16:10:58 -08001551 // TODO(bazel-team): Consider removing contentBasedPath stuff, which is unused as of 18 months
1552 // after its introduction in cl/252148134.
gregce11f3b0e2019-06-07 17:12:06 -07001553 private Artifact getImplicitOutputArtifact(String path, boolean contentBasedPath) {
1554 return getPackageRelativeArtifact(path, getBinOrGenfilesDirectory(), contentBasedPath);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001555 }
1556
1557 /**
jcater7ba83102020-09-10 11:05:29 -07001558 * Convenience method to return a configured target for the "compiler" attribute. Allows caller to
1559 * decide whether a warning should be printed if the "compiler" attribute is not set to the
1560 * default value.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001561 *
jcater7ba83102020-09-10 11:05:29 -07001562 * @param warnIfNotDefault if true, print a warning if the value for the "compiler" attribute is
1563 * set to something other than the default
1564 * @return a ConfiguredTarget for the "compiler" attribute
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001565 */
jhorvitz04816f52021-08-11 10:51:51 -07001566 public FilesToRunProvider getCompiler(boolean warnIfNotDefault) {
Lukacs Berkiffa73ad2015-09-18 11:40:12 +00001567 Label label = attributes().get("compiler", BuildType.LABEL);
jhorvitz04816f52021-08-11 10:51:51 -07001568 if (warnIfNotDefault && !label.equals(rule.getAttrDefaultValue("compiler"))) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001569 attributeWarning("compiler", "setting the compiler is strongly discouraged");
1570 }
jcater7ba83102020-09-10 11:05:29 -07001571 return getExecutablePrerequisite("compiler");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001572 }
1573
1574 /**
jhorvitz04816f52021-08-11 10:51:51 -07001575 * Returns the (unmodifiable, ordered) list of artifacts which are the outputs of this target.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001576 *
jhorvitz04816f52021-08-11 10:51:51 -07001577 * <p>Each element in this list is associated with a single output, either declared implicitly
1578 * (via setImplicitOutputsFunction()) or explicitly (listed in the 'outs' attribute of our rule).
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001579 */
jhorvitz04816f52021-08-11 10:51:51 -07001580 public ImmutableList<Artifact> getOutputArtifacts() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001581 ImmutableList.Builder<Artifact> artifacts = ImmutableList.builder();
jhorvitz04816f52021-08-11 10:51:51 -07001582 for (OutputFile out : rule.getOutputFiles()) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001583 artifacts.add(createOutputArtifact(out));
1584 }
1585 return artifacts.build();
1586 }
1587
1588 /**
jhorvitzb6590822021-08-13 15:18:27 -07001589 * Like {@link #getOutputArtifacts()} but for a singular output item. Reports an error if the
1590 * "out" attribute is not a singleton.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001591 *
jhorvitzb6590822021-08-13 15:18:27 -07001592 * @return null if the output list is empty, the artifact for the first item of the output list
1593 * otherwise
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001594 */
Googler7b649f92022-07-06 05:12:46 -07001595 @Nullable
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001596 public Artifact getOutputArtifact() {
1597 List<Artifact> outs = getOutputArtifacts();
1598 if (outs.size() != 1) {
1599 attributeError("out", "exactly one output file required");
1600 if (outs.isEmpty()) {
1601 return null;
1602 }
1603 }
1604 return outs.get(0);
1605 }
1606
plf727a07d2019-02-01 02:27:35 -08001607 @Override
jhorvitz04816f52021-08-11 10:51:51 -07001608 public Artifact.DerivedArtifact getRelatedArtifact(PathFragment pathFragment, String extension) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001609 PathFragment file = FileSystemUtils.replaceExtension(pathFragment, extension);
Googler0617f2c2020-10-22 08:43:54 -07001610 return getDerivedArtifact(file, getConfiguration().getBinDirectory(getLabel().getRepository()));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001611 }
1612
jhorvitzb6590822021-08-13 15:18:27 -07001613 /** Returns true if the target for this context is a test target. */
Googlerf812a2f2016-06-13 16:14:10 +00001614 public boolean isTestTarget() {
1615 return TargetUtils.isTestRule(getTarget());
1616 }
1617
Googlercfdeb4d2018-02-08 07:13:33 -08001618 /** Returns true if the testonly attribute is set on this context. */
1619 public boolean isTestOnlyTarget() {
1620 return attributes().has("testonly", Type.BOOLEAN) && attributes().get("testonly", Type.BOOLEAN);
1621 }
1622
Googlerf812a2f2016-06-13 16:14:10 +00001623 /**
Klaus Aehliga85af942019-10-29 07:48:32 -07001624 * Returns true if {@code label} is visible from {@code prerequisite}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001625 *
1626 * <p>This only computes the logic as implemented by the visibility system. The final decision
jcater0de10972020-04-07 12:15:05 -07001627 * whether a dependency is allowed is made by {@link PrerequisiteValidator}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001628 */
Klaus Aehliga85af942019-10-29 07:48:32 -07001629 public static boolean isVisible(Label label, TransitiveInfoCollection prerequisite) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001630 // Check visibility attribute
cushon34ff85e2017-11-15 08:59:27 -08001631 for (PackageGroupContents specification :
Ulf Adamscd31d3b2019-12-16 00:50:03 -08001632 prerequisite.getProvider(VisibilityProvider.class).getVisibility().toList()) {
Klaus Aehliga85af942019-10-29 07:48:32 -07001633 if (specification.containsPackage(label.getPackageIdentifier())) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001634 return true;
1635 }
1636 }
1637
1638 return false;
1639 }
1640
1641 /**
Klaus Aehliga85af942019-10-29 07:48:32 -07001642 * Returns true if {@code rule} is visible from {@code prerequisite}.
1643 *
1644 * <p>This only computes the logic as implemented by the visibility system. The final decision
jcater0de10972020-04-07 12:15:05 -07001645 * whether a dependency is allowed is made by {@link PrerequisiteValidator}.
Klaus Aehliga85af942019-10-29 07:48:32 -07001646 */
1647 public static boolean isVisible(Rule rule, TransitiveInfoCollection prerequisite) {
1648 return isVisible(rule.getLabel(), prerequisite);
1649 }
1650
Googler38349752023-01-11 09:02:30 -08001651 /**
1652 * @return the set of features applicable for the current rule.
1653 */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001654 public ImmutableSet<String> getFeatures() {
Googler993f1de2018-02-20 02:31:10 -08001655 return enabledFeatures;
1656 }
1657
Googler38349752023-01-11 09:02:30 -08001658 /**
1659 * @return the set of features that are disabled for the current rule.
1660 */
Googler993f1de2018-02-20 02:31:10 -08001661 public ImmutableSet<String> getDisabledFeatures() {
1662 return disabledFeatures;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001663 }
1664
Florian Weikertb8a6a942015-09-25 12:36:08 +00001665 @Override
plf43109892019-02-12 05:45:05 -08001666 public RuleErrorConsumer getRuleErrorConsumer() {
1667 return this;
1668 }
1669
jhorvitz7410c802020-07-22 11:55:07 -07001670 /**
1671 * Returns {@code true} if a {@link RequiredConfigFragmentsProvider} should be included for this
1672 * rule.
1673 */
1674 public boolean shouldIncludeRequiredConfigFragmentsProvider() {
jhorvitz8128f522021-08-18 17:33:43 -07001675 return requiredConfigFragments != null;
jhorvitz7410c802020-07-22 11:55:07 -07001676 }
1677
plf43109892019-02-12 05:45:05 -08001678 @Override
Florian Weikertb8a6a942015-09-25 12:36:08 +00001679 public String toString() {
1680 return "RuleContext(" + getLabel() + ", " + getConfiguration() + ")";
1681 }
1682
brandjonbfd332e2020-12-17 14:56:04 -08001683 /** Builder class for a RuleContext. */
brandjonbfd332e2020-12-17 14:56:04 -08001684 public static final class Builder implements RuleErrorConsumer {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001685 private final AnalysisEnvironment env;
lpino5fe7ed02018-07-18 05:55:23 -07001686 private final Target target;
jhorvitz2cdb6472021-10-06 14:22:36 -07001687 private final ImmutableList<Aspect> aspects;
jhorvitz33f76482021-10-28 10:13:26 -07001688 private final BuildConfigurationValue configuration;
cparsonse8d450c2018-10-04 16:01:53 -07001689 private final RuleErrorConsumer reporter;
jhorvitz2cdb6472021-10-06 14:22:36 -07001690 private ConfiguredRuleClassProvider ruleClassProvider;
jhorvitz2cdb6472021-10-06 14:22:36 -07001691 private ConfigurationFragmentPolicy configurationFragmentPolicy;
1692 private ActionLookupKey actionOwnerSymbol;
janakr9c101402018-03-10 06:48:59 -08001693 private OrderedSetMultimap<Attribute, ConfiguredTargetAndData> prerequisiteMap;
gregce79989f92021-02-01 07:01:55 -08001694 private ConfigConditions configConditions;
brandjonbfd332e2020-12-17 14:56:04 -08001695 private Mutability mutability;
cushon34ff85e2017-11-15 08:59:27 -08001696 private NestedSet<PackageGroupContents> visibility;
jhorvitz2cdb6472021-10-06 14:22:36 -07001697 private ImmutableMap<String, Attribute> aspectAttributes = ImmutableMap.of();
juliexxiab5f9d742020-04-09 13:07:13 -07001698 private ToolchainCollection<ResolvedToolchainContext> toolchainContexts;
jcater645c42b2021-05-12 09:35:48 -07001699 private ExecGroupCollection.Builder execGroupCollectionBuilder;
juliexxia3eb806e2020-07-15 08:42:34 -07001700 private ImmutableMap<String, String> rawExecProperties;
jhorvitz8128f522021-08-18 17:33:43 -07001701 @Nullable private RequiredConfigFragmentsProvider requiredConfigFragments;
Googler720dc5f2022-09-16 03:43:51 -07001702 @Nullable private NestedSet<Package> transitivePackagesForRunfileRepoMappingManifest;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001703
ulfjack865b6212018-06-14 03:41:55 -07001704 @VisibleForTesting
1705 public Builder(
Michael Staib8824d5e2016-01-20 21:37:05 +00001706 AnalysisEnvironment env,
lpino5fe7ed02018-07-18 05:55:23 -07001707 Target target,
dslomov44d15712017-12-20 05:42:28 -08001708 ImmutableList<Aspect> aspects,
jhorvitz33f76482021-10-28 10:13:26 -07001709 BuildConfigurationValue configuration) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001710 this.env = Preconditions.checkNotNull(env);
lpino5fe7ed02018-07-18 05:55:23 -07001711 this.target = Preconditions.checkNotNull(target);
jhorvitz2cdb6472021-10-06 14:22:36 -07001712 this.aspects = Preconditions.checkNotNull(aspects);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001713 this.configuration = Preconditions.checkNotNull(configuration);
cparsonse8d450c2018-10-04 16:01:53 -07001714 if (configuration.allowAnalysisFailures()) {
1715 reporter = new SuppressingErrorReporter();
1716 } else {
ulfjack07917642019-09-12 02:09:36 -07001717 reporter =
1718 new ErrorReporter(
1719 env, target.getAssociatedRule(), configuration, getRuleClassNameForLogging());
cparsonse8d450c2018-10-04 16:01:53 -07001720 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001721 }
1722
Googler2570fe12022-08-26 07:30:31 -07001723 /**
1724 * Same as {@link #build}, except without some attribute checks.
1725 *
1726 * <p>Don't use this function outside of testing. The use should be limited to cases where
1727 * specifying ConfigConditions.EMPTY, which can cause a noMatchError when accessing attributes
1728 * within attribute checking.
1729 */
1730 @VisibleForTesting
1731 public RuleContext unsafeBuild() throws InvalidExecGroupException {
1732 return build(false);
1733 }
1734
ulfjack865b6212018-06-14 03:41:55 -07001735 @VisibleForTesting
juliexxia6fe70c22020-05-18 14:38:42 -07001736 public RuleContext build() throws InvalidExecGroupException {
Googler2570fe12022-08-26 07:30:31 -07001737 return build(true);
1738 }
1739
1740 private RuleContext build(boolean attributeChecks) throws InvalidExecGroupException {
jhorvitz2cdb6472021-10-06 14:22:36 -07001741 Preconditions.checkNotNull(ruleClassProvider);
jhorvitz2cdb6472021-10-06 14:22:36 -07001742 Preconditions.checkNotNull(configurationFragmentPolicy);
1743 Preconditions.checkNotNull(actionOwnerSymbol);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001744 Preconditions.checkNotNull(prerequisiteMap);
1745 Preconditions.checkNotNull(configConditions);
brandjonbfd332e2020-12-17 14:56:04 -08001746 Preconditions.checkNotNull(mutability);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001747 Preconditions.checkNotNull(visibility);
Googler2570fe12022-08-26 07:30:31 -07001748 ConfiguredAttributeMapper attributes =
gregce3d33d7b2021-04-20 10:35:03 -07001749 ConfiguredAttributeMapper.of(
jcaterae8f15e2021-11-19 13:29:59 -08001750 target.getAssociatedRule(), configConditions.asProviders(), configuration);
janakr9c101402018-03-10 06:48:59 -08001751 ListMultimap<String, ConfiguredTargetAndData> targetMap = createTargetMap();
Googler9ba1ada2022-10-11 09:30:38 -07001752 // These checks can fail when ConfigConditions.EMPTY are empty, resulting in noMatchError
1753 // accessing attributes without a default condition.
1754 // ConfigConditions.EMPTY is always true for non-rules:
1755 // https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java;l=943;drc=720dc5fd640de692db129777c7c7c32924627c43
1756 // This can happen in BuildViewForTesting.getRuleContextForTesting as it specifies
1757 // ConfigConditions.EMPTY.
1758 if (attributeChecks && target instanceof Rule) {
Googler2570fe12022-08-26 07:30:31 -07001759 checkAttributesNonEmpty(attributes);
1760 checkAttributesForDuplicateLabels(attributes);
1761 }
gregce79989f92021-02-01 07:01:55 -08001762 // This conditionally checks visibility on config_setting rules based on
1763 // --config_setting_visibility_policy. This should be removed as soon as it's deemed safe
Googler2570fe12022-08-26 07:30:31 -07001764 // to unconditionally check visibility. See
1765 // https://github.com/bazelbuild/bazel/issues/12669.
Googlera3a4cf82022-10-07 11:34:58 -07001766 ConfigSettingVisibilityPolicy configSettingVisibilityPolicy =
1767 target.getPackage().getConfigSettingVisibilityPolicy();
1768 if (configSettingVisibilityPolicy != ConfigSettingVisibilityPolicy.LEGACY_OFF) {
gregce79989f92021-02-01 07:01:55 -08001769 Attribute configSettingAttr = attributes.getAttributeDefinition("$config_dependencies");
1770 for (ConfiguredTargetAndData condition : configConditions.asConfiguredTargets().values()) {
Googlera3a4cf82022-10-07 11:34:58 -07001771 validateDirectPrerequisite(
1772 configSettingAttr,
1773 // Another nuance: when both --incompatible_enforce_config_setting_visibility and
1774 // --incompatible_config_setting_private_default_visibility are disabled, both of
1775 // these are ignored:
1776 //
1777 // - visibility settings on a select() -> config_setting dep
1778 // - visibility settings on a select() -> alias -> config_setting dep chain
1779 //
1780 // In that scenario, both are ignored because the logic here that checks the
1781 // select() -> ??? edge is completely skipped.
1782 //
1783 // When just --incompatible_enforce_config_setting_visibility is on, that means
1784 // "enforce config_setting visibility with public default". That's a temporary state
1785 // to support depot migration. In that case, we continue to ignore the alias'
1786 // visibility in preference for the config_setting. So skip select() -> alias as
1787 // before, but now enforce select() -> config_setting_the_alias_refers_to.
1788 //
1789 // When we also turn on --incompatible_config_setting_private_default_visibility, we
1790 // expect full standard visibility compliance. In that case we directly evaluate the
1791 // alias visibility, as is usual semantics. So two the following two edges are
1792 // checked: 1: select() -> alias and 2: alias -> config_setting.
1793 configSettingVisibilityPolicy == ConfigSettingVisibilityPolicy.DEFAULT_PUBLIC
Googler268be232022-10-11 07:59:09 -07001794 ? condition.fromConfiguredTargetNoCheck(
1795 condition.getConfiguredTarget().getActual())
Googlera3a4cf82022-10-07 11:34:58 -07001796 : condition);
gregce79989f92021-02-01 07:01:55 -08001797 }
1798 }
jcater645c42b2021-05-12 09:35:48 -07001799
Michael Staib8824d5e2016-01-20 21:37:05 +00001800 return new RuleContext(
1801 this,
Nathan Harmatafcb17112016-04-13 16:56:58 +00001802 attributes,
Michael Staib8824d5e2016-01-20 21:37:05 +00001803 targetMap,
jhorvitz2cdb6472021-10-06 14:22:36 -07001804 createExecGroupCollection(execGroupCollectionBuilder, attributes));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001805 }
1806
jcater645c42b2021-05-12 09:35:48 -07001807 private ExecGroupCollection createExecGroupCollection(
1808 ExecGroupCollection.Builder execGroupCollectionBuilder, AttributeMap attributes)
1809 throws InvalidExecGroupException {
1810 if (rawExecProperties == null) {
jcaterc41ff072021-05-24 14:12:06 -07001811 if (!attributes.has(RuleClass.EXEC_PROPERTIES_ATTR, Type.STRING_DICT)) {
jcater645c42b2021-05-12 09:35:48 -07001812 rawExecProperties = ImmutableMap.of();
1813 } else {
1814 rawExecProperties =
jcaterc41ff072021-05-24 14:12:06 -07001815 ImmutableMap.copyOf(attributes.get(RuleClass.EXEC_PROPERTIES_ATTR, Type.STRING_DICT));
jcater645c42b2021-05-12 09:35:48 -07001816 }
1817 }
1818
1819 return execGroupCollectionBuilder.build(toolchainContexts, rawExecProperties);
1820 }
1821
adonovanec1cdc92020-08-07 08:15:51 -07001822 private void checkAttributesNonEmpty(AttributeMap attributes) {
1823 for (String attributeName : attributes.getAttributeNames()) {
1824 Attribute attr = attributes.getAttributeDefinition(attributeName);
1825 if (!attr.isNonEmpty()) {
1826 continue;
1827 }
1828 Object attributeValue = attributes.get(attributeName, attr.getType());
1829
1830 // TODO(adonovan): define in terms of Starlark.len?
1831 boolean isEmpty = false;
jhorvitz04816f52021-08-11 10:51:51 -07001832 if (attributeValue instanceof List) {
1833 isEmpty = ((List<?>) attributeValue).isEmpty();
1834 } else if (attributeValue instanceof Map) {
1835 isEmpty = ((Map<?, ?>) attributeValue).isEmpty();
adonovanec1cdc92020-08-07 08:15:51 -07001836 }
1837 if (isEmpty) {
1838 reporter.attributeError(attr.getName(), "attribute must be non empty");
1839 }
1840 }
Nathan Harmatafcb17112016-04-13 16:56:58 +00001841 }
1842
Googler2570fe12022-08-26 07:30:31 -07001843 private void checkAttributesForDuplicateLabels(ConfiguredAttributeMapper attributes) {
1844 for (String attributeName : attributes.getAttributeNames()) {
1845 Attribute attr = attributes.getAttributeDefinition(attributeName);
1846 if (attr.getType() != BuildType.LABEL_LIST) {
1847 continue;
1848 }
1849
1850 Set<Label> duplicates = attributes.checkForDuplicateLabels(attr);
1851 for (Label label : duplicates) {
1852 reporter.attributeError(attr.getName(), String.format("Label '%s' is duplicated", label));
1853 }
1854 }
1855 }
1856
Kurt Alfred Kluever4192ca62022-07-05 06:30:29 -07001857 @CanIgnoreReturnValue
jhorvitz2cdb6472021-10-06 14:22:36 -07001858 public Builder setRuleClassProvider(ConfiguredRuleClassProvider ruleClassProvider) {
1859 this.ruleClassProvider = ruleClassProvider;
brandjonbfd332e2020-12-17 14:56:04 -08001860 return this;
1861 }
1862
Kurt Alfred Kluever4192ca62022-07-05 06:30:29 -07001863 @CanIgnoreReturnValue
jhorvitz2cdb6472021-10-06 14:22:36 -07001864 public Builder setConfigurationFragmentPolicy(ConfigurationFragmentPolicy policy) {
1865 this.configurationFragmentPolicy = policy;
1866 return this;
1867 }
1868
Kurt Alfred Kluever4192ca62022-07-05 06:30:29 -07001869 @CanIgnoreReturnValue
jhorvitz2cdb6472021-10-06 14:22:36 -07001870 public Builder setActionOwnerSymbol(ActionLookupKey actionOwnerSymbol) {
1871 this.actionOwnerSymbol = actionOwnerSymbol;
brandjonbfd332e2020-12-17 14:56:04 -08001872 return this;
1873 }
1874
Kurt Alfred Kluever4192ca62022-07-05 06:30:29 -07001875 @CanIgnoreReturnValue
brandjonbfd332e2020-12-17 14:56:04 -08001876 public Builder setMutability(Mutability mutability) {
1877 this.mutability = mutability;
1878 return this;
1879 }
1880
Kurt Alfred Kluever4192ca62022-07-05 06:30:29 -07001881 @CanIgnoreReturnValue
ulfjack865b6212018-06-14 03:41:55 -07001882 public Builder setVisibility(NestedSet<PackageGroupContents> visibility) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001883 this.visibility = visibility;
1884 return this;
1885 }
1886
1887 /**
1888 * Sets the prerequisites and checks their visibility. It also generates appropriate error or
1889 * warning messages and sets the error flag as appropriate.
1890 */
Kurt Alfred Kluever4192ca62022-07-05 06:30:29 -07001891 @CanIgnoreReturnValue
ulfjack865b6212018-06-14 03:41:55 -07001892 public Builder setPrerequisites(
janakr9c101402018-03-10 06:48:59 -08001893 OrderedSetMultimap<Attribute, ConfiguredTargetAndData> prerequisiteMap) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001894 this.prerequisiteMap = Preconditions.checkNotNull(prerequisiteMap);
1895 return this;
1896 }
1897
jhorvitzb6590822021-08-13 15:18:27 -07001898 /** Adds attributes which are defined by an Aspect (and not by RuleClass). */
Kurt Alfred Kluever4192ca62022-07-05 06:30:29 -07001899 @CanIgnoreReturnValue
ulfjack865b6212018-06-14 03:41:55 -07001900 public Builder setAspectAttributes(Map<String, Attribute> aspectAttributes) {
Dmitry Lomovace678e2015-12-16 15:10:20 +00001901 this.aspectAttributes = ImmutableMap.copyOf(aspectAttributes);
Carmi Grushko06f65f72015-11-02 22:42:24 +00001902 return this;
1903 }
1904
1905 /**
gregce79989f92021-02-01 07:01:55 -08001906 * Sets the configuration conditions needed to determine which paths to follow for this rule's
1907 * configurable attributes.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001908 */
Kurt Alfred Kluever4192ca62022-07-05 06:30:29 -07001909 @CanIgnoreReturnValue
gregce79989f92021-02-01 07:01:55 -08001910 public Builder setConfigConditions(ConfigConditions configConditions) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001911 this.configConditions = Preconditions.checkNotNull(configConditions);
1912 return this;
1913 }
1914
juliexxiab5f9d742020-04-09 13:07:13 -07001915 /** Sets the collection of {@link ResolvedToolchainContext}s available to this rule. */
Kurt Alfred Kluever4192ca62022-07-05 06:30:29 -07001916 @CanIgnoreReturnValue
juliexxiab5f9d742020-04-09 13:07:13 -07001917 @VisibleForTesting
1918 public Builder setToolchainContexts(
1919 ToolchainCollection<ResolvedToolchainContext> toolchainContexts) {
1920 Preconditions.checkState(
1921 this.toolchainContexts == null,
1922 "toolchainContexts has already been set for this Builder");
1923 this.toolchainContexts = toolchainContexts;
John Cater13263f72017-05-24 19:06:47 +02001924 return this;
1925 }
1926
Kurt Alfred Kluever4192ca62022-07-05 06:30:29 -07001927 @CanIgnoreReturnValue
jcater645c42b2021-05-12 09:35:48 -07001928 public Builder setExecGroupCollectionBuilder(
1929 ExecGroupCollection.Builder execGroupCollectionBuilder) {
1930 this.execGroupCollectionBuilder = execGroupCollectionBuilder;
1931 return this;
1932 }
1933
juliexxia3eb806e2020-07-15 08:42:34 -07001934 /**
1935 * Warning: if you set the exec properties using this method any exec_properties attribute value
1936 * will be ignored in favor of this value.
1937 */
Kurt Alfred Kluever4192ca62022-07-05 06:30:29 -07001938 @CanIgnoreReturnValue
juliexxia3eb806e2020-07-15 08:42:34 -07001939 public Builder setExecProperties(ImmutableMap<String, String> execProperties) {
1940 this.rawExecProperties = execProperties;
1941 return this;
1942 }
1943
Kurt Alfred Kluever4192ca62022-07-05 06:30:29 -07001944 @CanIgnoreReturnValue
jhorvitz8128f522021-08-18 17:33:43 -07001945 public Builder setRequiredConfigFragments(
1946 @Nullable RequiredConfigFragmentsProvider requiredConfigFragments) {
gregce966dc232019-10-18 15:34:07 -07001947 this.requiredConfigFragments = requiredConfigFragments;
1948 return this;
1949 }
1950
Googler720dc5f2022-09-16 03:43:51 -07001951 @CanIgnoreReturnValue
1952 public Builder setTransitivePackagesForRunfileRepoMappingManifest(
1953 @Nullable NestedSet<Package> packages) {
1954 this.transitivePackagesForRunfileRepoMappingManifest = packages;
1955 return this;
1956 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001957
janakrf3e6f252018-01-18 07:45:12 -08001958 /** Determines and returns a map from attribute name to list of configured targets. */
janakr9c101402018-03-10 06:48:59 -08001959 private ImmutableSortedKeyListMultimap<String, ConfiguredTargetAndData> createTargetMap() {
1960 ImmutableSortedKeyListMultimap.Builder<String, ConfiguredTargetAndData> mapBuilder =
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001961 ImmutableSortedKeyListMultimap.builder();
1962
janakr9c101402018-03-10 06:48:59 -08001963 for (Map.Entry<Attribute, Collection<ConfiguredTargetAndData>> entry :
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001964 prerequisiteMap.asMap().entrySet()) {
1965 Attribute attribute = entry.getKey();
1966 if (attribute == null) {
1967 continue;
1968 }
lberki1cd6d1e2017-06-14 16:20:19 +02001969
1970 if (attribute.isSingleArtifact() && entry.getValue().size() > 1) {
1971 attributeError(attribute.getName(), "must contain a single dependency");
1972 continue;
1973 }
1974
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001975 if (attribute.isSilentRuleClassFilter()) {
Googlerf5924702022-12-08 14:55:42 -08001976 Predicate<String> filter = attribute.getAllowedRuleClassPredicate();
janakr9c101402018-03-10 06:48:59 -08001977 for (ConfiguredTargetAndData configuredTarget : entry.getValue()) {
Googlerf5924702022-12-08 14:55:42 -08001978 if (filter.apply(configuredTarget.getRuleClass())) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001979 validateDirectPrerequisite(attribute, configuredTarget);
1980 mapBuilder.put(attribute.getName(), configuredTarget);
1981 }
1982 }
1983 } else {
janakr9c101402018-03-10 06:48:59 -08001984 for (ConfiguredTargetAndData configuredTarget : entry.getValue()) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001985 validateDirectPrerequisite(attribute, configuredTarget);
1986 mapBuilder.put(attribute.getName(), configuredTarget);
1987 }
1988 }
1989 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001990 return mapBuilder.build();
1991 }
1992
Florian Weikertb8a6a942015-09-25 12:36:08 +00001993 @Override
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001994 public void ruleError(String message) {
Florian Weikertb8a6a942015-09-25 12:36:08 +00001995 reporter.ruleError(message);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001996 }
1997
Florian Weikertb8a6a942015-09-25 12:36:08 +00001998 @Override
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001999 public void attributeError(String attrName, String message) {
Florian Weikertb8a6a942015-09-25 12:36:08 +00002000 reporter.attributeError(attrName, message);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002001 }
2002
Florian Weikertb8a6a942015-09-25 12:36:08 +00002003 @Override
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002004 public void ruleWarning(String message) {
Florian Weikertb8a6a942015-09-25 12:36:08 +00002005 reporter.ruleWarning(message);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002006 }
2007
Florian Weikertb8a6a942015-09-25 12:36:08 +00002008 @Override
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002009 public void attributeWarning(String attrName, String message) {
Florian Weikertb8a6a942015-09-25 12:36:08 +00002010 reporter.attributeWarning(attrName, message);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002011 }
2012
cparsons0dcffc52017-10-13 23:40:31 +02002013 @Override
cparsons0dcffc52017-10-13 23:40:31 +02002014 public boolean hasErrors() {
2015 return reporter.hasErrors();
2016 }
2017
jhorvitz04816f52021-08-11 10:51:51 -07002018 private static String badPrerequisiteMessage(
lberkiee2dcae2018-03-28 05:49:04 -07002019 ConfiguredTargetAndData prerequisite, String reason, boolean isWarning) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002020 String msgReason = reason != null ? " (" + reason + ")" : "";
2021 if (isWarning) {
Googlere49cd592016-07-29 19:32:38 +00002022 return String.format(
lberkiee2dcae2018-03-28 05:49:04 -07002023 "%s is unexpected here%s; continuing anyway",
jhorvitzb6590822021-08-13 15:18:27 -07002024 AliasProvider.describeTargetWithAliases(prerequisite, TargetMode.WITH_KIND), msgReason);
Googlere49cd592016-07-29 19:32:38 +00002025 }
jhorvitzb6590822021-08-13 15:18:27 -07002026 return String.format(
2027 "%s is misplaced here%s",
lberkiee2dcae2018-03-28 05:49:04 -07002028 AliasProvider.describeTargetWithAliases(prerequisite, TargetMode.WITH_KIND), msgReason);
Googlere49cd592016-07-29 19:32:38 +00002029 }
2030
janakrf3e6f252018-01-18 07:45:12 -08002031 private void reportBadPrerequisite(
2032 Attribute attribute,
janakr9c101402018-03-10 06:48:59 -08002033 ConfiguredTargetAndData prerequisite,
janakrf3e6f252018-01-18 07:45:12 -08002034 String reason,
2035 boolean isWarning) {
lberkiee2dcae2018-03-28 05:49:04 -07002036 String message = badPrerequisiteMessage(prerequisite, reason, isWarning);
Googlere49cd592016-07-29 19:32:38 +00002037 if (isWarning) {
2038 attributeWarning(attribute.getName(), message);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002039 } else {
Googlere49cd592016-07-29 19:32:38 +00002040 attributeError(attribute.getName(), message);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002041 }
2042 }
2043
janakrf3e6f252018-01-18 07:45:12 -08002044 private void validateDirectPrerequisiteType(
janakr9c101402018-03-10 06:48:59 -08002045 ConfiguredTargetAndData prerequisite, Attribute attribute) {
Googlerf5924702022-12-08 14:55:42 -08002046 String ruleClass = prerequisite.getRuleClass();
2047 if (!ruleClass.isEmpty()) {
lpino5fe7ed02018-07-18 05:55:23 -07002048 String reason =
2049 attribute
2050 .getValidityPredicate()
Googlerf5924702022-12-08 14:55:42 -08002051 .checkValid(target.getAssociatedRule(), ruleClass, prerequisite.getRuleTags());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002052 if (reason != null) {
lberkiee2dcae2018-03-28 05:49:04 -07002053 reportBadPrerequisite(attribute, prerequisite, reason, false);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002054 }
Googlerf5924702022-12-08 14:55:42 -08002055 validateRuleDependency(prerequisite, attribute);
2056 return;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002057 }
2058
Googlerf5924702022-12-08 14:55:42 -08002059 if (!(prerequisite.isTargetFile() && attribute.isStrictLabelCheckingEnabled())) {
2060 return;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002061 }
Googlerf5924702022-12-08 14:55:42 -08002062
2063 Label prerequisiteTargetLabel = prerequisite.getTargetLabel();
2064 if (attribute.getAllowedFileTypesPredicate().apply(prerequisiteTargetLabel.getName())) {
2065 return;
2066 }
2067
2068 if (prerequisite.isTargetInputFile() && !prerequisite.getInputPath().exists()) {
2069 // Misplaced labels, no corresponding target exists
2070 if (attribute.getAllowedFileTypesPredicate().isNone()
2071 && !prerequisiteTargetLabel.getName().contains(".")) {
2072 // There are no allowed files in the attribute but it's not a valid rule,
2073 // and the filename doesn't contain a dot --> probably a misspelled rule
2074 attributeError(
2075 attribute.getName(), "rule '" + prerequisiteTargetLabel + "' does not exist");
2076 } else {
2077 attributeError(
2078 attribute.getName(), "target '" + prerequisiteTargetLabel + "' does not exist");
2079 }
2080 return;
2081 }
2082 // The file exists but has a bad extension
2083 reportBadPrerequisite(
2084 attribute, prerequisite, "expected " + attribute.getAllowedFileTypesPredicate(), false);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002085 }
2086
Michael Staib2707a882016-09-16 21:06:40 +00002087 /** Returns whether the context being constructed is for the evaluation of an aspect. */
2088 public boolean forAspect() {
dslomov44d15712017-12-20 05:42:28 -08002089 return !aspects.isEmpty();
Michael Staib2707a882016-09-16 21:06:40 +00002090 }
2091
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002092 public Rule getRule() {
lpino5fe7ed02018-07-18 05:55:23 -07002093 return target.getAssociatedRule();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002094 }
2095
Michael Staib8824d5e2016-01-20 21:37:05 +00002096 /**
jhorvitz2cdb6472021-10-06 14:22:36 -07002097 * Returns the {@link StarlarkSemantics} governs the building of this rule (and the rest of the
2098 * build).
Klaus Aehlig38053002019-10-29 09:54:32 -07002099 */
jhorvitz2cdb6472021-10-06 14:22:36 -07002100 public StarlarkSemantics getStarlarkSemantics() {
gregce61ec8d12020-05-18 11:02:05 -07002101 return env.getStarlarkSemantics();
Klaus Aehlig38053002019-10-29 09:54:32 -07002102 }
2103
2104 /**
Michael Staib8824d5e2016-01-20 21:37:05 +00002105 * Returns a rule class name suitable for log messages, including an aspect name if applicable.
2106 */
jhorvitz2cdb6472021-10-06 14:22:36 -07002107 private String getRuleClassNameForLogging() {
dslomov44d15712017-12-20 05:42:28 -08002108 if (aspects.isEmpty()) {
lpino5fe7ed02018-07-18 05:55:23 -07002109 return target.getAssociatedRule().getRuleClass();
Dmitry Lomov15756522016-12-16 16:52:37 +00002110 }
2111
dslomov44d15712017-12-20 05:42:28 -08002112 return Joiner.on(",")
jhorvitz04816f52021-08-11 10:51:51 -07002113 .join(aspects.stream().map(Aspect::getDescriptor).collect(Collectors.toList()))
dslomov44d15712017-12-20 05:42:28 -08002114 + " aspect on "
lpino5fe7ed02018-07-18 05:55:23 -07002115 + target.getAssociatedRule().getRuleClass();
Michael Staib8824d5e2016-01-20 21:37:05 +00002116 }
2117
jhorvitz33f76482021-10-28 10:13:26 -07002118 public BuildConfigurationValue getConfiguration() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002119 return configuration;
2120 }
2121
2122 /**
2123 * @return true if {@code rule} is visible from {@code prerequisite}.
jcater0de10972020-04-07 12:15:05 -07002124 * <p>This only computes the logic as implemented by the visibility system. The final
2125 * decision whether a dependency is allowed is made by {@link PrerequisiteValidator}, who is
2126 * supposed to call this method to determine whether a dependency is allowed as per
2127 * visibility rules.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002128 */
2129 public boolean isVisible(TransitiveInfoCollection prerequisite) {
lpino5fe7ed02018-07-18 05:55:23 -07002130 return RuleContext.isVisible(target.getAssociatedRule(), prerequisite);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002131 }
2132
janakrf3e6f252018-01-18 07:45:12 -08002133 private void validateDirectPrerequisiteFileTypes(
janakr9c101402018-03-10 06:48:59 -08002134 ConfiguredTargetAndData prerequisite, Attribute attribute) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002135 if (attribute.isSkipAnalysisTimeFileTypeCheck()) {
2136 return;
2137 }
2138 FileTypeSet allowedFileTypes = attribute.getAllowedFileTypesPredicate();
Ulf Adams788fd1a2015-03-12 13:54:09 +00002139 if (allowedFileTypes == null) {
2140 // It's not a label or label_list attribute.
2141 return;
2142 }
jhorvitzb6590822021-08-13 15:18:27 -07002143 if (allowedFileTypes == FileTypeSet.ANY_FILE
2144 && !attribute.isNonEmpty()
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002145 && !attribute.isSingleArtifact()) {
2146 return;
2147 }
2148
2149 // If we allow any file we still need to check if there are actually files generated
2150 // Note that this check only runs for ANY_FILE predicates if the attribute is NON_EMPTY
2151 // or SINGLE_ARTIFACT
2152 // If we performed this check when allowedFileTypes == NO_FILE this would
2153 // always throw an error in those cases
2154 if (allowedFileTypes != FileTypeSet.NO_FILE) {
Ulf Adamscd31d3b2019-12-16 00:50:03 -08002155 NestedSet<Artifact> artifacts =
janakrf3e6f252018-01-18 07:45:12 -08002156 prerequisite.getConfiguredTarget().getProvider(FileProvider.class).getFilesToBuild();
Ulf Adamscd31d3b2019-12-16 00:50:03 -08002157 if (attribute.isSingleArtifact() && !artifacts.isSingleton()) {
janakrf3e6f252018-01-18 07:45:12 -08002158 attributeError(
2159 attribute.getName(),
Googlerf5924702022-12-08 14:55:42 -08002160 "'" + prerequisite.getTargetLabel() + "' must produce a single file");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002161 return;
2162 }
Ulf Adamscd31d3b2019-12-16 00:50:03 -08002163 for (Artifact sourceArtifact : artifacts.toList()) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002164 if (allowedFileTypes.apply(sourceArtifact.getFilename())) {
2165 return;
2166 }
Googler2d90b6a2018-07-26 12:37:34 -07002167 if (sourceArtifact.isTreeArtifact()) {
2168 return;
2169 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002170 }
janakrf3e6f252018-01-18 07:45:12 -08002171 attributeError(
2172 attribute.getName(),
2173 "'"
Googlerf5924702022-12-08 14:55:42 -08002174 + prerequisite.getTargetLabel()
janakrf3e6f252018-01-18 07:45:12 -08002175 + "' does not produce any "
2176 + getRuleClassNameForLogging()
2177 + " "
2178 + attribute.getName()
2179 + " files (expected "
2180 + allowedFileTypes
2181 + ")");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002182 }
2183 }
2184
dslomov7df85152017-08-01 20:47:59 +02002185 /**
dslomovc13bb392017-08-02 23:29:54 +02002186 * Because some rules still have to use allowedRuleClasses to do rule dependency validation. A
2187 * dependency is valid if it is from a rule in allowedRuledClasses, OR if all of the providers
2188 * in requiredProviders are provided by the target.
dslomov7df85152017-08-01 20:47:59 +02002189 */
janakr9c101402018-03-10 06:48:59 -08002190 private void validateRuleDependency(ConfiguredTargetAndData prerequisite, Attribute attribute) {
dslomov7df85152017-08-01 20:47:59 +02002191
dslomovc13bb392017-08-02 23:29:54 +02002192 Set<String> unfulfilledRequirements = new LinkedHashSet<>();
2193 if (checkRuleDependencyClass(prerequisite, attribute, unfulfilledRequirements)) {
2194 return;
2195 }
2196
2197 if (checkRuleDependencyClassWarnings(prerequisite, attribute)) {
2198 return;
2199 }
2200
2201 if (checkRuleDependencyMandatoryProviders(prerequisite, attribute, unfulfilledRequirements)) {
2202 return;
2203 }
2204
2205 // not allowed rule class and some mandatory providers missing => reject.
2206 if (!unfulfilledRequirements.isEmpty()) {
2207 attributeError(
2208 attribute.getName(), StringUtil.joinEnglishList(unfulfilledRequirements, "and"));
2209 }
2210 }
2211
2212 /** Check if prerequisite should be allowed based on its rule class. */
jhorvitz04816f52021-08-11 10:51:51 -07002213 private static boolean checkRuleDependencyClass(
janakr9c101402018-03-10 06:48:59 -08002214 ConfiguredTargetAndData prerequisite,
janakrf3e6f252018-01-18 07:45:12 -08002215 Attribute attribute,
2216 Set<String> unfulfilledRequirements) {
Googlerf5924702022-12-08 14:55:42 -08002217 var predicate = attribute.getAllowedRuleClassPredicate();
2218 if (predicate == Predicates.<String>alwaysTrue()) {
2219 // alwaysTrue is a special sentinel value. See
2220 // RuleClass.Builder.RuleClassNamePredicate.unspecified.
2221 return false;
dslomovc32e1b12017-07-31 19:23:52 +02002222 }
Googlerf5924702022-12-08 14:55:42 -08002223
2224 if (predicate.apply(prerequisite.getRuleClass())) {
2225 // prerequisite has an allowed rule class => accept.
2226 return true;
2227 }
2228 // remember that the rule class that was not allowed;
2229 // but maybe prerequisite provides required providers? do not reject yet.
2230 unfulfilledRequirements.add(
2231 badPrerequisiteMessage(prerequisite, "expected " + predicate, false));
dslomovc13bb392017-08-02 23:29:54 +02002232 return false;
2233 }
dslomovc32e1b12017-07-31 19:23:52 +02002234
dslomovc13bb392017-08-02 23:29:54 +02002235 /**
2236 * Check if prerequisite should be allowed with warning based on its rule class.
2237 *
2238 * <p>If yes, also issues said warning.
2239 */
2240 private boolean checkRuleDependencyClassWarnings(
janakr9c101402018-03-10 06:48:59 -08002241 ConfiguredTargetAndData prerequisite, Attribute attribute) {
Googlerf5924702022-12-08 14:55:42 -08002242 if (!attribute.getAllowedRuleClassWarningPredicate().apply(prerequisite.getRuleClass())) {
2243 return false;
dslomovc13bb392017-08-02 23:29:54 +02002244 }
Googlerf5924702022-12-08 14:55:42 -08002245
2246 Predicate<String> allowedRuleClasses = attribute.getAllowedRuleClassPredicate();
2247 reportBadPrerequisite(
2248 attribute,
2249 prerequisite,
2250 allowedRuleClasses == Predicates.<String>alwaysTrue()
2251 ? null
2252 : "expected " + allowedRuleClasses,
2253 true);
2254 // prerequisite has a rule class allowed with a warning => accept, emitting a warning.
2255 return true;
dslomovc13bb392017-08-02 23:29:54 +02002256 }
2257
2258 /** Check if prerequisite should be allowed based on required providers on the attribute. */
jhorvitz04816f52021-08-11 10:51:51 -07002259 private static boolean checkRuleDependencyMandatoryProviders(
janakr9c101402018-03-10 06:48:59 -08002260 ConfiguredTargetAndData prerequisite,
janakrf3e6f252018-01-18 07:45:12 -08002261 Attribute attribute,
2262 Set<String> unfulfilledRequirements) {
dslomovc13bb392017-08-02 23:29:54 +02002263 RequiredProviders requiredProviders = attribute.getRequiredProviders();
2264
2265 if (requiredProviders.acceptsAny()) {
2266 // If no required providers specified, we do not know if we should accept.
2267 return false;
dslomovc32e1b12017-07-31 19:23:52 +02002268 }
2269
janakrf3e6f252018-01-18 07:45:12 -08002270 if (prerequisite.getConfiguredTarget().satisfies(requiredProviders)) {
dslomovc13bb392017-08-02 23:29:54 +02002271 return true;
dslomovc32e1b12017-07-31 19:23:52 +02002272 }
2273
dslomovc13bb392017-08-02 23:29:54 +02002274 unfulfilledRequirements.add(
2275 String.format(
2276 "'%s' does not have mandatory providers: %s",
Googlerf5924702022-12-08 14:55:42 -08002277 prerequisite.getTargetLabel(),
janakrf3e6f252018-01-18 07:45:12 -08002278 prerequisite
2279 .getConfiguredTarget()
2280 .missingProviders(requiredProviders)
2281 .getDescription()));
dslomovc32e1b12017-07-31 19:23:52 +02002282
dslomovc13bb392017-08-02 23:29:54 +02002283 return false;
dslomovc32e1b12017-07-31 19:23:52 +02002284 }
2285
janakrf3e6f252018-01-18 07:45:12 -08002286 private void validateDirectPrerequisite(
janakr9c101402018-03-10 06:48:59 -08002287 Attribute attribute, ConfiguredTargetAndData prerequisite) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002288 validateDirectPrerequisiteType(prerequisite, attribute);
2289 validateDirectPrerequisiteFileTypes(prerequisite, attribute);
Greg Estren875c7a72015-09-24 19:57:54 +00002290 if (attribute.performPrereqValidatorCheck()) {
jhorvitz2cdb6472021-10-06 14:22:36 -07002291 ruleClassProvider.getPrerequisiteValidator().validate(this, prerequisite, attribute);
Ulf Adams0b638972015-09-08 13:25:35 +00002292 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002293 }
2294 }
2295
ruperts8986b6e2017-10-17 00:26:29 +02002296 /** Helper class for reporting errors and warnings. */
cparsons963881a2018-10-03 14:23:55 -07002297 private static final class ErrorReporter extends EventHandlingErrorReporter
ruperts8986b6e2017-10-17 00:26:29 +02002298 implements RuleErrorConsumer {
Florian Weikertb8a6a942015-09-25 12:36:08 +00002299 private final Rule rule;
jhorvitz33f76482021-10-28 10:13:26 -07002300 private final BuildConfigurationValue configuration;
Florian Weikertb8a6a942015-09-25 12:36:08 +00002301
ulfjack07917642019-09-12 02:09:36 -07002302 ErrorReporter(
2303 AnalysisEnvironment env,
2304 Rule rule,
jhorvitz33f76482021-10-28 10:13:26 -07002305 BuildConfigurationValue configuration,
ulfjack07917642019-09-12 02:09:36 -07002306 String ruleClassNameForLogging) {
asteinbb82db782018-05-18 08:21:39 -07002307 super(ruleClassNameForLogging, env);
Florian Weikertb8a6a942015-09-25 12:36:08 +00002308 this.rule = rule;
ulfjack07917642019-09-12 02:09:36 -07002309 this.configuration = configuration;
Florian Weikertb8a6a942015-09-25 12:36:08 +00002310 }
2311
2312 @Override
Googler706d75b2019-09-18 10:09:07 -07002313 protected String getMacroMessageAppendix(String unusedAttrName) {
2314 // TODO(b/141234726): Historically this reported the location
2315 // of the rule attribute in the macro call (assuming no **kwargs),
2316 // but we no longer locations for individual attributes.
2317 // We should record the instantiation call stack in each rule
2318 // and report the position of its topmost frame here.
asteinbb82db782018-05-18 08:21:39 -07002319 return rule.wasCreatedByMacro()
2320 ? String.format(
2321 ". Since this rule was created by the macro '%s', the error might have been "
Googler706d75b2019-09-18 10:09:07 -07002322 + "caused by the macro implementation",
2323 getGeneratorFunction())
asteinbb82db782018-05-18 08:21:39 -07002324 : "";
Florian Weikertb8a6a942015-09-25 12:36:08 +00002325 }
2326
Florian Weikertb8a6a942015-09-25 12:36:08 +00002327 private String getGeneratorFunction() {
Googlera40c64a2020-08-11 16:39:39 -07002328 return (String) rule.getAttr("generator_function");
Florian Weikertb8a6a942015-09-25 12:36:08 +00002329 }
asteinbb82db782018-05-18 08:21:39 -07002330
2331 @Override
2332 protected Label getLabel() {
2333 return rule.getLabel();
2334 }
2335
2336 @Override
jhorvitz33f76482021-10-28 10:13:26 -07002337 protected BuildConfigurationValue getConfiguration() {
ulfjack07917642019-09-12 02:09:36 -07002338 return configuration;
2339 }
2340
2341 @Override
asteinbb82db782018-05-18 08:21:39 -07002342 protected Location getRuleLocation() {
2343 return rule.getLocation();
2344 }
cparsonse8d450c2018-10-04 16:01:53 -07002345 }
asteinbb82db782018-05-18 08:21:39 -07002346
cparsonse8d450c2018-10-04 16:01:53 -07002347 /**
2348 * Implementation of an error consumer which does not post any events, saves rule and attribute
2349 * errors for future consumption, and drops warnings.
2350 */
2351 public static final class SuppressingErrorReporter implements RuleErrorConsumer {
2352 private final List<String> errorMessages = Lists.newArrayList();
2353
2354 @Override
2355 public void ruleWarning(String message) {}
2356
2357 @Override
2358 public void ruleError(String message) {
2359 errorMessages.add(message);
2360 }
2361
2362 @Override
2363 public void attributeWarning(String attrName, String message) {}
2364
2365 @Override
2366 public void attributeError(String attrName, String message) {
2367 errorMessages.add(message);
2368 }
2369
2370 @Override
2371 public boolean hasErrors() {
2372 return !errorMessages.isEmpty();
2373 }
2374
jhorvitzb6590822021-08-13 15:18:27 -07002375 /** Returns the error message strings reported to this error consumer. */
cparsonse8d450c2018-10-04 16:01:53 -07002376 public List<String> getErrorMessages() {
2377 return errorMessages;
2378 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002379 }
2380}