blob: 9e24416067972a8ba677099e8cb506ef08340758 [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
tomlua155b532017-11-08 20:12:47 +010016import com.google.common.base.Preconditions;
janakrb6823b02019-04-12 13:57:02 -070017import com.google.common.base.Stopwatch;
Greg Estren00049432015-08-25 16:43:47 +000018import com.google.common.collect.ImmutableList;
Lukacs Berki7894c182016-05-10 12:07:01 +000019import com.google.common.collect.ImmutableMap;
John Cater3a0ce772017-08-09 21:09:53 +020020import com.google.common.collect.ImmutableSet;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010021import com.google.common.collect.Iterables;
Ulf Adams7cb66de2016-01-14 08:46:43 +000022import com.google.common.collect.Maps;
jcater1f724162018-08-27 09:16:01 -070023import com.google.common.collect.Streams;
janakrb5ace952019-04-08 17:44:08 -070024import com.google.common.flogger.GoogleLogger;
Janak Ramakrishnanb3a6ca72015-03-27 20:07:28 +000025import com.google.devtools.build.lib.actions.Actions;
janakr93e3eea2017-03-30 22:09:37 +000026import com.google.devtools.build.lib.actions.Actions.GeneratingActions;
Janak Ramakrishnanb3a6ca72015-03-27 20:07:28 +000027import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
gregce4c3ef112017-09-20 23:43:14 +020028import com.google.devtools.build.lib.analysis.AspectResolver;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010029import com.google.devtools.build.lib.analysis.CachingAnalysisEnvironment;
Dmitry Lomovb487ac62015-11-09 13:09:12 +000030import com.google.devtools.build.lib.analysis.ConfiguredAspect;
mstaib4a07a472018-04-19 14:16:41 -070031import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010032import com.google.devtools.build.lib.analysis.ConfiguredTarget;
Michael Staib5e573fd2016-01-27 00:33:29 +000033import com.google.devtools.build.lib.analysis.Dependency;
lberki102256f2019-02-08 01:34:23 -080034import com.google.devtools.build.lib.analysis.DependencyResolver;
lberki4cd44472019-02-06 08:36:34 -080035import com.google.devtools.build.lib.analysis.DependencyResolver.DependencyKind;
Dmitry Lomovd83af9e2017-02-23 15:44:23 +000036import com.google.devtools.build.lib.analysis.DependencyResolver.InconsistentAspectOrderException;
lberki1161e732019-02-18 05:07:04 -080037import com.google.devtools.build.lib.analysis.EmptyConfiguredTarget;
John Catercdfa9ca2019-04-05 12:32:09 -070038import com.google.devtools.build.lib.analysis.ResolvedToolchainContext;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010039import com.google.devtools.build.lib.analysis.TargetAndConfiguration;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010040import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
mjhalupka5d7fa7b2018-03-22 13:37:38 -070041import com.google.devtools.build.lib.analysis.config.BuildOptions;
mstaib794a0202019-04-23 17:56:02 -070042import com.google.devtools.build.lib.analysis.config.BuildOptions.OptionsDiffForReconstruction;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010043import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
gregce9dbe48b2017-09-20 00:35:36 +020044import com.google.devtools.build.lib.analysis.config.ConfigurationResolver;
Greg Estren00049432015-08-25 16:43:47 +000045import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
gregce2aee44b2017-09-16 07:16:44 +020046import com.google.devtools.build.lib.analysis.configuredtargets.MergedConfiguredTarget.DuplicateException;
cparsonse2d200f2018-03-06 16:15:11 -080047import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
juliexxiab4519fb2019-01-16 07:43:00 -080048import com.google.devtools.build.lib.analysis.skylark.StarlarkTransition.TransitionException;
Klaus Aehligfbdeffe2018-01-26 02:19:58 -080049import com.google.devtools.build.lib.buildeventstream.BuildEventId;
ulfjack904a8d62018-05-29 05:17:35 -070050import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildEventId.ConfigurationId;
51import com.google.devtools.build.lib.causes.AnalysisFailedCause;
52import com.google.devtools.build.lib.causes.Cause;
53import com.google.devtools.build.lib.causes.LoadingFailedCause;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000054import com.google.devtools.build.lib.cmdline.Label;
Ulf Adams84901732016-01-28 15:05:16 +000055import com.google.devtools.build.lib.collect.nestedset.NestedSet;
Marian Loburc62faba2015-09-09 10:08:06 +000056import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
Ulf Adams84901732016-01-28 15:05:16 +000057import com.google.devtools.build.lib.collect.nestedset.Order;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010058import com.google.devtools.build.lib.events.Event;
ulfjack904a8d62018-05-29 05:17:35 -070059import com.google.devtools.build.lib.events.EventKind;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010060import com.google.devtools.build.lib.events.StoredEventHandler;
Dmitry Lomovb487ac62015-11-09 13:09:12 +000061import com.google.devtools.build.lib.packages.Aspect;
Lukacs Berkiffa73ad2015-09-18 11:40:12 +000062import com.google.devtools.build.lib.packages.BuildType;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010063import com.google.devtools.build.lib.packages.NoSuchTargetException;
John Cateree45c662018-06-05 11:09:01 -070064import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper;
Marian Loburc62faba2015-09-09 10:08:06 +000065import com.google.devtools.build.lib.packages.Package;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010066import com.google.devtools.build.lib.packages.RawAttributeMapper;
67import com.google.devtools.build.lib.packages.Rule;
gregce749962a2019-03-08 12:47:34 -080068import com.google.devtools.build.lib.packages.RuleClass;
John Cateree45c662018-06-05 11:09:01 -070069import com.google.devtools.build.lib.packages.RuleClass.ExecutionPlatformConstraintsAllowed;
Greg Estren00049432015-08-25 16:43:47 +000070import com.google.devtools.build.lib.packages.RuleClassProvider;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010071import com.google.devtools.build.lib.packages.Target;
72import com.google.devtools.build.lib.packages.TargetUtils;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010073import com.google.devtools.build.lib.skyframe.AspectFunction.AspectCreationException;
74import com.google.devtools.build.lib.skyframe.SkyframeExecutor.BuildViewProvider;
janakr00408d62018-03-24 17:22:23 -070075import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
mstaib794a0202019-04-23 17:56:02 -070076import com.google.devtools.build.lib.skyframe.trimming.TrimmedConfigurationCache;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010077import com.google.devtools.build.lib.syntax.EvalException;
Greg Estrend5353252016-08-11 22:13:31 +000078import com.google.devtools.build.lib.util.OrderedSetMultimap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010079import com.google.devtools.build.skyframe.SkyFunction;
80import com.google.devtools.build.skyframe.SkyFunctionException;
81import com.google.devtools.build.skyframe.SkyKey;
82import com.google.devtools.build.skyframe.SkyValue;
Greg Estren00049432015-08-25 16:43:47 +000083import com.google.devtools.build.skyframe.ValueOrException;
janakra81bb952019-01-28 17:30:06 -080084import java.math.BigInteger;
janakrf3e6f252018-01-18 07:45:12 -080085import java.util.ArrayList;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010086import java.util.Collection;
janakrf3e6f252018-01-18 07:45:12 -080087import java.util.HashSet;
Lukacs Berki7894c182016-05-10 12:07:01 +000088import java.util.LinkedHashMap;
janakrf3e6f252018-01-18 07:45:12 -080089import java.util.List;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010090import java.util.Map;
juliexxiab4519fb2019-01-16 07:43:00 -080091import java.util.Objects;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010092import java.util.Set;
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +000093import java.util.concurrent.Semaphore;
janakrb6823b02019-04-12 13:57:02 -070094import java.util.concurrent.TimeUnit;
janakra81bb952019-01-28 17:30:06 -080095import java.util.function.Supplier;
ulfjack904a8d62018-05-29 05:17:35 -070096import java.util.stream.Collectors;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010097import javax.annotation.Nullable;
98
99/**
100 * SkyFunction for {@link ConfiguredTargetValue}s.
Lukacs Berki2300cd62016-05-19 11:06:37 +0000101 *
John Cater2e56f062017-07-20 19:43:20 +0200102 * <p>This class, together with {@link AspectFunction} drives the analysis phase. For more
ulfjack26d0e492017-08-07 13:42:33 +0200103 * information, see {@link com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory}.
Lukacs Berki2300cd62016-05-19 11:06:37 +0000104 *
ulfjack26d0e492017-08-07 13:42:33 +0200105 * @see com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100106 */
John Cater2e56f062017-07-20 19:43:20 +0200107public final class ConfiguredTargetFunction implements SkyFunction {
janakrb5ace952019-04-08 17:44:08 -0700108 private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();
109
janakrb6823b02019-04-12 13:57:02 -0700110 private static final ImmutableMap<Label, ConfigMatchingProvider> NO_CONFIG_CONDITIONS =
111 ImmutableMap.of();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100112
113 /**
114 * Exception class that signals an error during the evaluation of a dependency.
115 */
116 public static class DependencyEvaluationException extends Exception {
Ulf Adams25f03d82016-01-25 10:31:46 +0000117 public DependencyEvaluationException(InvalidConfigurationException cause) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100118 super(cause);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100119 }
120
Ulf Adams25f03d82016-01-25 10:31:46 +0000121 public DependencyEvaluationException(ConfiguredValueCreationException cause) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100122 super(cause);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100123 }
124
Dmitry Lomovd83af9e2017-02-23 15:44:23 +0000125 public DependencyEvaluationException(InconsistentAspectOrderException cause) {
126 super(cause);
127 }
128
juliexxiab4519fb2019-01-16 07:43:00 -0800129 public DependencyEvaluationException(TransitionException cause) {
130 super(cause);
131 }
132
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100133 @Override
Ulf Adams25f03d82016-01-25 10:31:46 +0000134 public synchronized Exception getCause() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100135 return (Exception) super.getCause();
136 }
137 }
138
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100139 private final BuildViewProvider buildViewProvider;
Greg Estren00049432015-08-25 16:43:47 +0000140 private final RuleClassProvider ruleClassProvider;
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +0000141 private final Semaphore cpuBoundSemaphore;
mjhalupka5d7fa7b2018-03-22 13:37:38 -0700142 private final BuildOptions defaultBuildOptions;
Googlerf526ed02018-09-20 03:59:54 -0700143 @Nullable private final ConfiguredTargetProgressReceiver configuredTargetProgress;
janakra81bb952019-01-28 17:30:06 -0800144 private final Supplier<BigInteger> nonceVersion;
145
janakr931d2852017-12-15 13:48:29 -0800146 /**
147 * Indicates whether the set of packages transitively loaded for a given {@link
148 * ConfiguredTargetValue} will be needed for package root resolution later in the build. If not,
149 * they are not collected and stored.
150 */
151 private final boolean storeTransitivePackagesForPackageRootResolution;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100152
janakr500e17b2018-03-28 15:26:04 -0700153 private final boolean shouldUnblockCpuWorkWhenFetchingDeps;
154
mstaib794a0202019-04-23 17:56:02 -0700155 private final TrimmedConfigurationCache<SkyKey, Label, OptionsDiffForReconstruction>
156 configuredTargetCache;
157
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +0000158 ConfiguredTargetFunction(
159 BuildViewProvider buildViewProvider,
160 RuleClassProvider ruleClassProvider,
janakr93e3eea2017-03-30 22:09:37 +0000161 Semaphore cpuBoundSemaphore,
mjhalupka5d7fa7b2018-03-22 13:37:38 -0700162 boolean storeTransitivePackagesForPackageRootResolution,
janakr500e17b2018-03-28 15:26:04 -0700163 boolean shouldUnblockCpuWorkWhenFetchingDeps,
Googlerf526ed02018-09-20 03:59:54 -0700164 BuildOptions defaultBuildOptions,
janakra81bb952019-01-28 17:30:06 -0800165 @Nullable ConfiguredTargetProgressReceiver configuredTargetProgress,
mstaib794a0202019-04-23 17:56:02 -0700166 Supplier<BigInteger> nonceVersion,
167 TrimmedConfigurationCache<SkyKey, Label, OptionsDiffForReconstruction>
168 configuredTargetCache) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100169 this.buildViewProvider = buildViewProvider;
Greg Estren00049432015-08-25 16:43:47 +0000170 this.ruleClassProvider = ruleClassProvider;
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +0000171 this.cpuBoundSemaphore = cpuBoundSemaphore;
janakr931d2852017-12-15 13:48:29 -0800172 this.storeTransitivePackagesForPackageRootResolution =
173 storeTransitivePackagesForPackageRootResolution;
janakr500e17b2018-03-28 15:26:04 -0700174 this.shouldUnblockCpuWorkWhenFetchingDeps = shouldUnblockCpuWorkWhenFetchingDeps;
mjhalupka5d7fa7b2018-03-22 13:37:38 -0700175 this.defaultBuildOptions = defaultBuildOptions;
Googlerf526ed02018-09-20 03:59:54 -0700176 this.configuredTargetProgress = configuredTargetProgress;
janakra81bb952019-01-28 17:30:06 -0800177 this.nonceVersion = nonceVersion;
mstaib794a0202019-04-23 17:56:02 -0700178 this.configuredTargetCache = configuredTargetCache;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100179 }
180
janakrb6823b02019-04-12 13:57:02 -0700181 private void acquireWithLogging(SkyKey key) throws InterruptedException {
182 Stopwatch stopwatch = Stopwatch.createStarted();
183 cpuBoundSemaphore.acquire();
184 long elapsedTime = stopwatch.elapsed().toMillis();
185 if (elapsedTime > 5) {
186 logger.atInfo().atMostEvery(10, TimeUnit.SECONDS).log(
187 "Spent %s milliseconds waiting for lock acquisition for %s", elapsedTime, key);
188 }
189 }
190
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100191 @Override
192 public SkyValue compute(SkyKey key, Environment env) throws ConfiguredTargetFunctionException,
193 InterruptedException {
janakr500e17b2018-03-28 15:26:04 -0700194 if (shouldUnblockCpuWorkWhenFetchingDeps) {
195 env =
196 new StateInformingSkyFunctionEnvironment(
197 env,
198 /*preFetch=*/ cpuBoundSemaphore::release,
janakrb6823b02019-04-12 13:57:02 -0700199 /*postFetch=*/ () -> acquireWithLogging(key));
janakr500e17b2018-03-28 15:26:04 -0700200 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100201 SkyframeBuildView view = buildViewProvider.getSkyframeBuildView();
janakr931d2852017-12-15 13:48:29 -0800202 NestedSetBuilder<Package> transitivePackagesForPackageRootResolution =
203 storeTransitivePackagesForPackageRootResolution ? NestedSetBuilder.stableOrder() : null;
ulfjack904a8d62018-05-29 05:17:35 -0700204 NestedSetBuilder<Cause> transitiveRootCauses = NestedSetBuilder.stableOrder();
janakr3863b532018-01-11 15:49:42 -0800205
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100206 ConfiguredTargetKey configuredTargetKey = (ConfiguredTargetKey) key.argument();
janakrac2cd352017-12-20 13:37:13 -0800207 Label label = configuredTargetKey.getLabel();
janakr3863b532018-01-11 15:49:42 -0800208 BuildConfiguration configuration = null;
209 ImmutableSet<SkyKey> packageAndMaybeConfiguration;
210 SkyKey packageKey = PackageValue.key(label.getPackageIdentifier());
211 SkyKey configurationKeyMaybe = configuredTargetKey.getConfigurationKey();
212 if (configurationKeyMaybe == null) {
213 packageAndMaybeConfiguration = ImmutableSet.of(packageKey);
214 } else {
215 packageAndMaybeConfiguration = ImmutableSet.of(packageKey, configurationKeyMaybe);
216 }
217 Map<SkyKey, SkyValue> packageAndMaybeConfigurationValues =
218 env.getValues(packageAndMaybeConfiguration);
219 if (env.valuesMissing()) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100220 return null;
221 }
janakr3863b532018-01-11 15:49:42 -0800222 PackageValue packageValue = (PackageValue) packageAndMaybeConfigurationValues.get(packageKey);
223 if (configurationKeyMaybe != null) {
224 configuration =
225 ((BuildConfigurationValue) packageAndMaybeConfigurationValues.get(configurationKeyMaybe))
226 .getConfiguration();
227 }
Ulf Adams2ac20962016-02-01 13:04:54 +0000228
229 // TODO(ulfjack): This tries to match the logic in TransitiveTargetFunction /
230 // TargetMarkerFunction. Maybe we can merge the two?
Janak Ramakrishnan0a4c6e42015-09-17 00:37:58 +0000231 Package pkg = packageValue.getPackage();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100232 Target target;
233 try {
janakrac2cd352017-12-20 13:37:13 -0800234 target = pkg.getTarget(label.getName());
Ulf Adams96683612016-01-25 09:04:54 +0000235 } catch (NoSuchTargetException e) {
Ulf Adams2ac20962016-02-01 13:04:54 +0000236 throw new ConfiguredTargetFunctionException(
Klaus Aehligfbdeffe2018-01-26 02:19:58 -0800237 new ConfiguredValueCreationException(e.getMessage(), label, configuration));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100238 }
Ulf Adams2ac20962016-02-01 13:04:54 +0000239 if (pkg.containsErrors()) {
ulfjack904a8d62018-05-29 05:17:35 -0700240 transitiveRootCauses.add(
241 new LoadingFailedCause(label, new NoSuchTargetException(target).getMessage()));
Ulf Adams2ac20962016-02-01 13:04:54 +0000242 }
janakr931d2852017-12-15 13:48:29 -0800243 if (transitivePackagesForPackageRootResolution != null) {
244 transitivePackagesForPackageRootResolution.add(pkg);
245 }
lberkia1f2ddb2019-03-04 23:43:25 -0800246 if (target.isConfigurable() != (configuredTargetKey.getConfigurationKey() != null)) {
lberki1161e732019-02-18 05:07:04 -0800247 // We somehow ended up in a target that requires a non-null configuration as a dependency of
lberkia1f2ddb2019-03-04 23:43:25 -0800248 // one that requires a null configuration or the other way round. This is always an error, but
249 // we need to analyze the dependencies of the latter target to realize that. Short-circuit the
250 // evaluation to avoid doing useless work and running code with a null configuration that's
251 // not prepared for it.
lberki1161e732019-02-18 05:07:04 -0800252 return new NonRuleConfiguredTargetValue(
lberkia1f2ddb2019-03-04 23:43:25 -0800253 new EmptyConfiguredTarget(target.getLabel(), configuredTargetKey.getConfigurationKey()),
lberki1161e732019-02-18 05:07:04 -0800254 GeneratingActions.EMPTY,
255 transitivePackagesForPackageRootResolution == null
256 ? null
257 : transitivePackagesForPackageRootResolution.build(),
258 nonceVersion.get());
259 }
260
Greg Estrenb5692bd2016-06-08 21:09:11 +0000261 // This line is only needed for accurate error messaging. Say this target has a circular
262 // dependency with one of its deps. With this line, loading this target fails so Bazel
263 // associates the corresponding error with this target, as expected. Without this line,
264 // the first TransitiveTargetValue call happens on its dep (in trimConfigurations), so Bazel
265 // associates the error with the dep, which is misleading.
janakrac2cd352017-12-20 13:37:13 -0800266 if (configuration != null
267 && configuration.trimConfigurations()
268 && env.getValue(TransitiveTargetKey.of(label)) == null) {
Greg Estrenb5692bd2016-06-08 21:09:11 +0000269 return null;
270 }
271
Ulf Adams2ac20962016-02-01 13:04:54 +0000272 TargetAndConfiguration ctgValue = new TargetAndConfiguration(target, configuration);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100273
274 SkyframeDependencyResolver resolver = view.createDependencyResolver(env);
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +0000275
jcater1f724162018-08-27 09:16:01 -0700276 UnloadedToolchainContext unloadedToolchainContext = null;
John Cater3a0ce772017-08-09 21:09:53 +0200277
janakrb6823b02019-04-12 13:57:02 -0700278 // TODO(janakr): this call may tie up this thread indefinitely, reducing the parallelism of
279 // Skyframe. This is a strict improvement over the prior state of the code, in which we ran
280 // with #processors threads, but ideally we would call #tryAcquire here, and if we failed,
281 // would exit this SkyFunction and restart it when permits were available.
282 acquireWithLogging(key);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100283 try {
284 // Get the configuration targets that trigger this rule's configurable attributes.
janakr931d2852017-12-15 13:48:29 -0800285 ImmutableMap<Label, ConfigMatchingProvider> configConditions =
286 getConfigConditions(
287 ctgValue.getTarget(),
288 env,
janakr931d2852017-12-15 13:48:29 -0800289 ctgValue,
290 transitivePackagesForPackageRootResolution,
lberkic67dcec2019-01-17 11:24:01 -0800291 transitiveRootCauses);
Greg Estren00049432015-08-25 16:43:47 +0000292 if (env.valuesMissing()) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100293 return null;
294 }
Ulf Adams2ac20962016-02-01 13:04:54 +0000295 // TODO(ulfjack): ConfiguredAttributeMapper (indirectly used from computeDependencies) isn't
296 // safe to use if there are missing config conditions, so we stop here, but only if there are
297 // config conditions - though note that we can't check if configConditions is non-empty - it
298 // may be empty for other reasons. It would be better to continue here so that we can collect
299 // more root causes during computeDependencies.
300 // Note that this doesn't apply to AspectFunction, because aspects can't have configurable
301 // attributes.
juliexxiab4519fb2019-01-16 07:43:00 -0800302 if (!transitiveRootCauses.isEmpty()
303 && !Objects.equals(configConditions, NO_CONFIG_CONDITIONS)) {
Ulf Adams2ac20962016-02-01 13:04:54 +0000304 throw new ConfiguredTargetFunctionException(
ulfjack904a8d62018-05-29 05:17:35 -0700305 new ConfiguredValueCreationException(
306 "Cannot compute config conditions", configuration, transitiveRootCauses.build()));
Ulf Adams2ac20962016-02-01 13:04:54 +0000307 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100308
John Cater2e56f062017-07-20 19:43:20 +0200309 // Determine what toolchains are needed by this target.
John Cater2e56f062017-07-20 19:43:20 +0200310 if (target instanceof Rule) {
John Cater53a87b92017-08-01 00:53:39 +0200311 Rule rule = ((Rule) target);
John Cater856b4dd2017-11-21 08:06:16 -0800312 if (rule.getRuleClassObject().supportsPlatforms()) {
313 ImmutableSet<Label> requiredToolchains =
314 rule.getRuleClassObject().getRequiredToolchains();
John Cateree45c662018-06-05 11:09:01 -0700315
316 // Collect local (target, rule) constraints for filtering out execution platforms.
317 ImmutableSet<Label> execConstraintLabels = getExecutionPlatformConstraints(rule);
jcater1f724162018-08-27 09:16:01 -0700318 unloadedToolchainContext =
John Catere39e5c92019-04-23 10:28:02 -0700319 (UnloadedToolchainContext)
320 env.getValueOrThrow(
321 UnloadedToolchainContext.key()
322 .configurationKey(configuredTargetKey.getConfigurationKey())
323 .requiredToolchainTypeLabels(requiredToolchains)
324 .execConstraintLabels(execConstraintLabels)
325 .shouldSanityCheckConfiguration(
326 configuration.trimConfigurationsRetroactively())
327 .build(),
328 ToolchainException.class);
John Cater856b4dd2017-11-21 08:06:16 -0800329 if (env.valuesMissing()) {
330 return null;
331 }
John Cater2e56f062017-07-20 19:43:20 +0200332 }
333 }
334
335 // Calculate the dependencies of this target.
lberki102256f2019-02-08 01:34:23 -0800336 OrderedSetMultimap<DependencyKind, ConfiguredTargetAndData> depValueMap =
Dmitry Lomov6231d082015-11-02 17:17:20 +0000337 computeDependencies(
338 env,
339 resolver,
340 ctgValue,
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000341 ImmutableList.<Aspect>of(),
Dmitry Lomov6231d082015-11-02 17:17:20 +0000342 configConditions,
jcater1f724162018-08-27 09:16:01 -0700343 unloadedToolchainContext == null
John Caterae4e7852018-07-09 15:02:42 -0700344 ? ImmutableSet.of()
jcater1f724162018-08-27 09:16:01 -0700345 : unloadedToolchainContext.resolvedToolchainLabels(),
Dmitry Lomov6231d082015-11-02 17:17:20 +0000346 ruleClassProvider,
347 view.getHostConfiguration(configuration),
janakr931d2852017-12-15 13:48:29 -0800348 transitivePackagesForPackageRootResolution,
ulfjack904a8d62018-05-29 05:17:35 -0700349 transitiveRootCauses,
mjhalupka5d7fa7b2018-03-22 13:37:38 -0700350 defaultBuildOptions);
Ulf Adams84901732016-01-28 15:05:16 +0000351 if (env.valuesMissing()) {
352 return null;
353 }
ulfjack904a8d62018-05-29 05:17:35 -0700354 if (!transitiveRootCauses.isEmpty()) {
Ulf Adams84901732016-01-28 15:05:16 +0000355 throw new ConfiguredTargetFunctionException(
ulfjack904a8d62018-05-29 05:17:35 -0700356 new ConfiguredValueCreationException(
357 "Analysis failed", configuration, transitiveRootCauses.build()));
Ulf Adams84901732016-01-28 15:05:16 +0000358 }
359 Preconditions.checkNotNull(depValueMap);
John Caterae4e7852018-07-09 15:02:42 -0700360
361 // Load the requested toolchains into the ToolchainContext, now that we have dependencies.
John Catercdfa9ca2019-04-05 12:32:09 -0700362 ResolvedToolchainContext toolchainContext = null;
jcater1f724162018-08-27 09:16:01 -0700363 if (unloadedToolchainContext != null) {
John Cater50745142019-04-16 07:41:24 -0700364 String targetDescription = target.toString();
lberki102256f2019-02-08 01:34:23 -0800365 toolchainContext =
John Cater50745142019-04-16 07:41:24 -0700366 ResolvedToolchainContext.load(
367 unloadedToolchainContext,
368 targetDescription,
369 depValueMap.get(DependencyResolver.TOOLCHAIN_DEPENDENCY));
John Caterae4e7852018-07-09 15:02:42 -0700370 }
371
John Cater2e56f062017-07-20 19:43:20 +0200372 ConfiguredTargetValue ans =
373 createConfiguredTarget(
374 view,
375 env,
376 target,
377 configuration,
janakreaff19c2019-01-31 13:59:40 -0800378 configuredTargetKey,
John Cater2e56f062017-07-20 19:43:20 +0200379 depValueMap,
380 configConditions,
381 toolchainContext,
janakr931d2852017-12-15 13:48:29 -0800382 transitivePackagesForPackageRootResolution);
Googlerf526ed02018-09-20 03:59:54 -0700383 if (configuredTargetProgress != null) {
384 configuredTargetProgress.doneConfigureTarget();
385 }
Greg Estren00049432015-08-25 16:43:47 +0000386 return ans;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100387 } catch (DependencyEvaluationException e) {
Ulf Adams25f03d82016-01-25 10:31:46 +0000388 if (e.getCause() instanceof ConfiguredValueCreationException) {
John Cater3a0ce772017-08-09 21:09:53 +0200389 ConfiguredValueCreationException cvce = (ConfiguredValueCreationException) e.getCause();
390
391 // Check if this is caused by an unresolved toolchain, and report it as such.
jcater1f724162018-08-27 09:16:01 -0700392 if (unloadedToolchainContext != null) {
393 UnloadedToolchainContext finalUnloadedToolchainContext = unloadedToolchainContext;
John Cater3a0ce772017-08-09 21:09:53 +0200394 Set<Label> toolchainDependencyErrors =
jcater1f724162018-08-27 09:16:01 -0700395 Streams.stream(cvce.getRootCauses())
396 .map(Cause::getLabel)
397 .filter(l -> finalUnloadedToolchainContext.resolvedToolchainLabels().contains(l))
398 .collect(ImmutableSet.toImmutableSet());
399
John Cater3a0ce772017-08-09 21:09:53 +0200400 if (!toolchainDependencyErrors.isEmpty()) {
401 env.getListener()
402 .handle(
403 Event.error(
404 String.format(
ulfjack904a8d62018-05-29 05:17:35 -0700405 "XXX - While resolving toolchains for target %s: %s",
John Cater3a0ce772017-08-09 21:09:53 +0200406 target.getLabel(), e.getCause().getMessage())));
407 }
408 }
409
410 throw new ConfiguredTargetFunctionException(cvce);
Dmitry Lomovd83af9e2017-02-23 15:44:23 +0000411 } else if (e.getCause() instanceof InconsistentAspectOrderException) {
412 InconsistentAspectOrderException cause = (InconsistentAspectOrderException) e.getCause();
413 throw new ConfiguredTargetFunctionException(
Klaus Aehligfbdeffe2018-01-26 02:19:58 -0800414 new ConfiguredValueCreationException(
415 cause.getMessage(), target.getLabel(), configuration));
John Cater3a0ce772017-08-09 21:09:53 +0200416 } else if (e.getCause() instanceof InvalidConfigurationException) {
Ulf Adams25f03d82016-01-25 10:31:46 +0000417 InvalidConfigurationException cause = (InvalidConfigurationException) e.getCause();
cparsonsf3ad3032017-08-30 19:34:29 +0200418 env.getListener().handle(Event.error(cause.getMessage()));
Ulf Adams25f03d82016-01-25 10:31:46 +0000419 throw new ConfiguredTargetFunctionException(
Klaus Aehligfbdeffe2018-01-26 02:19:58 -0800420 new ConfiguredValueCreationException(
421 cause.getMessage(), target.getLabel(), configuration));
juliexxia03ff8782019-03-20 13:03:27 -0700422 } else if (e.getCause() instanceof TransitionException) {
423 TransitionException cause = (TransitionException) e.getCause();
424 env.getListener().handle(Event.error(cause.getMessage()));
425 throw new ConfiguredTargetFunctionException(
426 new ConfiguredValueCreationException(e.getMessage(), target.getLabel(), configuration));
John Cater3a0ce772017-08-09 21:09:53 +0200427 } else {
428 // Unknown exception type.
429 throw new ConfiguredTargetFunctionException(
Klaus Aehligfbdeffe2018-01-26 02:19:58 -0800430 new ConfiguredValueCreationException(e.getMessage(), target.getLabel(), configuration));
Ulf Adams25f03d82016-01-25 10:31:46 +0000431 }
Marian Loburfc567b32015-09-14 08:44:25 +0000432 } catch (AspectCreationException e) {
433 throw new ConfiguredTargetFunctionException(
ulfjack904a8d62018-05-29 05:17:35 -0700434 new ConfiguredValueCreationException(
435 e.getMessage(),
436 configuration,
437 e.getCauses()));
John Cater76b6f202018-07-10 08:43:04 -0700438 } catch (ToolchainException e) {
John Cater535daee2017-08-04 22:44:03 +0200439 // We need to throw a ConfiguredValueCreationException, so either find one or make one.
John Catere39e5c92019-04-23 10:28:02 -0700440 ConfiguredValueCreationException cvce = e.asConfiguredValueCreationException();
441 if (cvce == null) {
Klaus Aehligfbdeffe2018-01-26 02:19:58 -0800442 cvce =
John Cater76b6f202018-07-10 08:43:04 -0700443 new ConfiguredValueCreationException(e.getMessage(), target.getLabel(), configuration);
John Cater2e56f062017-07-20 19:43:20 +0200444 }
John Cater535daee2017-08-04 22:44:03 +0200445
446 env.getListener()
447 .handle(
448 Event.error(
449 String.format(
450 "While resolving toolchains for target %s: %s",
John Cater76b6f202018-07-10 08:43:04 -0700451 target.getLabel(), e.getMessage())));
John Cater535daee2017-08-04 22:44:03 +0200452 throw new ConfiguredTargetFunctionException(cvce);
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +0000453 } finally {
454 cpuBoundSemaphore.release();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100455 }
456 }
457
458 /**
John Cateree45c662018-06-05 11:09:01 -0700459 * Returns the target-specific execution platform constraints, based on the rule definition and
460 * any constraints added by the target.
461 */
John Cater9a849c62019-04-25 07:03:41 -0700462 public static ImmutableSet<Label> getExecutionPlatformConstraints(Rule rule) {
John Cateree45c662018-06-05 11:09:01 -0700463 NonconfigurableAttributeMapper mapper = NonconfigurableAttributeMapper.of(rule);
464 ImmutableSet.Builder<Label> execConstraintLabels = new ImmutableSet.Builder<>();
465
466 execConstraintLabels.addAll(rule.getRuleClassObject().getExecutionPlatformConstraints());
467
468 if (rule.getRuleClassObject().executionPlatformConstraintsAllowed()
469 == ExecutionPlatformConstraintsAllowed.PER_TARGET) {
470 execConstraintLabels.addAll(
John Caterae6f7d52019-04-12 10:42:59 -0700471 mapper.get(RuleClass.EXEC_COMPATIBLE_WITH_ATTR, BuildType.LABEL_LIST));
John Cateree45c662018-06-05 11:09:01 -0700472 }
473
474 return execConstraintLabels.build();
475 }
476
477 /**
John Cater2e56f062017-07-20 19:43:20 +0200478 * Computes the direct dependencies of a node in the configured target graph (a configured target
479 * or an aspects).
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100480 *
481 * <p>Returns null if Skyframe hasn't evaluated the required dependencies yet. In this case, the
482 * caller should also return null to Skyframe.
John Cater2e56f062017-07-20 19:43:20 +0200483 *
484 * @param env the Skyframe environment
Greg Estren86045da2016-12-14 19:46:48 +0000485 * @param resolver the dependency resolver
486 * @param ctgValue the label and the configuration of the node
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000487 * @param aspects
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100488 * @param configConditions the configuration conditions for evaluating the attributes of the node
John Caterae4e7852018-07-09 15:02:42 -0700489 * @param toolchainLabels labels of required toolchain dependencies
Greg Estren00049432015-08-25 16:43:47 +0000490 * @param ruleClassProvider rule class provider for determining the right configuration fragments
John Cater2e56f062017-07-20 19:43:20 +0200491 * to apply to deps
Greg Estren00049432015-08-25 16:43:47 +0000492 * @param hostConfiguration the host configuration. There's a noticeable performance hit from
493 * instantiating this on demand for every dependency that wants it, so it's best to compute
494 * the host configuration as early as possible and pass this reference to all consumers
mjhalupka5d7fa7b2018-03-22 13:37:38 -0700495 * @param defaultBuildOptions the default build options provided by the server; these are used to
496 * create diffs for {@link BuildConfigurationValue.Key}s to prevent storing the entire
497 * BuildOptions object.
John Cater2e56f062017-07-20 19:43:20 +0200498 */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100499 @Nullable
lberki102256f2019-02-08 01:34:23 -0800500 static OrderedSetMultimap<DependencyKind, ConfiguredTargetAndData> computeDependencies(
Dmitry Lomov6231d082015-11-02 17:17:20 +0000501 Environment env,
502 SkyframeDependencyResolver resolver,
503 TargetAndConfiguration ctgValue,
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000504 Iterable<Aspect> aspects,
Lukacs Berki7894c182016-05-10 12:07:01 +0000505 ImmutableMap<Label, ConfigMatchingProvider> configConditions,
John Caterae4e7852018-07-09 15:02:42 -0700506 ImmutableSet<Label> toolchainLabels,
Dmitry Lomov6231d082015-11-02 17:17:20 +0000507 RuleClassProvider ruleClassProvider,
508 BuildConfiguration hostConfiguration,
janakr931d2852017-12-15 13:48:29 -0800509 @Nullable NestedSetBuilder<Package> transitivePackagesForPackageRootResolution,
ulfjack904a8d62018-05-29 05:17:35 -0700510 NestedSetBuilder<Cause> transitiveRootCauses,
mjhalupka5d7fa7b2018-03-22 13:37:38 -0700511 BuildOptions defaultBuildOptions)
Dmitry Lomov9b2fc5c2016-11-11 11:18:48 +0000512 throws DependencyEvaluationException, ConfiguredTargetFunctionException,
John Cater2e56f062017-07-20 19:43:20 +0200513 AspectCreationException, InterruptedException {
Greg Estrend5353252016-08-11 22:13:31 +0000514 // Create the map from attributes to set of (target, configuration) pairs.
lberki102256f2019-02-08 01:34:23 -0800515 OrderedSetMultimap<DependencyKind, Dependency> depValueNames;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100516 try {
John Cater2e56f062017-07-20 19:43:20 +0200517 depValueNames =
518 resolver.dependentNodeMap(
519 ctgValue,
520 hostConfiguration,
521 aspects,
522 configConditions,
John Caterae4e7852018-07-09 15:02:42 -0700523 toolchainLabels,
ulfjack904a8d62018-05-29 05:17:35 -0700524 transitiveRootCauses,
mstaib4a07a472018-04-19 14:16:41 -0700525 ((ConfiguredRuleClassProvider) ruleClassProvider).getTrimmingTransitionFactory());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100526 } catch (EvalException e) {
Ulf Adams25f03d82016-01-25 10:31:46 +0000527 // EvalException can only be thrown by computed Skylark attributes in the current rule.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100528 env.getListener().handle(Event.error(e.getLocation(), e.getMessage()));
Ulf Adams25f03d82016-01-25 10:31:46 +0000529 throw new DependencyEvaluationException(
ulfjack904a8d62018-05-29 05:17:35 -0700530 new ConfiguredValueCreationException(
531 e.print(), ctgValue.getLabel(), ctgValue.getConfiguration()));
Dmitry Lomovd83af9e2017-02-23 15:44:23 +0000532 } catch (InconsistentAspectOrderException e) {
533 env.getListener().handle(Event.error(e.getLocation(), e.getMessage()));
534 throw new DependencyEvaluationException(e);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100535 }
536
Greg Estren00049432015-08-25 16:43:47 +0000537 // Trim each dep's configuration so it only includes the fragments needed by its transitive
gregce5bae50a2017-08-17 23:23:47 +0200538 // closure.
lberkiafc82e02019-03-12 01:57:26 -0700539 depValueNames =
540 ConfigurationResolver.resolveConfigurations(
541 env,
542 ctgValue,
543 depValueNames,
544 hostConfiguration,
545 ruleClassProvider,
546 defaultBuildOptions);
Googler8f168792018-07-09 01:36:01 -0700547
548 // Return early in case packages were not loaded yet. In theory, we could start configuring
549 // dependent targets in loaded packages. However, that creates an artificial sync boundary
550 // between loading all dependent packages (fast) and configuring some dependent targets (can
551 // have a long tail).
552 if (env.valuesMissing()) {
553 return null;
Greg Estren00049432015-08-25 16:43:47 +0000554 }
555
556 // Resolve configured target dependencies and handle errors.
janakr9c101402018-03-10 06:48:59 -0800557 Map<SkyKey, ConfiguredTargetAndData> depValues =
janakr931d2852017-12-15 13:48:29 -0800558 resolveConfiguredTargetDependencies(
559 env,
ulfjack904a8d62018-05-29 05:17:35 -0700560 ctgValue,
janakr931d2852017-12-15 13:48:29 -0800561 depValueNames.values(),
562 transitivePackagesForPackageRootResolution,
ulfjack904a8d62018-05-29 05:17:35 -0700563 transitiveRootCauses);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100564 if (depValues == null) {
565 return null;
566 }
567
Greg Estren00049432015-08-25 16:43:47 +0000568 // Resolve required aspects.
gregce4c3ef112017-09-20 23:43:14 +0200569 OrderedSetMultimap<Dependency, ConfiguredAspect> depAspects =
janakr931d2852017-12-15 13:48:29 -0800570 AspectResolver.resolveAspectDependencies(
571 env, depValues, depValueNames.values(), transitivePackagesForPackageRootResolution);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100572 if (depAspects == null) {
573 return null;
574 }
575
Greg Estren00049432015-08-25 16:43:47 +0000576 // Merge the dependent configured targets and aspects into a single map.
Dmitry Lomov9b2fc5c2016-11-11 11:18:48 +0000577 try {
gregce4c3ef112017-09-20 23:43:14 +0200578 return AspectResolver.mergeAspects(depValueNames, depValues, depAspects);
Dmitry Lomov9b2fc5c2016-11-11 11:18:48 +0000579 } catch (DuplicateException e) {
580 env.getListener().handle(
581 Event.error(ctgValue.getTarget().getLocation(), e.getMessage()));
582
583 throw new ConfiguredTargetFunctionException(
ulfjack904a8d62018-05-29 05:17:35 -0700584 new ConfiguredValueCreationException(
585 e.getMessage(), ctgValue.getLabel(), ctgValue.getConfiguration()));
Dmitry Lomov9b2fc5c2016-11-11 11:18:48 +0000586 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100587 }
588
589 /**
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000590 * Returns the set of {@link ConfigMatchingProvider}s that key the configurable attributes used by
591 * this rule.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100592 *
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000593 * <p>>If the configured targets supplying those providers aren't yet resolved by the dependency
594 * resolver, returns null.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100595 */
596 @Nullable
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000597 static ImmutableMap<Label, ConfigMatchingProvider> getConfigConditions(
598 Target target,
599 Environment env,
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000600 TargetAndConfiguration ctgValue,
janakr931d2852017-12-15 13:48:29 -0800601 @Nullable NestedSetBuilder<Package> transitivePackagesForPackageRootResolution,
lberkic67dcec2019-01-17 11:24:01 -0800602 NestedSetBuilder<Cause> transitiveRootCauses)
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000603 throws DependencyEvaluationException, InterruptedException {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100604 if (!(target instanceof Rule)) {
Ulf Adams2ac20962016-02-01 13:04:54 +0000605 return NO_CONFIG_CONDITIONS;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100606 }
gregce749962a2019-03-08 12:47:34 -0800607 RawAttributeMapper attrs = RawAttributeMapper.of(((Rule) target));
608 if (!attrs.has(RuleClass.CONFIG_SETTING_DEPS_ATTRIBUTE)) {
609 return NO_CONFIG_CONDITIONS;
610 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100611
612 // Collect the labels of the configured targets we need to resolve.
gregce749962a2019-03-08 12:47:34 -0800613 List<Label> configLabels =
614 attrs.get(RuleClass.CONFIG_SETTING_DEPS_ATTRIBUTE, BuildType.LABEL_LIST).stream()
615 .map(configLabel -> target.getLabel().resolveRepositoryRelative(configLabel))
616 .collect(Collectors.toList());
617 if (configLabels.isEmpty()) {
Ulf Adams2ac20962016-02-01 13:04:54 +0000618 return NO_CONFIG_CONDITIONS;
mstaib6e2cfe92019-04-23 17:50:11 -0700619 } else if (ctgValue.getConfiguration().trimConfigurationsRetroactively()) {
620 String message =
621 target.getLabel()
622 + " has configurable attributes, but these are not supported in retroactive trimming "
623 + "mode.";
624 env.getListener().handle(Event.error(TargetUtils.getLocationMaybe(target), message));
625 throw new DependencyEvaluationException(
626 new ConfiguredValueCreationException(
627 message, ctgValue.getLabel(), ctgValue.getConfiguration()));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100628 }
629
lberkia1f2ddb2019-03-04 23:43:25 -0800630 // Collect the actual deps without a configuration transition (since by definition config
631 // conditions evaluate over the current target's configuration). If the dependency is
632 // (erroneously) something that needs the null configuration, its analysis will be
633 // short-circuited. That error will be reported later.
gregce15e0fa82018-05-30 07:31:48 -0700634 ImmutableList.Builder<Dependency> depsBuilder = ImmutableList.builder();
gregce749962a2019-03-08 12:47:34 -0800635 for (Label configurabilityLabel : configLabels) {
lberkia1f2ddb2019-03-04 23:43:25 -0800636 Dependency configurabilityDependency =
637 Dependency.withConfiguration(configurabilityLabel, ctgValue.getConfiguration());
lberkic67dcec2019-01-17 11:24:01 -0800638 depsBuilder.add(configurabilityDependency);
Dmitry Lomovd83af9e2017-02-23 15:44:23 +0000639 }
lberkic67dcec2019-01-17 11:24:01 -0800640
gregce15e0fa82018-05-30 07:31:48 -0700641 ImmutableList<Dependency> configConditionDeps = depsBuilder.build();
Greg Estren00049432015-08-25 16:43:47 +0000642
janakr9c101402018-03-10 06:48:59 -0800643 Map<SkyKey, ConfiguredTargetAndData> configValues =
janakr931d2852017-12-15 13:48:29 -0800644 resolveConfiguredTargetDependencies(
645 env,
ulfjack904a8d62018-05-29 05:17:35 -0700646 ctgValue,
gregce15e0fa82018-05-30 07:31:48 -0700647 configConditionDeps,
janakr931d2852017-12-15 13:48:29 -0800648 transitivePackagesForPackageRootResolution,
ulfjack904a8d62018-05-29 05:17:35 -0700649 transitiveRootCauses);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100650 if (configValues == null) {
651 return null;
652 }
653
gregce749962a2019-03-08 12:47:34 -0800654 Map<Label, ConfigMatchingProvider> configConditions = new LinkedHashMap<>();
655
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100656 // Get the configured targets as ConfigMatchingProvider interfaces.
gregce15e0fa82018-05-30 07:31:48 -0700657 for (Dependency entry : configConditionDeps) {
dslomovddc180a2017-07-14 11:34:24 +0200658 SkyKey baseKey = ConfiguredTargetValue.key(entry.getLabel(), entry.getConfiguration());
janakrf3e6f252018-01-18 07:45:12 -0800659 ConfiguredTarget value = configValues.get(baseKey).getConfiguredTarget();
lberkic67dcec2019-01-17 11:24:01 -0800660 // The code above guarantees that value is non-null here and since the rule is a
661 // config_setting, provider must also be non-null.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100662 ConfigMatchingProvider provider = value.getProvider(ConfigMatchingProvider.class);
663 if (provider != null) {
Lukacs Berki7894c182016-05-10 12:07:01 +0000664 configConditions.put(entry.getLabel(), provider);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100665 } else {
666 // Not a valid provider for configuration conditions.
667 String message =
668 entry.getLabel() + " is not a valid configuration key for " + target.getLabel();
669 env.getListener().handle(Event.error(TargetUtils.getLocationMaybe(target), message));
ulfjack904a8d62018-05-29 05:17:35 -0700670 throw new DependencyEvaluationException(
671 new ConfiguredValueCreationException(
672 message, ctgValue.getLabel(), ctgValue.getConfiguration()));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100673 }
674 }
675
Lukacs Berki7894c182016-05-10 12:07:01 +0000676 return ImmutableMap.copyOf(configConditions);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100677 }
678
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000679 /**
janakrf3e6f252018-01-18 07:45:12 -0800680 * Resolves the targets referenced in depValueNames and returns their {@link
janakr9c101402018-03-10 06:48:59 -0800681 * ConfiguredTargetAndData} instances.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100682 *
683 * <p>Returns null if not all instances are available yet.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100684 */
685 @Nullable
janakr9c101402018-03-10 06:48:59 -0800686 private static Map<SkyKey, ConfiguredTargetAndData> resolveConfiguredTargetDependencies(
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000687 Environment env,
ulfjack904a8d62018-05-29 05:17:35 -0700688 TargetAndConfiguration ctgValue,
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000689 Collection<Dependency> deps,
janakr931d2852017-12-15 13:48:29 -0800690 @Nullable NestedSetBuilder<Package> transitivePackagesForPackageRootResolution,
ulfjack904a8d62018-05-29 05:17:35 -0700691 NestedSetBuilder<Cause> transitiveRootCauses)
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000692 throws DependencyEvaluationException, InterruptedException {
Ulf Adams84901732016-01-28 15:05:16 +0000693 boolean missedValues = env.valuesMissing();
ulfjack904a8d62018-05-29 05:17:35 -0700694 String failWithMessage = null;
janakrf3e6f252018-01-18 07:45:12 -0800695 // Naively we would like to just fetch all requested ConfiguredTargets, together with their
696 // Packages. However, some ConfiguredTargets are AliasConfiguredTargets, which means that their
697 // associated Targets (and therefore associated Packages) don't correspond to their own Labels.
698 // We don't know the associated Package until we fetch the ConfiguredTarget. Therefore, we have
699 // to do a potential second pass, in which we fetch all the Packages for AliasConfiguredTargets.
700 Iterable<SkyKey> depKeys =
701 Iterables.concat(
702 Iterables.transform(
703 deps,
704 input -> ConfiguredTargetValue.key(input.getLabel(), input.getConfiguration())),
705 Iterables.transform(
706 deps, input -> PackageValue.key(input.getLabel().getPackageIdentifier())));
Ulf Adams84901732016-01-28 15:05:16 +0000707 Map<SkyKey, ValueOrException<ConfiguredValueCreationException>> depValuesOrExceptions =
gregcef19fcfe2017-06-02 16:04:07 -0400708 env.getValuesOrThrow(depKeys, ConfiguredValueCreationException.class);
janakr9c101402018-03-10 06:48:59 -0800709 Map<SkyKey, ConfiguredTargetAndData> result = Maps.newHashMapWithExpectedSize(deps.size());
janakrf3e6f252018-01-18 07:45:12 -0800710 Set<SkyKey> aliasPackagesToFetch = new HashSet<>();
711 List<Dependency> aliasDepsToRedo = new ArrayList<>();
712 Map<SkyKey, SkyValue> aliasPackageValues = null;
713 Collection<Dependency> depsToProcess = deps;
714 for (int i = 0; i < 2; i++) {
715 for (Dependency dep : depsToProcess) {
716 SkyKey key = ConfiguredTargetValue.key(dep.getLabel(), dep.getConfiguration());
717 try {
718 ConfiguredTargetValue depValue =
719 (ConfiguredTargetValue) depValuesOrExceptions.get(key).get();
720
721 if (depValue == null) {
722 missedValues = true;
723 } else {
724 ConfiguredTarget depCt = depValue.getConfiguredTarget();
725 Label depLabel = depCt.getLabel();
726 SkyKey packageKey = PackageValue.key(depLabel.getPackageIdentifier());
727 PackageValue pkgValue;
728 if (i == 0) {
729 ValueOrException<ConfiguredValueCreationException> packageResult =
730 depValuesOrExceptions.get(packageKey);
731 if (packageResult == null) {
732 aliasPackagesToFetch.add(packageKey);
733 aliasDepsToRedo.add(dep);
734 continue;
735 } else {
janakr169e7072019-03-14 09:18:31 -0700736 pkgValue = (PackageValue) packageResult.get();
737 if (pkgValue == null) {
738 // In a race, the getValuesOrThrow call above may have retrieved the package
janakr9c0a6332019-04-12 16:21:54 -0700739 // before it was done but the configured target after it was done. Since
740 // SkyFunctionEnvironment may cache absent values, re-requesting it on this
741 // evaluation may be useless, just treat it as missing.
742 missedValues = true;
743 continue;
janakr169e7072019-03-14 09:18:31 -0700744 }
janakrf3e6f252018-01-18 07:45:12 -0800745 }
746 } else {
747 // We were doing AliasConfiguredTarget mop-up.
748 pkgValue = (PackageValue) aliasPackageValues.get(packageKey);
749 if (pkgValue == null) {
750 // This is unexpected: on the second iteration, all packages should be present,
751 // since the configured targets that depend on them are present. But since that is
752 // not a guarantee Skyframe makes, we tolerate their absence.
753 missedValues = true;
754 continue;
755 }
756 }
757 try {
mstaibdc242d42019-04-18 10:20:13 -0700758 BuildConfiguration depConfiguration = dep.getConfiguration();
759 BuildConfigurationValue.Key depKey =
760 depValue.getConfiguredTarget().getConfigurationKey();
761 // Retroactive trimming may change the configuration associated with the dependency.
762 // If it does, we need to get that instance.
763 // TODO(mstaib): doing these individually instead of doing them all at once may end up
764 // being wasteful use of Skyframe. Although these configurations are guaranteed to be
765 // in the Skyframe cache (because the dependency would have had to retrieve them to be
766 // created in the first place), looking them up repeatedly may be slower than just
767 // keeping a local cache and assigning the same configuration to all the CTs which
768 // need it. Profile this and see if there's a better way.
769 if (depKey != null && !depKey.equals(BuildConfigurationValue.key(depConfiguration))) {
770 if (!depConfiguration.trimConfigurationsRetroactively()) {
771 throw new AssertionError(
772 "Loading configurations mid-dependency resolution should ONLY happen when "
773 + "retroactive trimming is enabled.");
774 }
775 depConfiguration =
776 ((BuildConfigurationValue) env.getValue(depKey)).getConfiguration();
777 }
janakrf3e6f252018-01-18 07:45:12 -0800778 result.put(
779 key,
janakr9c101402018-03-10 06:48:59 -0800780 new ConfiguredTargetAndData(
janakrf3e6f252018-01-18 07:45:12 -0800781 depValue.getConfiguredTarget(),
janakr9c101402018-03-10 06:48:59 -0800782 pkgValue.getPackage().getTarget(depLabel.getName()),
mstaibdc242d42019-04-18 10:20:13 -0700783 depConfiguration));
janakrf3e6f252018-01-18 07:45:12 -0800784 } catch (NoSuchTargetException e) {
785 throw new IllegalStateException("Target already verified for " + dep, e);
786 }
787 if (transitivePackagesForPackageRootResolution != null) {
788 transitivePackagesForPackageRootResolution.addTransitive(
789 depValue.getTransitivePackagesForPackageRootResolution());
790 }
janakr931d2852017-12-15 13:48:29 -0800791 }
janakrf3e6f252018-01-18 07:45:12 -0800792 } catch (ConfiguredValueCreationException e) {
ulfjack904a8d62018-05-29 05:17:35 -0700793 transitiveRootCauses.addTransitive(e.rootCauses);
794 failWithMessage = e.getMessage();
Ulf Adams84901732016-01-28 15:05:16 +0000795 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100796 }
janakrf3e6f252018-01-18 07:45:12 -0800797 if (aliasDepsToRedo.isEmpty()) {
798 break;
799 }
800 aliasPackageValues = env.getValues(aliasPackagesToFetch);
801 depsToProcess = aliasDepsToRedo;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100802 }
Ulf Adams84901732016-01-28 15:05:16 +0000803 if (missedValues) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100804 return null;
ulfjack904a8d62018-05-29 05:17:35 -0700805 } else if (failWithMessage != null) {
Ulf Adams84901732016-01-28 15:05:16 +0000806 throw new DependencyEvaluationException(
ulfjack904a8d62018-05-29 05:17:35 -0700807 new ConfiguredValueCreationException(
808 failWithMessage, ctgValue.getConfiguration(), transitiveRootCauses.build()));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100809 } else {
Ulf Adams7cb66de2016-01-14 08:46:43 +0000810 return result;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100811 }
812 }
813
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100814 @Override
815 public String extractTag(SkyKey skyKey) {
816 return Label.print(((ConfiguredTargetKey) skyKey.argument()).getLabel());
817 }
818
819 @Nullable
John Cater2e56f062017-07-20 19:43:20 +0200820 private ConfiguredTargetValue createConfiguredTarget(
821 SkyframeBuildView view,
822 Environment env,
823 Target target,
824 BuildConfiguration configuration,
janakreaff19c2019-01-31 13:59:40 -0800825 ConfiguredTargetKey configuredTargetKey,
lberki102256f2019-02-08 01:34:23 -0800826 OrderedSetMultimap<DependencyKind, ConfiguredTargetAndData> depValueMap,
Lukacs Berki7894c182016-05-10 12:07:01 +0000827 ImmutableMap<Label, ConfigMatchingProvider> configConditions,
John Catercdfa9ca2019-04-05 12:32:09 -0700828 @Nullable ResolvedToolchainContext toolchainContext,
janakr931d2852017-12-15 13:48:29 -0800829 @Nullable NestedSetBuilder<Package> transitivePackagesForPackageRootResolution)
Greg Estren9eb1cf02015-06-26 22:18:35 +0000830 throws ConfiguredTargetFunctionException, InterruptedException {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100831 StoredEventHandler events = new StoredEventHandler();
janakr573807d2018-01-11 14:02:35 -0800832 CachingAnalysisEnvironment analysisEnvironment =
833 view.createAnalysisEnvironment(
gregced56e9582018-06-15 13:23:34 -0700834 ConfiguredTargetKey.of(target.getLabel(), configuration),
janakr573807d2018-01-11 14:02:35 -0800835 false,
836 events,
837 env,
838 configuration);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100839 if (env.valuesMissing()) {
840 return null;
841 }
842
Ulf Adams84901732016-01-28 15:05:16 +0000843 Preconditions.checkNotNull(depValueMap);
cparsonse2d200f2018-03-06 16:15:11 -0800844 ConfiguredTarget configuredTarget;
845 try {
846 configuredTarget =
847 view.createConfiguredTarget(
848 target,
849 configuration,
850 analysisEnvironment,
janakreaff19c2019-01-31 13:59:40 -0800851 configuredTargetKey,
cparsonse2d200f2018-03-06 16:15:11 -0800852 depValueMap,
853 configConditions,
854 toolchainContext);
855 } catch (ActionConflictException e) {
856 throw new ConfiguredTargetFunctionException(e);
857 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100858
859 events.replayOn(env.getListener());
860 if (events.hasErrors()) {
861 analysisEnvironment.disable(target);
ulfjack904a8d62018-05-29 05:17:35 -0700862 NestedSet<Cause> rootCauses = NestedSetBuilder.wrap(
863 Order.STABLE_ORDER,
864 events.getEvents().stream()
865 .filter((event) -> event.getKind() == EventKind.ERROR)
866 .map((event) ->
867 new AnalysisFailedCause(
868 target.getLabel(),
869 ConfiguredValueCreationException.toId(configuration),
870 event.getMessage()))
871 .collect(Collectors.toList()));
Klaus Aehligfbdeffe2018-01-26 02:19:58 -0800872 throw new ConfiguredTargetFunctionException(
873 new ConfiguredValueCreationException(
874 "Analysis of target '" + target.getLabel() + "' failed; build aborted",
ulfjack904a8d62018-05-29 05:17:35 -0700875 configuration,
876 rootCauses));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100877 }
878 Preconditions.checkState(!analysisEnvironment.hasErrors(),
879 "Analysis environment hasError() but no errors reported");
880 if (env.valuesMissing()) {
881 return null;
882 }
883
884 analysisEnvironment.disable(target);
885 Preconditions.checkNotNull(configuredTarget, target);
886
cparsonse2d200f2018-03-06 16:15:11 -0800887 if (configuredTarget instanceof RuleConfiguredTarget) {
888 RuleConfiguredTarget ruleConfiguredTarget = (RuleConfiguredTarget) configuredTarget;
889 return new RuleConfiguredTargetValue(
890 ruleConfiguredTarget,
891 transitivePackagesForPackageRootResolution == null
892 ? null
janakra81bb952019-01-28 17:30:06 -0800893 : transitivePackagesForPackageRootResolution.build(),
894 nonceVersion.get());
cparsonse2d200f2018-03-06 16:15:11 -0800895 } else {
896 GeneratingActions generatingActions;
897 // Check for conflicting actions within this configured target (that indicates a bug in the
898 // rule implementation).
899 try {
900 generatingActions =
901 Actions.filterSharedActionsAndThrowActionConflict(
902 analysisEnvironment.getActionKeyContext(),
903 analysisEnvironment.getRegisteredActions());
904 } catch (ActionConflictException e) {
905 throw new ConfiguredTargetFunctionException(e);
906 }
907 return new NonRuleConfiguredTargetValue(
908 configuredTarget,
909 generatingActions,
910 transitivePackagesForPackageRootResolution == null
911 ? null
janakra81bb952019-01-28 17:30:06 -0800912 : transitivePackagesForPackageRootResolution.build(),
913 nonceVersion.get());
Janak Ramakrishnanb3a6ca72015-03-27 20:07:28 +0000914 }
915 }
916
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100917 /**
janakr00408d62018-03-24 17:22:23 -0700918 * An exception indicating that there was a problem during the construction of a
919 * ConfiguredTargetValue.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100920 */
janakr00408d62018-03-24 17:22:23 -0700921 @AutoCodec
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100922 public static final class ConfiguredValueCreationException extends Exception {
ulfjack904a8d62018-05-29 05:17:35 -0700923 private static ConfigurationId toId(BuildConfiguration config) {
924 return config == null ? null : config.getEventId().asStreamProto().getConfiguration();
janakr00408d62018-03-24 17:22:23 -0700925 }
926
ulfjack904a8d62018-05-29 05:17:35 -0700927 @Nullable private final BuildEventId configuration;
928 private final NestedSet<Cause> rootCauses;
929
janakr00408d62018-03-24 17:22:23 -0700930 @AutoCodec.VisibleForSerialization
931 @AutoCodec.Instantiator
932 ConfiguredValueCreationException(
933 String message,
ulfjack904a8d62018-05-29 05:17:35 -0700934 @Nullable BuildEventId configuration,
935 NestedSet<Cause> rootCauses) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100936 super(message);
ulfjack904a8d62018-05-29 05:17:35 -0700937 this.rootCauses = rootCauses;
janakr00408d62018-03-24 17:22:23 -0700938 this.configuration = configuration;
Klaus Aehligfbdeffe2018-01-26 02:19:58 -0800939 }
940
ulfjack904a8d62018-05-29 05:17:35 -0700941 private ConfiguredValueCreationException(
942 String message, Label currentTarget, @Nullable BuildConfiguration configuration) {
943 this(
944 message,
945 configuration == null ? null : configuration.getEventId(),
946 NestedSetBuilder.<Cause>stableOrder()
947 .add(new AnalysisFailedCause(currentTarget, toId(configuration), message))
948 .build());
Ulf Adams25f03d82016-01-25 10:31:46 +0000949 }
950
ulfjack904a8d62018-05-29 05:17:35 -0700951 private ConfiguredValueCreationException(
952 String message, @Nullable BuildConfiguration configuration, NestedSet<Cause> rootCauses) {
953 this(message, configuration == null ? null : configuration.getEventId(), rootCauses);
Ulf Adams84901732016-01-28 15:05:16 +0000954 }
955
ulfjack904a8d62018-05-29 05:17:35 -0700956 public NestedSet<Cause> getRootCauses() {
957 return rootCauses;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100958 }
Klaus Aehligfbdeffe2018-01-26 02:19:58 -0800959
ulfjack6192b8c2018-05-24 02:40:42 -0700960 @Nullable public BuildEventId getConfiguration() {
Klaus Aehligfbdeffe2018-01-26 02:19:58 -0800961 return configuration;
962 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100963 }
964
965 /**
janakrb6823b02019-04-12 13:57:02 -0700966 * Used to declare all the exception types that can be wrapped in the exception thrown by {@link
967 * ConfiguredTargetFunction#compute}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100968 */
janakrb6823b02019-04-12 13:57:02 -0700969 static final class ConfiguredTargetFunctionException extends SkyFunctionException {
Ulf Adams25f03d82016-01-25 10:31:46 +0000970 private ConfiguredTargetFunctionException(ConfiguredValueCreationException e) {
971 super(e, Transience.PERSISTENT);
Ulf Adams3ab82f72015-09-04 12:10:53 +0000972 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100973
Janak Ramakrishnanb3a6ca72015-03-27 20:07:28 +0000974 private ConfiguredTargetFunctionException(ActionConflictException e) {
975 super(e, Transience.PERSISTENT);
976 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100977 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100978}