blob: 897c0fc1779f9321c9423c5d02582d9596871c23 [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.
14package com.google.devtools.build.lib.skyframe;
15
16import com.google.common.base.Function;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010017import com.google.common.collect.ImmutableMap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010018import com.google.common.collect.Iterables;
Rumou Duan33bab462016-04-25 17:55:12 +000019import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010020import com.google.devtools.build.lib.analysis.ConfiguredTarget;
Michael Staib5e573fd2016-01-27 00:33:29 +000021import com.google.devtools.build.lib.analysis.Dependency;
Dmitry Lomovd83af9e2017-02-23 15:44:23 +000022import com.google.devtools.build.lib.analysis.DependencyResolver.InconsistentAspectOrderException;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010023import com.google.devtools.build.lib.analysis.LabelAndConfiguration;
24import com.google.devtools.build.lib.analysis.TargetAndConfiguration;
Greg Estren00049432015-08-25 16:43:47 +000025import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010026import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
gregce9dbe48b2017-09-20 00:35:36 +020027import com.google.devtools.build.lib.analysis.config.ConfigurationResolver;
Greg Estren373e3e22016-08-09 22:36:51 +000028import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000029import com.google.devtools.build.lib.cmdline.Label;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010030import com.google.devtools.build.lib.packages.Attribute;
Lukacs Berkiffa73ad2015-09-18 11:40:12 +000031import com.google.devtools.build.lib.packages.BuildType;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010032import com.google.devtools.build.lib.packages.RawAttributeMapper;
33import com.google.devtools.build.lib.packages.Rule;
Greg Estren00049432015-08-25 16:43:47 +000034import com.google.devtools.build.lib.packages.RuleClassProvider;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010035import com.google.devtools.build.lib.skyframe.SkyframeActionExecutor.ConflictException;
Greg Estren00049432015-08-25 16:43:47 +000036import com.google.devtools.build.lib.syntax.EvalException;
Greg Estrend5353252016-08-11 22:13:31 +000037import com.google.devtools.build.lib.util.OrderedSetMultimap;
Mark Schaller6df81792015-12-10 18:47:47 +000038import com.google.devtools.build.lib.util.Preconditions;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010039import com.google.devtools.build.skyframe.SkyFunction;
40import com.google.devtools.build.skyframe.SkyFunctionException;
41import com.google.devtools.build.skyframe.SkyKey;
42import com.google.devtools.build.skyframe.SkyValue;
Lukacs Berki53e03912016-05-19 16:26:09 +000043import java.util.LinkedHashMap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010044import java.util.LinkedHashSet;
45import java.util.Map;
46import java.util.Set;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010047import javax.annotation.Nullable;
48
49/**
50 * Build a post-processed ConfiguredTarget, vetting it for action conflict issues.
51 */
52public class PostConfiguredTargetFunction implements SkyFunction {
53 private static final Function<Dependency, SkyKey> TO_KEYS =
54 new Function<Dependency, SkyKey>() {
55 @Override
56 public SkyKey apply(Dependency input) {
57 return PostConfiguredTargetValue.key(
58 new ConfiguredTargetKey(input.getLabel(), input.getConfiguration()));
59 }
60 };
61
62 private final SkyframeExecutor.BuildViewProvider buildViewProvider;
Greg Estren00049432015-08-25 16:43:47 +000063 private final RuleClassProvider ruleClassProvider;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010064
65 public PostConfiguredTargetFunction(
Greg Estren00049432015-08-25 16:43:47 +000066 SkyframeExecutor.BuildViewProvider buildViewProvider,
67 RuleClassProvider ruleClassProvider) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010068 this.buildViewProvider = Preconditions.checkNotNull(buildViewProvider);
Greg Estren00049432015-08-25 16:43:47 +000069 this.ruleClassProvider = ruleClassProvider;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010070 }
71
72 @Nullable
73 @Override
Florian Weikert4b67d4f2015-09-14 13:35:34 +000074 public SkyValue compute(SkyKey skyKey, Environment env)
75 throws SkyFunctionException, InterruptedException {
Rumou Duan33bab462016-04-25 17:55:12 +000076 ImmutableMap<ActionAnalysisMetadata, ConflictException> badActions =
77 PrecomputedValue.BAD_ACTIONS.get(env);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010078 ConfiguredTargetValue ctValue = (ConfiguredTargetValue)
79 env.getValue(ConfiguredTargetValue.key((ConfiguredTargetKey) skyKey.argument()));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010080 if (env.valuesMissing()) {
81 return null;
82 }
83
Rumou Duan33bab462016-04-25 17:55:12 +000084 for (ActionAnalysisMetadata action : ctValue.getActions()) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010085 if (badActions.containsKey(action)) {
86 throw new ActionConflictFunctionException(badActions.get(action));
87 }
88 }
89
90 ConfiguredTarget ct = ctValue.getConfiguredTarget();
91 TargetAndConfiguration ctgValue =
92 new TargetAndConfiguration(ct.getTarget(), ct.getConfiguration());
93
Lukacs Berki7894c182016-05-10 12:07:01 +000094 ImmutableMap<Label, ConfigMatchingProvider> configConditions =
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010095 getConfigurableAttributeConditions(ctgValue, env);
96 if (configConditions == null) {
97 return null;
98 }
99
Greg Estrend5353252016-08-11 22:13:31 +0000100 OrderedSetMultimap<Attribute, Dependency> deps;
Greg Estren00049432015-08-25 16:43:47 +0000101 try {
102 BuildConfiguration hostConfiguration =
103 buildViewProvider.getSkyframeBuildView().getHostConfiguration(ct.getConfiguration());
Ulf Adamsd55d7af2016-01-19 11:03:22 +0000104 SkyframeDependencyResolver resolver =
105 buildViewProvider.getSkyframeBuildView().createDependencyResolver(env);
Ulf Adams84901732016-01-28 15:05:16 +0000106 // We don't track root causes here - this function is only invoked for successfully analyzed
107 // targets - as long as we redo the exact same steps here as in ConfiguredTargetFunction, this
108 // can never fail.
Dmitry Lomov6231d082015-11-02 17:17:20 +0000109 deps =
110 resolver.dependentNodeMap(
cpeyserb38e3af2017-09-11 16:58:58 +0200111 ctgValue,
112 hostConfiguration,
113 /*aspect=*/ null,
114 configConditions,
115 /*toolchainContext=*/ null);
gregce5bae50a2017-08-17 23:23:47 +0200116 if (ct.getConfiguration() != null) {
gregce9dbe48b2017-09-20 00:35:36 +0200117 deps = ConfigurationResolver.resolveConfigurations(env, ctgValue, deps, hostConfiguration,
118 ruleClassProvider);
Greg Estren00049432015-08-25 16:43:47 +0000119 }
Dmitry Lomovd83af9e2017-02-23 15:44:23 +0000120 } catch (EvalException | ConfiguredTargetFunction.DependencyEvaluationException
121 | InvalidConfigurationException | InconsistentAspectOrderException e) {
Greg Estren373e3e22016-08-09 22:36:51 +0000122 throw new PostConfiguredTargetFunctionException(e);
Greg Estren00049432015-08-25 16:43:47 +0000123 }
124
125 env.getValues(Iterables.transform(deps.values(), TO_KEYS));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100126 if (env.valuesMissing()) {
127 return null;
128 }
129
130 return new PostConfiguredTargetValue(ct);
131 }
132
133 /**
134 * Returns the configurable attribute conditions necessary to evaluate the given configured
135 * target, or null if not all dependencies have yet been SkyFrame-evaluated.
136 */
137 @Nullable
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000138 private static ImmutableMap<Label, ConfigMatchingProvider> getConfigurableAttributeConditions(
139 TargetAndConfiguration ctg, Environment env) throws InterruptedException {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100140 if (!(ctg.getTarget() instanceof Rule)) {
Lukacs Berki7894c182016-05-10 12:07:01 +0000141 return ImmutableMap.of();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100142 }
143 Rule rule = (Rule) ctg.getTarget();
144 RawAttributeMapper mapper = RawAttributeMapper.of(rule);
145 Set<SkyKey> depKeys = new LinkedHashSet<>();
146 for (Attribute attribute : rule.getAttributes()) {
147 for (Label label : mapper.getConfigurabilityKeys(attribute.getName(), attribute.getType())) {
Lukacs Berkiffa73ad2015-09-18 11:40:12 +0000148 if (!BuildType.Selector.isReservedLabel(label)) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100149 depKeys.add(ConfiguredTargetValue.key(label, ctg.getConfiguration()));
150 }
151 }
152 }
153 Map<SkyKey, SkyValue> cts = env.getValues(depKeys);
154 if (env.valuesMissing()) {
155 return null;
156 }
Lukacs Berki53e03912016-05-19 16:26:09 +0000157 Map<Label, ConfigMatchingProvider> conditions = new LinkedHashMap<>();
Lukacs Berki7894c182016-05-10 12:07:01 +0000158 for (Map.Entry<SkyKey, SkyValue> entry : cts.entrySet()) {
159 Label label = ((ConfiguredTargetKey) entry.getKey().argument()).getLabel();
160 ConfiguredTarget ct = ((ConfiguredTargetValue) entry.getValue()).getConfiguredTarget();
161 conditions.put(label, Preconditions.checkNotNull(
162 ct.getProvider(ConfigMatchingProvider.class)));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100163 }
Lukacs Berki53e03912016-05-19 16:26:09 +0000164 return ImmutableMap.copyOf(conditions);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100165 }
166
167 @Nullable
168 @Override
169 public String extractTag(SkyKey skyKey) {
170 return Label.print(((LabelAndConfiguration) skyKey.argument()).getLabel());
171 }
172
173 private static class ActionConflictFunctionException extends SkyFunctionException {
174 public ActionConflictFunctionException(ConflictException e) {
175 super(e, Transience.PERSISTENT);
176 }
177 }
Greg Estren00049432015-08-25 16:43:47 +0000178
179 private static class PostConfiguredTargetFunctionException extends SkyFunctionException {
180 public PostConfiguredTargetFunctionException(Exception e) {
181 super(e, Transience.PERSISTENT);
182 }
183 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100184}