Damien Martin-Guillerez | f88f4d8 | 2015-09-25 13:56:55 +0000 | [diff] [blame] | 1 | // Copyright 2014 The Bazel Authors. All rights reserved. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 2 | // |
| 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 | package com.google.devtools.build.lib.skyframe; |
| 15 | |
| 16 | import com.google.common.base.Function; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 17 | import com.google.common.collect.ImmutableMap; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 18 | import com.google.common.collect.Iterables; |
Rumou Duan | 33bab46 | 2016-04-25 17:55:12 +0000 | [diff] [blame] | 19 | import com.google.devtools.build.lib.actions.ActionAnalysisMetadata; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 20 | import com.google.devtools.build.lib.analysis.ConfiguredTarget; |
Michael Staib | 5e573fd | 2016-01-27 00:33:29 +0000 | [diff] [blame] | 21 | import com.google.devtools.build.lib.analysis.Dependency; |
Dmitry Lomov | d83af9e | 2017-02-23 15:44:23 +0000 | [diff] [blame] | 22 | import com.google.devtools.build.lib.analysis.DependencyResolver.InconsistentAspectOrderException; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 23 | import com.google.devtools.build.lib.analysis.LabelAndConfiguration; |
| 24 | import com.google.devtools.build.lib.analysis.TargetAndConfiguration; |
Greg Estren | 0004943 | 2015-08-25 16:43:47 +0000 | [diff] [blame] | 25 | import com.google.devtools.build.lib.analysis.config.BuildConfiguration; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 26 | import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider; |
gregce | 9dbe48b | 2017-09-20 00:35:36 +0200 | [diff] [blame] | 27 | import com.google.devtools.build.lib.analysis.config.ConfigurationResolver; |
Greg Estren | 373e3e2 | 2016-08-09 22:36:51 +0000 | [diff] [blame] | 28 | import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; |
Lukacs Berki | 6e91eb9 | 2015-09-21 09:12:37 +0000 | [diff] [blame] | 29 | import com.google.devtools.build.lib.cmdline.Label; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 30 | import com.google.devtools.build.lib.packages.Attribute; |
Lukacs Berki | ffa73ad | 2015-09-18 11:40:12 +0000 | [diff] [blame] | 31 | import com.google.devtools.build.lib.packages.BuildType; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 32 | import com.google.devtools.build.lib.packages.RawAttributeMapper; |
| 33 | import com.google.devtools.build.lib.packages.Rule; |
Greg Estren | 0004943 | 2015-08-25 16:43:47 +0000 | [diff] [blame] | 34 | import com.google.devtools.build.lib.packages.RuleClassProvider; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 35 | import com.google.devtools.build.lib.skyframe.SkyframeActionExecutor.ConflictException; |
Greg Estren | 0004943 | 2015-08-25 16:43:47 +0000 | [diff] [blame] | 36 | import com.google.devtools.build.lib.syntax.EvalException; |
Greg Estren | d535325 | 2016-08-11 22:13:31 +0000 | [diff] [blame] | 37 | import com.google.devtools.build.lib.util.OrderedSetMultimap; |
Mark Schaller | 6df8179 | 2015-12-10 18:47:47 +0000 | [diff] [blame] | 38 | import com.google.devtools.build.lib.util.Preconditions; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 39 | import com.google.devtools.build.skyframe.SkyFunction; |
| 40 | import com.google.devtools.build.skyframe.SkyFunctionException; |
| 41 | import com.google.devtools.build.skyframe.SkyKey; |
| 42 | import com.google.devtools.build.skyframe.SkyValue; |
Lukacs Berki | 53e0391 | 2016-05-19 16:26:09 +0000 | [diff] [blame] | 43 | import java.util.LinkedHashMap; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 44 | import java.util.LinkedHashSet; |
| 45 | import java.util.Map; |
| 46 | import java.util.Set; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 47 | import javax.annotation.Nullable; |
| 48 | |
| 49 | /** |
| 50 | * Build a post-processed ConfiguredTarget, vetting it for action conflict issues. |
| 51 | */ |
| 52 | public 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 Estren | 0004943 | 2015-08-25 16:43:47 +0000 | [diff] [blame] | 63 | private final RuleClassProvider ruleClassProvider; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 64 | |
| 65 | public PostConfiguredTargetFunction( |
Greg Estren | 0004943 | 2015-08-25 16:43:47 +0000 | [diff] [blame] | 66 | SkyframeExecutor.BuildViewProvider buildViewProvider, |
| 67 | RuleClassProvider ruleClassProvider) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 68 | this.buildViewProvider = Preconditions.checkNotNull(buildViewProvider); |
Greg Estren | 0004943 | 2015-08-25 16:43:47 +0000 | [diff] [blame] | 69 | this.ruleClassProvider = ruleClassProvider; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 70 | } |
| 71 | |
| 72 | @Nullable |
| 73 | @Override |
Florian Weikert | 4b67d4f | 2015-09-14 13:35:34 +0000 | [diff] [blame] | 74 | public SkyValue compute(SkyKey skyKey, Environment env) |
| 75 | throws SkyFunctionException, InterruptedException { |
Rumou Duan | 33bab46 | 2016-04-25 17:55:12 +0000 | [diff] [blame] | 76 | ImmutableMap<ActionAnalysisMetadata, ConflictException> badActions = |
| 77 | PrecomputedValue.BAD_ACTIONS.get(env); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 78 | ConfiguredTargetValue ctValue = (ConfiguredTargetValue) |
| 79 | env.getValue(ConfiguredTargetValue.key((ConfiguredTargetKey) skyKey.argument())); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 80 | if (env.valuesMissing()) { |
| 81 | return null; |
| 82 | } |
| 83 | |
Rumou Duan | 33bab46 | 2016-04-25 17:55:12 +0000 | [diff] [blame] | 84 | for (ActionAnalysisMetadata action : ctValue.getActions()) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 85 | 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 Berki | 7894c18 | 2016-05-10 12:07:01 +0000 | [diff] [blame] | 94 | ImmutableMap<Label, ConfigMatchingProvider> configConditions = |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 95 | getConfigurableAttributeConditions(ctgValue, env); |
| 96 | if (configConditions == null) { |
| 97 | return null; |
| 98 | } |
| 99 | |
Greg Estren | d535325 | 2016-08-11 22:13:31 +0000 | [diff] [blame] | 100 | OrderedSetMultimap<Attribute, Dependency> deps; |
Greg Estren | 0004943 | 2015-08-25 16:43:47 +0000 | [diff] [blame] | 101 | try { |
| 102 | BuildConfiguration hostConfiguration = |
| 103 | buildViewProvider.getSkyframeBuildView().getHostConfiguration(ct.getConfiguration()); |
Ulf Adams | d55d7af | 2016-01-19 11:03:22 +0000 | [diff] [blame] | 104 | SkyframeDependencyResolver resolver = |
| 105 | buildViewProvider.getSkyframeBuildView().createDependencyResolver(env); |
Ulf Adams | 8490173 | 2016-01-28 15:05:16 +0000 | [diff] [blame] | 106 | // 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 Lomov | 6231d08 | 2015-11-02 17:17:20 +0000 | [diff] [blame] | 109 | deps = |
| 110 | resolver.dependentNodeMap( |
cpeyser | b38e3af | 2017-09-11 16:58:58 +0200 | [diff] [blame] | 111 | ctgValue, |
| 112 | hostConfiguration, |
| 113 | /*aspect=*/ null, |
| 114 | configConditions, |
| 115 | /*toolchainContext=*/ null); |
gregce | 5bae50a | 2017-08-17 23:23:47 +0200 | [diff] [blame] | 116 | if (ct.getConfiguration() != null) { |
gregce | 9dbe48b | 2017-09-20 00:35:36 +0200 | [diff] [blame] | 117 | deps = ConfigurationResolver.resolveConfigurations(env, ctgValue, deps, hostConfiguration, |
| 118 | ruleClassProvider); |
Greg Estren | 0004943 | 2015-08-25 16:43:47 +0000 | [diff] [blame] | 119 | } |
Dmitry Lomov | d83af9e | 2017-02-23 15:44:23 +0000 | [diff] [blame] | 120 | } catch (EvalException | ConfiguredTargetFunction.DependencyEvaluationException |
| 121 | | InvalidConfigurationException | InconsistentAspectOrderException e) { |
Greg Estren | 373e3e2 | 2016-08-09 22:36:51 +0000 | [diff] [blame] | 122 | throw new PostConfiguredTargetFunctionException(e); |
Greg Estren | 0004943 | 2015-08-25 16:43:47 +0000 | [diff] [blame] | 123 | } |
| 124 | |
| 125 | env.getValues(Iterables.transform(deps.values(), TO_KEYS)); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 126 | 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 Ramakrishnan | 3c0adb2 | 2016-08-15 21:54:55 +0000 | [diff] [blame] | 138 | private static ImmutableMap<Label, ConfigMatchingProvider> getConfigurableAttributeConditions( |
| 139 | TargetAndConfiguration ctg, Environment env) throws InterruptedException { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 140 | if (!(ctg.getTarget() instanceof Rule)) { |
Lukacs Berki | 7894c18 | 2016-05-10 12:07:01 +0000 | [diff] [blame] | 141 | return ImmutableMap.of(); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 142 | } |
| 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 Berki | ffa73ad | 2015-09-18 11:40:12 +0000 | [diff] [blame] | 148 | if (!BuildType.Selector.isReservedLabel(label)) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 149 | 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 Berki | 53e0391 | 2016-05-19 16:26:09 +0000 | [diff] [blame] | 157 | Map<Label, ConfigMatchingProvider> conditions = new LinkedHashMap<>(); |
Lukacs Berki | 7894c18 | 2016-05-10 12:07:01 +0000 | [diff] [blame] | 158 | 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 Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 163 | } |
Lukacs Berki | 53e0391 | 2016-05-19 16:26:09 +0000 | [diff] [blame] | 164 | return ImmutableMap.copyOf(conditions); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 165 | } |
| 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 Estren | 0004943 | 2015-08-25 16:43:47 +0000 | [diff] [blame] | 178 | |
| 179 | private static class PostConfiguredTargetFunctionException extends SkyFunctionException { |
| 180 | public PostConfiguredTargetFunctionException(Exception e) { |
| 181 | super(e, Transience.PERSISTENT); |
| 182 | } |
| 183 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 184 | } |