blob: b620259f25deb266d78e5dbb95b5990c56773743 [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
Eric Fellheimere27d0632015-09-25 21:35:26 +000016import com.google.common.collect.ImmutableList;
Greg Estren531fc042015-05-26 22:37:44 +000017import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
18import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
Mark Schallerb25759c2015-07-29 17:09:18 +000019import com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment;
Googler119b15f2016-07-22 19:22:48 +000020import com.google.devtools.build.lib.analysis.config.ConfigRuleClasses.ConfigSettingRule;
Greg Estren23b51812016-08-02 18:07:41 +000021import com.google.devtools.build.lib.analysis.config.ConfigurationFragmentFactory;
Greg Estren4f3b2b32015-11-19 19:39:50 +000022import com.google.devtools.build.lib.analysis.config.FragmentOptions;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000023import com.google.devtools.build.lib.cmdline.Label;
Kristina Chodorow73fa2032015-08-28 17:57:46 +000024import com.google.devtools.build.lib.cmdline.PackageIdentifier;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010025import com.google.devtools.build.lib.collect.nestedset.NestedSet;
26import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
Mark Schaller6b6d8a92015-10-23 01:00:28 +000027import com.google.devtools.build.lib.events.Event;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010028import com.google.devtools.build.lib.events.EventHandler;
Eric Fellheimerb5c98842015-08-12 23:24:21 +000029import com.google.devtools.build.lib.packages.AspectDefinition;
30import com.google.devtools.build.lib.packages.Attribute;
Michael Staibb51251e2015-09-29 23:31:51 +000031import com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy;
Dmitry Lomov940ea072016-01-21 22:34:14 +000032import com.google.devtools.build.lib.packages.DependencyFilter;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010033import com.google.devtools.build.lib.packages.NoSuchPackageException;
34import com.google.devtools.build.lib.packages.NoSuchTargetException;
Eric Fellheimerb5c98842015-08-12 23:24:21 +000035import com.google.devtools.build.lib.packages.NoSuchThingException;
Janak Ramakrishnan0a4c6e42015-09-17 00:37:58 +000036import com.google.devtools.build.lib.packages.Package;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010037import com.google.devtools.build.lib.packages.Rule;
Greg Estren531fc042015-05-26 22:37:44 +000038import com.google.devtools.build.lib.packages.RuleClassProvider;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010039import com.google.devtools.build.lib.packages.Target;
Mark Schaller6b6d8a92015-10-23 01:00:28 +000040import com.google.devtools.build.lib.packages.TargetUtils;
Mark Schallerb25759c2015-07-29 17:09:18 +000041import com.google.devtools.build.lib.skyframe.TransitiveTargetFunction.TransitiveTargetValueBuilder;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010042import com.google.devtools.build.skyframe.SkyKey;
43import com.google.devtools.build.skyframe.SkyValue;
Mark Schallerc18381e2015-07-29 16:51:14 +000044import com.google.devtools.build.skyframe.ValueOrException2;
Greg Estren4f3b2b32015-11-19 19:39:50 +000045import com.google.devtools.common.options.Option;
Greg Estren4f3b2b32015-11-19 19:39:50 +000046import java.lang.reflect.Field;
Marian Loburfdd788e2015-03-25 09:36:28 +000047import java.util.Collection;
Googler119b15f2016-07-22 19:22:48 +000048import java.util.HashMap;
Greg Estren4f3b2b32015-11-19 19:39:50 +000049import java.util.LinkedHashMap;
Greg Estren531fc042015-05-26 22:37:44 +000050import java.util.LinkedHashSet;
Greg Estren4f3b2b32015-11-19 19:39:50 +000051import java.util.Map;
Marian Loburfdd788e2015-03-25 09:36:28 +000052import java.util.Map.Entry;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010053import java.util.Set;
Mark Schallerb25759c2015-07-29 17:09:18 +000054import javax.annotation.Nullable;
55
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010056/**
57 * This class builds transitive Target values such that evaluating a Target value is similar to
58 * running it through the LabelVisitor.
59 */
Mark Schallerb25759c2015-07-29 17:09:18 +000060public class TransitiveTargetFunction
61 extends TransitiveBaseTraversalFunction<TransitiveTargetValueBuilder> {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010062
Greg Estren531fc042015-05-26 22:37:44 +000063 private final ConfiguredRuleClassProvider ruleClassProvider;
64
Greg Estren4f3b2b32015-11-19 19:39:50 +000065 /**
66 * Maps build option names to matching config fragments. This is used to determine correct
67 * fragment requirements for config_setting rules, which are unique in that their dependencies
68 * are triggered by string representations of option names.
69 */
70 private final Map<String, Class<? extends Fragment>> optionsToFragmentMap;
71
Greg Estren531fc042015-05-26 22:37:44 +000072 TransitiveTargetFunction(RuleClassProvider ruleClassProvider) {
73 this.ruleClassProvider = (ConfiguredRuleClassProvider) ruleClassProvider;
Greg Estren4f3b2b32015-11-19 19:39:50 +000074 this.optionsToFragmentMap = computeOptionsToFragmentMap(this.ruleClassProvider);
75 }
76
77 /**
78 * Computes the option name --> config fragments map. Note that this mapping is technically
79 * one-to-many: a single option may be required by multiple fragments (e.g. Java options are
80 * used by both JavaConfiguration and Jvm). In such cases, we arbitrarily choose one fragment
81 * since that's all that's needed to satisfy the config_setting.
82 */
83 private static Map<String, Class<? extends Fragment>> computeOptionsToFragmentMap(
84 ConfiguredRuleClassProvider ruleClassProvider) {
85 Map<String, Class<? extends Fragment>> result = new LinkedHashMap<>();
Googler119b15f2016-07-22 19:22:48 +000086 Map<Class<? extends FragmentOptions>, Integer> visitedOptionsClasses = new HashMap<>();
Greg Estren4f3b2b32015-11-19 19:39:50 +000087 for (ConfigurationFragmentFactory factory : ruleClassProvider.getConfigurationFragments()) {
Googler119b15f2016-07-22 19:22:48 +000088 Set<Class<? extends FragmentOptions>> requiredOpts = factory.requiredOptions();
89 for (Class<? extends FragmentOptions> optionsClass : requiredOpts) {
90 Integer previousBest = visitedOptionsClasses.get(optionsClass);
91 if (previousBest != null && previousBest <= requiredOpts.size()) {
Greg Estren4f3b2b32015-11-19 19:39:50 +000092 // Multiple config fragments may require the same options class, but we only need one of
Googler119b15f2016-07-22 19:22:48 +000093 // them to guarantee that class makes it into the configuration. Pick one that depends
94 // on as few options classes as possible (not necessarily unique).
Greg Estren4f3b2b32015-11-19 19:39:50 +000095 continue;
96 }
Googler119b15f2016-07-22 19:22:48 +000097 visitedOptionsClasses.put(optionsClass, requiredOpts.size());
Greg Estren4f3b2b32015-11-19 19:39:50 +000098 for (Field field : optionsClass.getFields()) {
99 if (field.isAnnotationPresent(Option.class)) {
100 result.put(field.getAnnotation(Option.class).name(), factory.creates());
101 }
102 }
103 }
104 }
105 return result;
Greg Estren531fc042015-05-26 22:37:44 +0000106 }
107
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100108 @Override
Mark Schallerb25759c2015-07-29 17:09:18 +0000109 SkyKey getKey(Label label) {
110 return TransitiveTargetValue.key(label);
Marian Loburfdd788e2015-03-25 09:36:28 +0000111 }
112
Mark Schallerb25759c2015-07-29 17:09:18 +0000113 @Override
114 TransitiveTargetValueBuilder processTarget(Label label, TargetAndErrorIfAny targetAndErrorIfAny) {
115 Target target = targetAndErrorIfAny.getTarget();
116 boolean packageLoadedSuccessfully = targetAndErrorIfAny.isPackageLoadedSuccessfully();
117 return new TransitiveTargetValueBuilder(label, target, packageLoadedSuccessfully);
Greg Estren531fc042015-05-26 22:37:44 +0000118 }
119
Mark Schallerb25759c2015-07-29 17:09:18 +0000120 @Override
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000121 void processDeps(
122 TransitiveTargetValueBuilder builder,
123 EventHandler eventHandler,
Mark Schallerb25759c2015-07-29 17:09:18 +0000124 TargetAndErrorIfAny targetAndErrorIfAny,
125 Iterable<Entry<SkyKey, ValueOrException2<NoSuchPackageException, NoSuchTargetException>>>
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000126 depEntries)
127 throws InterruptedException {
Mark Schallerb25759c2015-07-29 17:09:18 +0000128 boolean successfulTransitiveLoading = builder.isSuccessfulTransitiveLoading();
129 Target target = targetAndErrorIfAny.getTarget();
130 NestedSetBuilder<Label> transitiveRootCauses = builder.getTransitiveRootCauses();
131
Mark Schallerc18381e2015-07-29 16:51:14 +0000132 for (Entry<SkyKey, ValueOrException2<NoSuchPackageException, NoSuchTargetException>> entry :
Mark Schallerb25759c2015-07-29 17:09:18 +0000133 depEntries) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100134 Label depLabel = (Label) entry.getKey().argument();
135 TransitiveTargetValue transitiveTargetValue;
136 try {
137 transitiveTargetValue = (TransitiveTargetValue) entry.getValue().get();
138 if (transitiveTargetValue == null) {
139 continue;
140 }
141 } catch (NoSuchPackageException | NoSuchTargetException e) {
142 successfulTransitiveLoading = false;
143 transitiveRootCauses.add(depLabel);
Mark Schallerb25759c2015-07-29 17:09:18 +0000144 maybeReportErrorAboutMissingEdge(target, depLabel, e, eventHandler);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100145 continue;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100146 }
Mark Schallerb25759c2015-07-29 17:09:18 +0000147 builder.getTransitiveSuccessfulPkgs().addTransitive(
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100148 transitiveTargetValue.getTransitiveSuccessfulPackages());
Mark Schallerb25759c2015-07-29 17:09:18 +0000149 builder.getTransitiveUnsuccessfulPkgs().addTransitive(
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100150 transitiveTargetValue.getTransitiveUnsuccessfulPackages());
Mark Schallerb25759c2015-07-29 17:09:18 +0000151 builder.getTransitiveTargets().addTransitive(transitiveTargetValue.getTransitiveTargets());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100152 NestedSet<Label> rootCauses = transitiveTargetValue.getTransitiveRootCauses();
153 if (rootCauses != null) {
154 successfulTransitiveLoading = false;
155 transitiveRootCauses.addTransitive(rootCauses);
156 if (transitiveTargetValue.getErrorLoadingTarget() != null) {
157 maybeReportErrorAboutMissingEdge(target, depLabel,
Mark Schallerb25759c2015-07-29 17:09:18 +0000158 transitiveTargetValue.getErrorLoadingTarget(), eventHandler);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100159 }
160 }
Greg Estren531fc042015-05-26 22:37:44 +0000161
Mark Schallerb25759c2015-07-29 17:09:18 +0000162 NestedSet<Class<? extends Fragment>> depFragments =
Greg Estren531fc042015-05-26 22:37:44 +0000163 transitiveTargetValue.getTransitiveConfigFragments();
Mark Schallerb25759c2015-07-29 17:09:18 +0000164 Collection<Class<? extends Fragment>> depFragmentsAsCollection =
Greg Estren531fc042015-05-26 22:37:44 +0000165 depFragments.toCollection();
166 // The simplest collection technique would be to unconditionally add all deps' nested
167 // sets to the current target's nested set. But when there's large overlap between their
168 // fragment needs, this produces unnecessarily bloated nested sets and a lot of references
169 // that don't contribute anything unique to the required fragment set. So we optimize here
170 // by completely skipping sets that don't offer anything new. More fine-tuned optimization
171 // is possible, but this offers a good balance between simplicity and practical efficiency.
Mark Schallerb25759c2015-07-29 17:09:18 +0000172 Set<Class<? extends Fragment>> addedConfigFragments = builder.getConfigFragmentsFromDeps();
Greg Estren531fc042015-05-26 22:37:44 +0000173 if (!addedConfigFragments.containsAll(depFragmentsAsCollection)) {
Mark Schallerb25759c2015-07-29 17:09:18 +0000174 builder.getTransitiveConfigFragments().addTransitive(depFragments);
Greg Estren531fc042015-05-26 22:37:44 +0000175 addedConfigFragments.addAll(depFragmentsAsCollection);
176 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100177 }
Mark Schallerb25759c2015-07-29 17:09:18 +0000178 builder.setSuccessfulTransitiveLoading(successfulTransitiveLoading);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100179 }
180
181 @Override
Mark Schallerb25759c2015-07-29 17:09:18 +0000182 public SkyValue computeSkyValue(TargetAndErrorIfAny targetAndErrorIfAny,
183 TransitiveTargetValueBuilder builder) {
184 Target target = targetAndErrorIfAny.getTarget();
185 NoSuchTargetException errorLoadingTarget = targetAndErrorIfAny.getErrorLoadingTarget();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100186
Greg Estren23b51812016-08-02 18:07:41 +0000187 // Get configuration fragments directly required by this rule.
Marian Loburfdd788e2015-03-25 09:36:28 +0000188 if (target instanceof Rule) {
Greg Estren23b51812016-08-02 18:07:41 +0000189 Rule rule = (Rule) target;
190
191 // Declared by the rule class:
Michael Staibb51251e2015-09-29 23:31:51 +0000192 ConfigurationFragmentPolicy configurationFragmentPolicy =
Greg Estren23b51812016-08-02 18:07:41 +0000193 rule.getRuleClassObject().getConfigurationFragmentPolicy();
Greg Estrene2eb6392015-11-17 16:05:29 +0000194 for (ConfigurationFragmentFactory factory : ruleClassProvider.getConfigurationFragments()) {
195 Class<? extends Fragment> fragment = factory.creates();
196 // isLegalConfigurationFragment considers both natively declared fragments and Skylark
197 // (named) fragments.
Greg Estren23b51812016-08-02 18:07:41 +0000198 if (configurationFragmentPolicy.isLegalConfigurationFragment(fragment)) {
199 addFragmentIfNew(builder, fragment.asSubclass(BuildConfiguration.Fragment.class));
200 }
201 }
202
203 // Declared by late-bound attributes:
204 for (Attribute attr : rule.getAttributes()) {
205 if (attr.isLateBound()) {
206 addFragmentsIfNew(builder,
207 attr.getLateBoundDefault().getRequiredConfigurationFragments());
Marian Loburfdd788e2015-03-25 09:36:28 +0000208 }
209 }
Greg Estren4f3b2b32015-11-19 19:39:50 +0000210
211 // config_setting rules have values like {"some_flag": "some_value"} that need the
Greg Estren23b51812016-08-02 18:07:41 +0000212 // corresponding fragments in their configurations to properly resolve:
Greg Estren4f3b2b32015-11-19 19:39:50 +0000213 if (rule.getRuleClass().equals(ConfigSettingRule.RULE_NAME)) {
Greg Estren23b51812016-08-02 18:07:41 +0000214 addFragmentsIfNew(builder,
Greg Estren4f3b2b32015-11-19 19:39:50 +0000215 ConfigSettingRule.requiresConfigurationFragments(rule, optionsToFragmentMap));
216 }
217
Greg Estren23b51812016-08-02 18:07:41 +0000218 // Fragments to unconditionally include:
219 addFragmentIfNew(builder,
220 ruleClassProvider.getUniversalFragment().asSubclass(BuildConfiguration.Fragment.class));
Marian Loburfdd788e2015-03-25 09:36:28 +0000221 }
Marian Loburfdd788e2015-03-25 09:36:28 +0000222
Mark Schallerb25759c2015-07-29 17:09:18 +0000223 return builder.build(errorLoadingTarget);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100224 }
225
Greg Estren23b51812016-08-02 18:07:41 +0000226 private void addFragmentIfNew(TransitiveTargetValueBuilder builder,
227 Class<? extends Fragment> fragment) {
228 // This only checks that the deps don't already use this fragment, not the parent rule itself.
229 // So duplicates are still possible. We can further optimize if needed.
230 if (!builder.getConfigFragmentsFromDeps().contains(fragment)) {
231 builder.getTransitiveConfigFragments().add(fragment);
232 }
233 }
234
235 private void addFragmentsIfNew(TransitiveTargetValueBuilder builder, Iterable<?> fragments) {
236 // We take Iterable<?> instead of Iterable<Class<?>> or Iterable<Class<? extends Fragment>>
237 // because both of the latter are passed as actual parameters and there's no way to consistently
238 // cast to one of them. In actuality, all values are Class<? extends Fragment>, but the values
239 // coming from Attribute.java don't have access to the Fragment symbol since Attribute is built
240 // in a different library.
241 for (Object fragment : fragments) {
242 addFragmentIfNew(builder, (Class<? extends Fragment>) fragment);
243 }
244 }
245
Googler119b15f2016-07-22 19:22:48 +0000246 @Override
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000247 protected Collection<Label> getAspectLabels(
248 Rule fromRule,
249 Attribute attr,
250 Label toLabel,
Eric Fellheimere27d0632015-09-25 21:35:26 +0000251 ValueOrException2<NoSuchPackageException, NoSuchTargetException> toVal,
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000252 final Environment env)
253 throws InterruptedException {
Eric Fellheimere27d0632015-09-25 21:35:26 +0000254 SkyKey packageKey = PackageValue.key(toLabel.getPackageIdentifier());
255 try {
256 PackageValue pkgValue =
257 (PackageValue) env.getValueOrThrow(packageKey, NoSuchPackageException.class);
258 if (pkgValue == null) {
259 return ImmutableList.of();
Eric Fellheimerb5c98842015-08-12 23:24:21 +0000260 }
Eric Fellheimere27d0632015-09-25 21:35:26 +0000261 Package pkg = pkgValue.getPackage();
262 if (pkg.containsErrors()) {
263 // Do nothing. This error was handled when we computed the corresponding
264 // TransitiveTargetValue.
265 return ImmutableList.of();
266 }
267 Target dependedTarget = pkgValue.getPackage().getTarget(toLabel.getName());
Dmitry Lomov940ea072016-01-21 22:34:14 +0000268 return AspectDefinition.visitAspectsIfRequired(fromRule, attr, dependedTarget,
269 DependencyFilter.ALL_DEPS).values();
Eric Fellheimere27d0632015-09-25 21:35:26 +0000270 } catch (NoSuchThingException e) {
271 // Do nothing. This error was handled when we computed the corresponding
272 // TransitiveTargetValue.
273 return ImmutableList.of();
Eric Fellheimerb5c98842015-08-12 23:24:21 +0000274 }
Eric Fellheimer85fe0612015-08-18 21:09:54 +0000275 }
276
Mark Schaller6b6d8a92015-10-23 01:00:28 +0000277 @Override
278 TargetMarkerValue getTargetMarkerValue(SkyKey targetMarkerKey, Environment env)
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000279 throws NoSuchTargetException, NoSuchPackageException, InterruptedException {
Mark Schaller6b6d8a92015-10-23 01:00:28 +0000280 return (TargetMarkerValue)
281 env.getValueOrThrow(
282 targetMarkerKey, NoSuchTargetException.class, NoSuchPackageException.class);
283 }
284
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000285 private static void maybeReportErrorAboutMissingEdge(
286 Target target, Label depLabel, NoSuchThingException e, EventHandler eventHandler)
287 throws InterruptedException {
Mark Schaller6b6d8a92015-10-23 01:00:28 +0000288 if (e instanceof NoSuchTargetException) {
289 NoSuchTargetException nste = (NoSuchTargetException) e;
290 if (depLabel.equals(nste.getLabel())) {
291 eventHandler.handle(
292 Event.error(
293 TargetUtils.getLocationMaybe(target),
294 TargetUtils.formatMissingEdge(target, depLabel, e)));
295 }
296 } else if (e instanceof NoSuchPackageException) {
297 NoSuchPackageException nspe = (NoSuchPackageException) e;
298 if (nspe.getPackageId().equals(depLabel.getPackageIdentifier())) {
299 eventHandler.handle(
300 Event.error(
301 TargetUtils.getLocationMaybe(target),
302 TargetUtils.formatMissingEdge(target, depLabel, e)));
303 }
304 }
305 }
306
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100307 /**
Mark Schallerb25759c2015-07-29 17:09:18 +0000308 * Holds values accumulated across the given target and its transitive dependencies for the
309 * purpose of constructing a {@link TransitiveTargetValue}.
310 *
311 * <p>Note that this class is mutable! The {@code successfulTransitiveLoading} property is
312 * initialized with the {@code packageLoadedSuccessfully} constructor parameter, and may be
313 * modified if a transitive dependency is found to be in error.
314 */
315 static class TransitiveTargetValueBuilder {
316 private boolean successfulTransitiveLoading;
317 private final NestedSetBuilder<PackageIdentifier> transitiveSuccessfulPkgs;
318 private final NestedSetBuilder<PackageIdentifier> transitiveUnsuccessfulPkgs;
319 private final NestedSetBuilder<Label> transitiveTargets;
320 private final NestedSetBuilder<Class<? extends Fragment>> transitiveConfigFragments;
321 private final Set<Class<? extends Fragment>> configFragmentsFromDeps;
322 private final NestedSetBuilder<Label> transitiveRootCauses;
323
324 public TransitiveTargetValueBuilder(Label label, Target target,
325 boolean packageLoadedSuccessfully) {
326 this.transitiveSuccessfulPkgs = NestedSetBuilder.stableOrder();
327 this.transitiveUnsuccessfulPkgs = NestedSetBuilder.stableOrder();
328 this.transitiveTargets = NestedSetBuilder.stableOrder();
329 this.transitiveConfigFragments = NestedSetBuilder.stableOrder();
330 // No need to store directly required fragments that are also required by deps.
331 this.configFragmentsFromDeps = new LinkedHashSet<>();
332 this.transitiveRootCauses = NestedSetBuilder.stableOrder();
333
334 this.successfulTransitiveLoading = packageLoadedSuccessfully;
335 PackageIdentifier packageId = target.getPackage().getPackageIdentifier();
336 if (packageLoadedSuccessfully) {
337 transitiveSuccessfulPkgs.add(packageId);
338 } else {
339 transitiveRootCauses.add(label);
340 transitiveUnsuccessfulPkgs.add(packageId);
341 }
342 transitiveTargets.add(target.getLabel());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100343 }
344
Mark Schallerb25759c2015-07-29 17:09:18 +0000345 public NestedSetBuilder<PackageIdentifier> getTransitiveSuccessfulPkgs() {
346 return transitiveSuccessfulPkgs;
347 }
348
349 public NestedSetBuilder<PackageIdentifier> getTransitiveUnsuccessfulPkgs() {
350 return transitiveUnsuccessfulPkgs;
351 }
352
353 public NestedSetBuilder<Label> getTransitiveTargets() {
354 return transitiveTargets;
355 }
356
357 public NestedSetBuilder<Class<? extends Fragment>> getTransitiveConfigFragments() {
358 return transitiveConfigFragments;
359 }
360
361 public Set<Class<? extends Fragment>> getConfigFragmentsFromDeps() {
362 return configFragmentsFromDeps;
363 }
364
365 public NestedSetBuilder<Label> getTransitiveRootCauses() {
366 return transitiveRootCauses;
367 }
368
369 public boolean isSuccessfulTransitiveLoading() {
370 return successfulTransitiveLoading;
371 }
372
373 public void setSuccessfulTransitiveLoading(boolean successfulTransitiveLoading) {
374 this.successfulTransitiveLoading = successfulTransitiveLoading;
375 }
376
377 public SkyValue build(@Nullable NoSuchTargetException errorLoadingTarget) {
378 NestedSet<PackageIdentifier> successfullyLoadedPkgs = transitiveSuccessfulPkgs.build();
379 NestedSet<PackageIdentifier> unsuccessfullyLoadedPkgs = transitiveUnsuccessfulPkgs.build();
380 NestedSet<Label> loadedTargets = transitiveTargets.build();
381 NestedSet<Class<? extends Fragment>> configFragments = transitiveConfigFragments.build();
382 return successfulTransitiveLoading
383 ? TransitiveTargetValue.successfulTransitiveLoading(successfullyLoadedPkgs,
384 unsuccessfullyLoadedPkgs, loadedTargets, configFragments)
385 : TransitiveTargetValue.unsuccessfulTransitiveLoading(successfullyLoadedPkgs,
386 unsuccessfullyLoadedPkgs, loadedTargets, transitiveRootCauses.build(),
387 errorLoadingTarget, configFragments);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100388 }
389 }
390}