blob: f67a4e883ee8491aa69efbbe0afdc2633a5062b7 [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.skyframe;
16
janakr93e3eea2017-03-30 22:09:37 +000017import com.google.common.base.Supplier;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010018import com.google.common.collect.ImmutableList;
Lukacs Berki7894c182016-05-10 12:07:01 +000019import com.google.common.collect.ImmutableMap;
cpeyserfb829992017-09-07 17:17:03 +020020import com.google.common.collect.ImmutableSet;
Rumou Duan33bab462016-04-25 17:55:12 +000021import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
janakr93e3eea2017-03-30 22:09:37 +000022import com.google.devtools.build.lib.actions.ActionLookupValue;
ulfjack90e2e982017-08-07 11:27:32 +020023import com.google.devtools.build.lib.analysis.AliasProvider;
gregce4c3ef112017-09-20 23:43:14 +020024import com.google.devtools.build.lib.analysis.AspectResolver;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010025import com.google.devtools.build.lib.analysis.CachingAnalysisEnvironment;
Dmitry Lomovb487ac62015-11-09 13:09:12 +000026import com.google.devtools.build.lib.analysis.ConfiguredAspect;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010027import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
28import com.google.devtools.build.lib.analysis.ConfiguredTarget;
Dmitry Lomovd83af9e2017-02-23 15:44:23 +000029import com.google.devtools.build.lib.analysis.DependencyResolver.InconsistentAspectOrderException;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010030import com.google.devtools.build.lib.analysis.TargetAndConfiguration;
John Cater2e56f062017-07-20 19:43:20 +020031import com.google.devtools.build.lib.analysis.ToolchainContext;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010032import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
33import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
Ulf Adams25f03d82016-01-25 10:31:46 +000034import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
gregce2aee44b2017-09-16 07:16:44 +020035import com.google.devtools.build.lib.analysis.configuredtargets.MergedConfiguredTarget;
36import com.google.devtools.build.lib.analysis.configuredtargets.MergedConfiguredTarget.DuplicateException;
John Fielda97e17f2015-11-13 02:19:52 +000037import com.google.devtools.build.lib.cmdline.Label;
Ulf Adams84901732016-01-28 15:05:16 +000038import com.google.devtools.build.lib.collect.nestedset.NestedSet;
Marian Loburc62faba2015-09-09 10:08:06 +000039import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
Ulf Adams84901732016-01-28 15:05:16 +000040import com.google.devtools.build.lib.collect.nestedset.Order;
Ulf Adams9e16f0a2016-01-25 12:43:32 +000041import com.google.devtools.build.lib.events.Event;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010042import com.google.devtools.build.lib.events.StoredEventHandler;
Dmitry Lomov2eb8bdd2016-04-06 08:47:30 +000043import com.google.devtools.build.lib.packages.Aspect;
Dmitry Lomove851fe22017-02-14 23:11:23 +000044import com.google.devtools.build.lib.packages.AspectDescriptor;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010045import com.google.devtools.build.lib.packages.Attribute;
Janak Ramakrishnan0a4c6e42015-09-17 00:37:58 +000046import com.google.devtools.build.lib.packages.BuildFileContainsErrorsException;
Dmitry Lomovc15ba2e2015-10-30 15:50:01 +000047import com.google.devtools.build.lib.packages.NativeAspectClass;
Ulf Adamsd55d7af2016-01-19 11:03:22 +000048import com.google.devtools.build.lib.packages.NoSuchThingException;
Marian Loburc62faba2015-09-09 10:08:06 +000049import com.google.devtools.build.lib.packages.Package;
Greg Estren00049432015-08-25 16:43:47 +000050import com.google.devtools.build.lib.packages.RuleClassProvider;
Googler74558fc2016-05-06 21:47:42 +000051import com.google.devtools.build.lib.packages.SkylarkAspect;
Dmitry Lomov82e03772015-11-30 12:13:22 +000052import com.google.devtools.build.lib.packages.SkylarkAspectClass;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010053import com.google.devtools.build.lib.packages.Target;
54import com.google.devtools.build.lib.skyframe.AspectValue.AspectKey;
Dmitry Lomov9b2fc5c2016-11-11 11:18:48 +000055import com.google.devtools.build.lib.skyframe.ConfiguredTargetFunction.ConfiguredTargetFunctionException;
Ulf Adams25f03d82016-01-25 10:31:46 +000056import com.google.devtools.build.lib.skyframe.ConfiguredTargetFunction.ConfiguredValueCreationException;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010057import com.google.devtools.build.lib.skyframe.ConfiguredTargetFunction.DependencyEvaluationException;
58import com.google.devtools.build.lib.skyframe.SkyframeExecutor.BuildViewProvider;
Ulf Adamsa47ca012016-01-20 10:35:19 +000059import com.google.devtools.build.lib.skyframe.SkylarkImportLookupFunction.SkylarkImportFailedException;
John Cater2e56f062017-07-20 19:43:20 +020060import com.google.devtools.build.lib.skyframe.ToolchainUtil.ToolchainContextException;
Dmitry Lomov0b832ce2015-10-20 10:03:14 +000061import com.google.devtools.build.lib.syntax.Type.ConversionException;
Greg Estrend5353252016-08-11 22:13:31 +000062import com.google.devtools.build.lib.util.OrderedSetMultimap;
Mark Schaller6df81792015-12-10 18:47:47 +000063import com.google.devtools.build.lib.util.Preconditions;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010064import com.google.devtools.build.skyframe.SkyFunction;
65import com.google.devtools.build.skyframe.SkyFunctionException;
66import com.google.devtools.build.skyframe.SkyKey;
67import com.google.devtools.build.skyframe.SkyValue;
Dmitry Lomovca9bfa42016-11-15 13:22:36 +000068import java.util.ArrayList;
Dmitry Lomove851fe22017-02-14 23:11:23 +000069import java.util.HashMap;
Dmitry Lomovca9bfa42016-11-15 13:22:36 +000070import java.util.Map;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010071import javax.annotation.Nullable;
72
73/**
74 * The Skyframe function that generates aspects.
Dmitry Lomove8040172016-04-06 14:53:43 +000075 *
Lukacs Berki2300cd62016-05-19 11:06:37 +000076 * This class, together with {@link ConfiguredTargetFunction} drives the analysis phase. For more
ulfjack26d0e492017-08-07 13:42:33 +020077 * information, see {@link com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory}.
Lukacs Berki2300cd62016-05-19 11:06:37 +000078 *
Dmitry Lomove8040172016-04-06 14:53:43 +000079 * {@link AspectFunction} takes a SkyKey containing an {@link AspectKey} [a tuple of
80 * (target label, configurations, aspect class and aspect parameters)],
81 * loads an {@link Aspect} from aspect class and aspect parameters,
82 * gets a {@link ConfiguredTarget} for label and configurations, and then creates
83 * a {@link ConfiguredAspect} for a given {@link AspectKey}.
84 *
85 * See {@link com.google.devtools.build.lib.packages.AspectClass} documentation
86 * for an overview of aspect-related classes
Lukacs Berki2300cd62016-05-19 11:06:37 +000087 *
ulfjack26d0e492017-08-07 13:42:33 +020088 * @see com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory
Lukacs Berki2300cd62016-05-19 11:06:37 +000089 * @see com.google.devtools.build.lib.packages.AspectClass
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010090 */
Dmitry Lomovc15ba2e2015-10-30 15:50:01 +000091public final class AspectFunction implements SkyFunction {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010092 private final BuildViewProvider buildViewProvider;
Greg Estren00049432015-08-25 16:43:47 +000093 private final RuleClassProvider ruleClassProvider;
janakr93e3eea2017-03-30 22:09:37 +000094 private final Supplier<Boolean> removeActionsAfterEvaluation;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010095
janakr93e3eea2017-03-30 22:09:37 +000096 AspectFunction(
97 BuildViewProvider buildViewProvider,
98 RuleClassProvider ruleClassProvider,
99 Supplier<Boolean> removeActionsAfterEvaluation) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100100 this.buildViewProvider = buildViewProvider;
Greg Estren00049432015-08-25 16:43:47 +0000101 this.ruleClassProvider = ruleClassProvider;
janakr93e3eea2017-03-30 22:09:37 +0000102 this.removeActionsAfterEvaluation = Preconditions.checkNotNull(removeActionsAfterEvaluation);
Dmitry Lomovc15ba2e2015-10-30 15:50:01 +0000103 }
104
105 /**
106 * Load Skylark aspect from an extension file. Is to be called from a SkyFunction.
107 *
108 * @return {@code null} if dependencies cannot be satisfied.
109 */
110 @Nullable
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000111 static SkylarkAspect loadSkylarkAspect(
John Fielda97e17f2015-11-13 02:19:52 +0000112 Environment env, Label extensionLabel, String skylarkValueName)
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000113 throws AspectCreationException, InterruptedException {
Damien Martin-Guillerez8ca065c22015-11-27 16:22:59 +0000114 SkyKey importFileKey = SkylarkImportLookupValue.key(extensionLabel, false);
Ulf Adams0678e792016-01-25 15:30:45 +0000115 try {
116 SkylarkImportLookupValue skylarkImportLookupValue =
117 (SkylarkImportLookupValue) env.getValueOrThrow(
118 importFileKey, SkylarkImportFailedException.class);
119 if (skylarkImportLookupValue == null) {
120 return null;
121 }
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +0000122
brandjon357ed7a2017-05-09 11:37:22 -0400123 Object skylarkValue = skylarkImportLookupValue.getEnvironmentExtension().getBindings()
Ulf Adams0678e792016-01-25 15:30:45 +0000124 .get(skylarkValueName);
Dmitry Lomov1920dd92017-07-21 12:57:18 +0200125 if (skylarkValue == null) {
126 throw new ConversionException(
127 String.format(
128 "%s is not exported from %s", skylarkValueName, extensionLabel.toString()));
129 }
Ulf Adams0678e792016-01-25 15:30:45 +0000130 if (!(skylarkValue instanceof SkylarkAspect)) {
131 throw new ConversionException(
Dmitry Lomov1920dd92017-07-21 12:57:18 +0200132 String.format(
133 "%s from %s is not an aspect", skylarkValueName, extensionLabel.toString()));
Ulf Adams0678e792016-01-25 15:30:45 +0000134 }
135 return (SkylarkAspect) skylarkValue;
136 } catch (SkylarkImportFailedException | ConversionException e) {
137 env.getListener().handle(Event.error(e.getMessage()));
138 throw new AspectCreationException(e.getMessage());
Dmitry Lomovc15ba2e2015-10-30 15:50:01 +0000139 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100140 }
141
142 @Nullable
143 @Override
144 public SkyValue compute(SkyKey skyKey, Environment env)
Florian Weikert4b67d4f2015-09-14 13:35:34 +0000145 throws AspectFunctionException, InterruptedException {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100146 SkyframeBuildView view = buildViewProvider.getSkyframeBuildView();
Marian Loburc62faba2015-09-09 10:08:06 +0000147 NestedSetBuilder<Package> transitivePackages = NestedSetBuilder.stableOrder();
Ulf Adams84901732016-01-28 15:05:16 +0000148 NestedSetBuilder<Label> transitiveRootCauses = NestedSetBuilder.stableOrder();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100149 AspectKey key = (AspectKey) skyKey.argument();
Dmitry Lomovc15ba2e2015-10-30 15:50:01 +0000150 ConfiguredAspectFactory aspectFactory;
Dmitry Lomov2eb8bdd2016-04-06 08:47:30 +0000151 Aspect aspect;
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +0000152 if (key.getAspectClass() instanceof NativeAspectClass) {
153 NativeAspectClass nativeAspectClass = (NativeAspectClass) key.getAspectClass();
154 aspectFactory = (ConfiguredAspectFactory) nativeAspectClass;
Dmitry Lomove8040172016-04-06 14:53:43 +0000155 aspect = Aspect.forNative(nativeAspectClass, key.getParameters());
Dmitry Lomovb487ac62015-11-09 13:09:12 +0000156 } else if (key.getAspectClass() instanceof SkylarkAspectClass) {
157 SkylarkAspectClass skylarkAspectClass = (SkylarkAspectClass) key.getAspectClass();
Dmitry Lomovc15ba2e2015-10-30 15:50:01 +0000158 SkylarkAspect skylarkAspect;
159 try {
160 skylarkAspect =
161 loadSkylarkAspect(
John Fielda97e17f2015-11-13 02:19:52 +0000162 env, skylarkAspectClass.getExtensionLabel(), skylarkAspectClass.getExportedName());
Ulf Adams0678e792016-01-25 15:30:45 +0000163 } catch (AspectCreationException e) {
164 throw new AspectFunctionException(e);
Dmitry Lomovc15ba2e2015-10-30 15:50:01 +0000165 }
166 if (skylarkAspect == null) {
167 return null;
168 }
169
Dmitry Lomov777845c2016-04-06 15:24:36 +0000170 aspectFactory = new SkylarkAspectFactory(skylarkAspect);
Dmitry Lomove8040172016-04-06 14:53:43 +0000171 aspect = Aspect.forSkylark(
172 skylarkAspect.getAspectClass(),
Googler74558fc2016-05-06 21:47:42 +0000173 skylarkAspect.getDefinition(key.getParameters()),
Dmitry Lomove8040172016-04-06 14:53:43 +0000174 key.getParameters());
Dmitry Lomovc15ba2e2015-10-30 15:50:01 +0000175 } else {
176 throw new IllegalStateException();
177 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100178
Ulf Adams9e16f0a2016-01-25 12:43:32 +0000179 // Keep this in sync with the same code in ConfiguredTargetFunction.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100180 PackageValue packageValue =
181 (PackageValue) env.getValue(PackageValue.key(key.getLabel().getPackageIdentifier()));
182 if (packageValue == null) {
183 return null;
184 }
Janak Ramakrishnan0a4c6e42015-09-17 00:37:58 +0000185 Package pkg = packageValue.getPackage();
186 if (pkg.containsErrors()) {
187 throw new AspectFunctionException(
Ulf Adams9e16f0a2016-01-25 12:43:32 +0000188 new BuildFileContainsErrorsException(key.getLabel().getPackageIdentifier()));
Janak Ramakrishnan0a4c6e42015-09-17 00:37:58 +0000189 }
Lukacs Berkiea988b62016-08-30 12:26:18 +0000190
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100191
Lukacs Berkiea988b62016-08-30 12:26:18 +0000192 ConfiguredTargetValue configuredTargetValue;
Ulf Adams84901732016-01-28 15:05:16 +0000193 try {
194 configuredTargetValue =
195 (ConfiguredTargetValue) env.getValueOrThrow(
Michael Staib04f6f242016-03-01 15:40:29 +0000196 ConfiguredTargetValue.key(key.getLabel(), key.getBaseConfiguration()),
Ulf Adams84901732016-01-28 15:05:16 +0000197 ConfiguredValueCreationException.class);
198 } catch (ConfiguredValueCreationException e) {
199 throw new AspectFunctionException(new AspectCreationException(e.getRootCauses()));
200 }
Dmitry Lomove2033b12015-08-19 16:57:49 +0000201 if (configuredTargetValue == null) {
Greg Estren00049432015-08-25 16:43:47 +0000202 // TODO(bazel-team): remove this check when top-level targets also use dynamic configurations.
203 // Right now the key configuration may be dynamic while the original target's configuration
204 // is static, resulting in a Skyframe cache miss even though the original target is, in fact,
205 // precomputed.
Dmitry Lomove2033b12015-08-19 16:57:49 +0000206 return null;
207 }
Lukacs Berkiea988b62016-08-30 12:26:18 +0000208
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000209
Lukacs Berkiea988b62016-08-30 12:26:18 +0000210 if (configuredTargetValue.getConfiguredTarget() == null) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100211 return null;
212 }
213
dslomov99ea6b42017-04-25 17:46:17 +0200214 ConfiguredTarget associatedTarget = configuredTargetValue.getConfiguredTarget();
215
216 Target target = associatedTarget.getTarget();
dslomov99ea6b42017-04-25 17:46:17 +0200217
Lukacs Berkiea988b62016-08-30 12:26:18 +0000218 if (configuredTargetValue.getConfiguredTarget().getProvider(AliasProvider.class) != null) {
219 return createAliasAspect(env, target, aspect, key,
220 configuredTargetValue.getConfiguredTarget());
221 }
222
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000223
Dmitry Lomov15756522016-12-16 16:52:37 +0000224 ImmutableList.Builder<Aspect> aspectPathBuilder = ImmutableList.builder();
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000225
Dmitry Lomove851fe22017-02-14 23:11:23 +0000226 if (!key.getBaseKeys().isEmpty()) {
227 // We transitively collect all required aspects to reduce the number of restarts.
228 // Semantically it is enough to just request key.getBaseKeys().
dslomov039b9ee2017-04-11 08:51:30 +0000229 ImmutableList.Builder<SkyKey> aspectPathSkyKeysBuilder = ImmutableList.builder();
230 ImmutableMap<AspectDescriptor, SkyKey> aspectKeys =
231 getSkyKeysForAspectsAndCollectAspectPath(key.getBaseKeys(), aspectPathSkyKeysBuilder);
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000232
Dmitry Lomove851fe22017-02-14 23:11:23 +0000233 Map<SkyKey, SkyValue> values = env.getValues(aspectKeys.values());
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000234 if (env.valuesMissing()) {
235 return null;
236 }
dslomov039b9ee2017-04-11 08:51:30 +0000237 ImmutableList<SkyKey> aspectPathSkyKeys = aspectPathSkyKeysBuilder.build();
238 for (SkyKey aspectPathSkyKey : aspectPathSkyKeys) {
239 aspectPathBuilder.add(((AspectValue) values.get(aspectPathSkyKey)).getAspect());
240 }
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000241 try {
dslomov039b9ee2017-04-11 08:51:30 +0000242 associatedTarget = getBaseTarget(
243 associatedTarget, key.getBaseKeys(), values);
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000244 } catch (DuplicateException e) {
245 env.getListener().handle(
246 Event.error(associatedTarget.getTarget().getLocation(), e.getMessage()));
247
248 throw new AspectFunctionException(
249 new AspectCreationException(e.getMessage(), associatedTarget.getLabel()));
250
251 }
252 }
Dmitry Lomov15756522016-12-16 16:52:37 +0000253 aspectPathBuilder.add(aspect);
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000254
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100255 SkyframeDependencyResolver resolver = view.createDependencyResolver(env);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100256
Michael Staib04f6f242016-03-01 15:40:29 +0000257 // When getting the dependencies of this hybrid aspect+base target, use the aspect's
258 // configuration. The configuration of the aspect will always be a superset of the target's
gregcee0bbe752017-09-12 23:58:34 +0200259 // (trimmed configuration mode: target is part of the aspect's config fragment requirements;
260 // untrimmed mode: target is the same configuration as the aspect), so the fragments
Michael Staib04f6f242016-03-01 15:40:29 +0000261 // required by all dependencies (both those of the aspect and those of the base target)
262 // will be present this way.
263 TargetAndConfiguration originalTargetAndAspectConfiguration =
264 new TargetAndConfiguration(target, key.getAspectConfiguration());
Dmitry Lomov15756522016-12-16 16:52:37 +0000265 ImmutableList<Aspect> aspectPath = aspectPathBuilder.build();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100266 try {
267 // Get the configuration targets that trigger this rule's configurable attributes.
Lukacs Berki7894c182016-05-10 12:07:01 +0000268 ImmutableMap<Label, ConfigMatchingProvider> configConditions =
269 ConfiguredTargetFunction.getConfigConditions(
270 target, env, resolver, originalTargetAndAspectConfiguration,
271 transitivePackages, transitiveRootCauses);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100272 if (configConditions == null) {
273 // Those targets haven't yet been resolved.
274 return null;
275 }
276
John Cater2e56f062017-07-20 19:43:20 +0200277 // Determine what toolchains are needed by this target.
278 ToolchainContext toolchainContext;
279 try {
cpeyserfb829992017-09-07 17:17:03 +0200280 ImmutableSet<Label> requiredToolchains = aspect.getDefinition().getRequiredToolchains();
John Cater2e56f062017-07-20 19:43:20 +0200281 toolchainContext =
282 ToolchainUtil.createToolchainContext(
John Cater53a87b92017-08-01 00:53:39 +0200283 env,
284 String.format(
285 "aspect %s applied to %s",
286 aspect.getDescriptor().getDescription(), target.toString()),
287 requiredToolchains,
288 key.getAspectConfiguration());
John Cater2e56f062017-07-20 19:43:20 +0200289 } catch (ToolchainContextException e) {
290 // TODO(katre): better error handling
291 throw new AspectCreationException(e.getMessage());
292 }
293 if (env.valuesMissing()) {
294 return null;
295 }
296
Dmitry Lomov9b2fc5c2016-11-11 11:18:48 +0000297 OrderedSetMultimap<Attribute, ConfiguredTarget> depValueMap;
298 try {
John Cater2e56f062017-07-20 19:43:20 +0200299 depValueMap =
300 ConfiguredTargetFunction.computeDependencies(
301 env,
302 resolver,
303 originalTargetAndAspectConfiguration,
304 aspectPath,
305 configConditions,
306 toolchainContext,
307 ruleClassProvider,
308 view.getHostConfiguration(originalTargetAndAspectConfiguration.getConfiguration()),
309 transitivePackages,
310 transitiveRootCauses);
Dmitry Lomov9b2fc5c2016-11-11 11:18:48 +0000311 } catch (ConfiguredTargetFunctionException e) {
312 throw new AspectCreationException(e.getMessage());
313 }
Ulf Adams84901732016-01-28 15:05:16 +0000314 if (depValueMap == null) {
315 return null;
316 }
317 if (!transitiveRootCauses.isEmpty()) {
318 throw new AspectFunctionException(
319 new AspectCreationException("Loading failed", transitiveRootCauses.build()));
320 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100321
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000322 return createAspect(
323 env,
324 key,
Dmitry Lomov15756522016-12-16 16:52:37 +0000325 aspectPath,
Dmitry Lomov2eb8bdd2016-04-06 08:47:30 +0000326 aspect,
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000327 aspectFactory,
328 associatedTarget,
Michael Staib04f6f242016-03-01 15:40:29 +0000329 key.getAspectConfiguration(),
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000330 configConditions,
John Cater2e56f062017-07-20 19:43:20 +0200331 toolchainContext,
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000332 depValueMap,
Marian Loburc62faba2015-09-09 10:08:06 +0000333 transitivePackages);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100334 } catch (DependencyEvaluationException e) {
Ulf Adams25f03d82016-01-25 10:31:46 +0000335 if (e.getCause() instanceof ConfiguredValueCreationException) {
336 ConfiguredValueCreationException cause = (ConfiguredValueCreationException) e.getCause();
337 throw new AspectFunctionException(new AspectCreationException(
338 cause.getMessage(), cause.getAnalysisRootCause()));
Dmitry Lomovd83af9e2017-02-23 15:44:23 +0000339 } else if (e.getCause() instanceof InconsistentAspectOrderException) {
340 InconsistentAspectOrderException cause = (InconsistentAspectOrderException) e.getCause();
341 throw new AspectFunctionException(new AspectCreationException(
342 cause.getMessage()));
Ulf Adams25f03d82016-01-25 10:31:46 +0000343 } else {
344 // Cast to InvalidConfigurationException as a consistency check. If you add any
345 // DependencyEvaluationException constructors, you may need to change this code, too.
346 InvalidConfigurationException cause = (InvalidConfigurationException) e.getCause();
347 throw new AspectFunctionException(new AspectCreationException(cause.getMessage()));
348 }
Marian Loburfc567b32015-09-14 08:44:25 +0000349 } catch (AspectCreationException e) {
350 throw new AspectFunctionException(e);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100351 }
352 }
353
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000354 /**
355 * Merges aspects defined by {@code aspectKeys} into the {@code target} using
356 * previously computed {@code values}.
357 *
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000358 * @return A {@link ConfiguredTarget} that is a result of a merge.
359 * @throws DuplicateException if there is a duplicate provider provided by aspects.
360 */
dslomov039b9ee2017-04-11 08:51:30 +0000361 private ConfiguredTarget getBaseTarget(ConfiguredTarget target,
Dmitry Lomove851fe22017-02-14 23:11:23 +0000362 ImmutableList<AspectKey> aspectKeys,
dslomov039b9ee2017-04-11 08:51:30 +0000363 Map<SkyKey, SkyValue> values)
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000364 throws DuplicateException {
365 ArrayList<ConfiguredAspect> aspectValues = new ArrayList<>();
Dmitry Lomove851fe22017-02-14 23:11:23 +0000366 for (AspectKey aspectKey : aspectKeys) {
367 SkyKey skyAspectKey = aspectKey.getSkyKey();
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000368 AspectValue aspectValue = (AspectValue) values.get(skyAspectKey);
369 ConfiguredAspect configuredAspect = aspectValue.getConfiguredAspect();
370 aspectValues.add(configuredAspect);
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000371 }
372 return MergedConfiguredTarget.of(target, aspectValues);
373 }
374
375 /**
Dmitry Lomove851fe22017-02-14 23:11:23 +0000376 * Collect all SkyKeys that are needed for a given list of AspectKeys,
377 * including transitive dependencies.
dslomov039b9ee2017-04-11 08:51:30 +0000378 *
379 * Also collects all propagating aspects in correct order.
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000380 */
dslomov039b9ee2017-04-11 08:51:30 +0000381 private ImmutableMap<AspectDescriptor, SkyKey> getSkyKeysForAspectsAndCollectAspectPath(
382 ImmutableList<AspectKey> keys,
383 ImmutableList.Builder<SkyKey> aspectPathBuilder) {
Dmitry Lomove851fe22017-02-14 23:11:23 +0000384 HashMap<AspectDescriptor, SkyKey> result = new HashMap<>();
385 for (AspectKey key : keys) {
dslomov039b9ee2017-04-11 08:51:30 +0000386 buildSkyKeys(key, result, aspectPathBuilder);
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000387 }
Dmitry Lomove851fe22017-02-14 23:11:23 +0000388 return ImmutableMap.copyOf(result);
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000389 }
390
dslomov039b9ee2017-04-11 08:51:30 +0000391 private void buildSkyKeys(AspectKey key, HashMap<AspectDescriptor, SkyKey> result,
392 ImmutableList.Builder<SkyKey> aspectPathBuilder) {
Dmitry Lomove851fe22017-02-14 23:11:23 +0000393 if (result.containsKey(key.getAspectDescriptor())) {
394 return;
395 }
396 ImmutableList<AspectKey> baseKeys = key.getBaseKeys();
dslomov039b9ee2017-04-11 08:51:30 +0000397 SkyKey skyKey = key.getSkyKey();
398 result.put(key.getAspectDescriptor(), skyKey);
Dmitry Lomove851fe22017-02-14 23:11:23 +0000399 for (AspectKey baseKey : baseKeys) {
dslomov039b9ee2017-04-11 08:51:30 +0000400 buildSkyKeys(baseKey, result, aspectPathBuilder);
Dmitry Lomove851fe22017-02-14 23:11:23 +0000401 }
dslomov039b9ee2017-04-11 08:51:30 +0000402 // Post-order list of aspect SkyKeys gives the order of propagating aspects:
403 // the aspect comes after all aspects it transitively sees.
404 aspectPathBuilder.add(skyKey);
Dmitry Lomove851fe22017-02-14 23:11:23 +0000405 }
dslomovfa50c3d2017-05-08 08:47:44 -0400406
janakr93e3eea2017-03-30 22:09:37 +0000407 private SkyValue createAliasAspect(
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000408 Environment env,
409 Target originalTarget,
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000410 Aspect aspect,
Lukacs Berkiea988b62016-08-30 12:26:18 +0000411 AspectKey originalKey,
janakr93e3eea2017-03-30 22:09:37 +0000412 ConfiguredTarget configuredTarget)
413 throws InterruptedException {
Lukacs Berkiea988b62016-08-30 12:26:18 +0000414 ImmutableList<Label> aliasChain = configuredTarget.getProvider(AliasProvider.class)
415 .getAliasChain();
416 // Find the next alias in the chain: either the next alias (if there are two) or the name of
417 // the real configured target.
418 Label aliasLabel = aliasChain.size() > 1 ? aliasChain.get(1) : configuredTarget.getLabel();
419
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000420 SkyKey depKey = ActionLookupValue.key(originalKey.withLabel(aliasLabel));
Lukacs Berkiea988b62016-08-30 12:26:18 +0000421
422 // Compute the AspectValue of the target the alias refers to (which can itself be either an
423 // alias or a real target)
Lukacs Berki549bfce2016-04-22 15:29:12 +0000424 AspectValue real = (AspectValue) env.getValue(depKey);
425 if (env.valuesMissing()) {
426 return null;
427 }
428
429 NestedSet<Package> transitivePackages = NestedSetBuilder.<Package>stableOrder()
430 .addTransitive(real.getTransitivePackages())
431 .add(originalTarget.getPackage())
432 .build();
Lukacs Berkiea988b62016-08-30 12:26:18 +0000433
Lukacs Berki549bfce2016-04-22 15:29:12 +0000434 return new AspectValue(
435 originalKey,
436 aspect,
437 originalTarget.getLabel(),
438 originalTarget.getLocation(),
439 ConfiguredAspect.forAlias(real.getConfiguredAspect()),
Rumou Duan33bab462016-04-25 17:55:12 +0000440 ImmutableList.<ActionAnalysisMetadata>of(),
janakr93e3eea2017-03-30 22:09:37 +0000441 transitivePackages,
442 removeActionsAfterEvaluation.get());
Lukacs Berki549bfce2016-04-22 15:29:12 +0000443 }
444
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100445 @Nullable
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000446 private AspectValue createAspect(
447 Environment env,
448 AspectKey key,
Dmitry Lomov15756522016-12-16 16:52:37 +0000449 ImmutableList<Aspect> aspectPath,
Dmitry Lomov2eb8bdd2016-04-06 08:47:30 +0000450 Aspect aspect,
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000451 ConfiguredAspectFactory aspectFactory,
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000452 ConfiguredTarget associatedTarget,
Michael Staib04f6f242016-03-01 15:40:29 +0000453 BuildConfiguration aspectConfiguration,
Lukacs Berki7894c182016-05-10 12:07:01 +0000454 ImmutableMap<Label, ConfigMatchingProvider> configConditions,
John Cater2e56f062017-07-20 19:43:20 +0200455 ToolchainContext toolchainContext,
Greg Estrend5353252016-08-11 22:13:31 +0000456 OrderedSetMultimap<Attribute, ConfiguredTarget> directDeps,
Marian Loburc62faba2015-09-09 10:08:06 +0000457 NestedSetBuilder<Package> transitivePackages)
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000458 throws AspectFunctionException, InterruptedException {
Marian Loburc62faba2015-09-09 10:08:06 +0000459
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100460 SkyframeBuildView view = buildViewProvider.getSkyframeBuildView();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100461
462 StoredEventHandler events = new StoredEventHandler();
463 CachingAnalysisEnvironment analysisEnvironment = view.createAnalysisEnvironment(
Michael Staib04f6f242016-03-01 15:40:29 +0000464 key, false, events, env, aspectConfiguration);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100465 if (env.valuesMissing()) {
466 return null;
467 }
468
Dmitry Lomov6cd98972017-03-01 15:44:00 +0000469 ConfiguredAspect configuredAspect;
gregce4c3ef112017-09-20 23:43:14 +0200470 if (AspectResolver.aspectMatchesConfiguredTarget(associatedTarget, aspect)) {
John Cater2e56f062017-07-20 19:43:20 +0200471 configuredAspect =
472 view.getConfiguredTargetFactory()
473 .createAspect(
474 analysisEnvironment,
475 associatedTarget,
476 aspectPath,
477 aspectFactory,
478 aspect,
479 directDeps,
480 configConditions,
481 toolchainContext,
482 aspectConfiguration,
483 view.getHostConfiguration(aspectConfiguration));
Dmitry Lomov6cd98972017-03-01 15:44:00 +0000484 } else {
485 configuredAspect = ConfiguredAspect.forNonapplicableTarget(aspect.getDescriptor());
486 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100487
488 events.replayOn(env.getListener());
489 if (events.hasErrors()) {
490 analysisEnvironment.disable(associatedTarget.getTarget());
491 throw new AspectFunctionException(new AspectCreationException(
492 "Analysis of target '" + associatedTarget.getLabel() + "' failed; build aborted"));
493 }
494 Preconditions.checkState(!analysisEnvironment.hasErrors(),
495 "Analysis environment hasError() but no errors reported");
496
497 if (env.valuesMissing()) {
498 return null;
499 }
500
501 analysisEnvironment.disable(associatedTarget.getTarget());
Dmitry Lomovb487ac62015-11-09 13:09:12 +0000502 Preconditions.checkNotNull(configuredAspect);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100503
504 return new AspectValue(
Dmitry Lomove2033b12015-08-19 16:57:49 +0000505 key,
Dmitry Lomov2eb8bdd2016-04-06 08:47:30 +0000506 aspect,
Dmitry Lomove2033b12015-08-19 16:57:49 +0000507 associatedTarget.getLabel(),
508 associatedTarget.getTarget().getLocation(),
Dmitry Lomovb487ac62015-11-09 13:09:12 +0000509 configuredAspect,
Marian Loburc62faba2015-09-09 10:08:06 +0000510 ImmutableList.copyOf(analysisEnvironment.getRegisteredActions()),
janakr93e3eea2017-03-30 22:09:37 +0000511 transitivePackages.build(),
512 removeActionsAfterEvaluation.get());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100513 }
514
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100515 @Override
516 public String extractTag(SkyKey skyKey) {
Michael Staib2707a882016-09-16 21:06:40 +0000517 AspectKey aspectKey = (AspectKey) skyKey.argument();
518 return Label.print(aspectKey.getLabel());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100519 }
Marian Loburc62faba2015-09-09 10:08:06 +0000520
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100521 /**
522 * An exception indicating that there was a problem creating an aspect.
523 */
524 public static final class AspectCreationException extends Exception {
Ulf Adams84901732016-01-28 15:05:16 +0000525 /** Targets in the transitive closure that failed to load. May be empty. */
526 private final NestedSet<Label> loadingRootCauses;
527
Ulf Adams25f03d82016-01-25 10:31:46 +0000528 /**
529 * The target for which analysis failed, if any. We can't represent aspects with labels, so if
530 * the aspect analysis fails, this will be {@code null}.
531 */
532 @Nullable private final Label analysisRootCause;
533
534 public AspectCreationException(String message, Label analysisRootCause) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100535 super(message);
Ulf Adams84901732016-01-28 15:05:16 +0000536 this.loadingRootCauses = NestedSetBuilder.<Label>emptySet(Order.STABLE_ORDER);
Ulf Adams25f03d82016-01-25 10:31:46 +0000537 this.analysisRootCause = analysisRootCause;
538 }
539
Ulf Adams84901732016-01-28 15:05:16 +0000540 public AspectCreationException(String message, NestedSet<Label> loadingRootCauses) {
541 super(message);
542 this.loadingRootCauses = loadingRootCauses;
543 this.analysisRootCause = null;
544 }
545
546 public AspectCreationException(NestedSet<Label> loadingRootCauses) {
547 this("Loading failed", loadingRootCauses);
548 }
549
Ulf Adams25f03d82016-01-25 10:31:46 +0000550 public AspectCreationException(String message) {
Ulf Adams84901732016-01-28 15:05:16 +0000551 this(message, (Label) null);
552 }
553
554 public NestedSet<Label> getRootCauses() {
555 return loadingRootCauses;
Ulf Adams25f03d82016-01-25 10:31:46 +0000556 }
557
558 @Nullable public Label getAnalysisRootCause() {
559 return analysisRootCause;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100560 }
561 }
562
563 /**
564 * Used to indicate errors during the computation of an {@link AspectValue}.
565 */
566 private static final class AspectFunctionException extends SkyFunctionException {
Ulf Adams9e16f0a2016-01-25 12:43:32 +0000567 public AspectFunctionException(NoSuchThingException e) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100568 super(e, Transience.PERSISTENT);
569 }
570
Ulf Adams9e16f0a2016-01-25 12:43:32 +0000571 public AspectFunctionException(AspectCreationException e) {
572 super(e, Transience.PERSISTENT);
Ulf Adamsd55d7af2016-01-19 11:03:22 +0000573 }
Dmitry Lomovd83af9e2017-02-23 15:44:23 +0000574
575 public AspectFunctionException(InconsistentAspectOrderException cause) {
576 super(cause, Transience.PERSISTENT);
577 }
Ulf Adamsd55d7af2016-01-19 11:03:22 +0000578 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100579}