blob: c71ff9c74274a07babdf61ba2825d74c1ab7cd11 [file] [log] [blame]
John Cater77a49622019-04-19 07:23:33 -07001// Copyright 2019 The Bazel Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.lib.skyframe;
15
16import static com.google.common.collect.ImmutableList.toImmutableList;
John Cater004099d2019-05-17 11:21:59 -070017import static com.google.common.collect.ImmutableSet.toImmutableSet;
John Cater77a49622019-04-19 07:23:33 -070018import static java.util.stream.Collectors.joining;
19
20import com.google.auto.value.AutoValue;
John Cater72f73142019-04-19 10:08:22 -070021import com.google.common.base.Preconditions;
John Cater77a49622019-04-19 07:23:33 -070022import com.google.common.collect.HashBasedTable;
23import com.google.common.collect.ImmutableBiMap;
24import com.google.common.collect.ImmutableList;
John Cater004099d2019-05-17 11:21:59 -070025import com.google.common.collect.ImmutableMap;
John Cater77a49622019-04-19 07:23:33 -070026import com.google.common.collect.ImmutableSet;
hlopko23f052f2019-11-15 06:55:09 -080027import com.google.common.collect.Iterables;
John Cater77a49622019-04-19 07:23:33 -070028import com.google.common.collect.Table;
29import com.google.devtools.build.lib.analysis.PlatformConfiguration;
30import com.google.devtools.build.lib.analysis.PlatformOptions;
31import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
32import com.google.devtools.build.lib.analysis.platform.ConstraintValueInfo;
33import com.google.devtools.build.lib.analysis.platform.PlatformInfo;
34import com.google.devtools.build.lib.analysis.platform.ToolchainTypeInfo;
35import com.google.devtools.build.lib.cmdline.Label;
36import com.google.devtools.build.lib.events.Event;
37import com.google.devtools.build.lib.skyframe.ConstraintValueLookupUtil.InvalidConstraintValueException;
38import com.google.devtools.build.lib.skyframe.PlatformLookupUtil.InvalidPlatformException;
39import com.google.devtools.build.lib.skyframe.RegisteredToolchainsFunction.InvalidToolchainLabelException;
40import com.google.devtools.build.lib.skyframe.SingleToolchainResolutionFunction.NoToolchainFoundException;
John Catera4baa3c2019-11-26 08:27:41 -080041import com.google.devtools.build.lib.skyframe.SingleToolchainResolutionValue.SingleToolchainResolutionKey;
John Cater004099d2019-05-17 11:21:59 -070042import com.google.devtools.build.lib.skyframe.ToolchainTypeLookupUtil.InvalidToolchainTypeException;
John Cater77a49622019-04-19 07:23:33 -070043import com.google.devtools.build.skyframe.SkyFunction;
44import com.google.devtools.build.skyframe.SkyFunctionException;
45import com.google.devtools.build.skyframe.SkyKey;
46import com.google.devtools.build.skyframe.ValueOrException2;
47import java.util.ArrayList;
48import java.util.List;
49import java.util.Map;
50import java.util.Optional;
51import java.util.Set;
52import java.util.stream.Collectors;
53import javax.annotation.Nullable;
54
55/**
56 * Sky function which performs toolchain resolution for multiple toolchain types, including
57 * selecting the execution platform.
58 */
59public class ToolchainResolutionFunction implements SkyFunction {
60
61 @Nullable
62 @Override
63 public UnloadedToolchainContext compute(SkyKey skyKey, Environment env)
64 throws ToolchainResolutionFunctionException, InterruptedException {
John Cater60837112020-05-12 06:31:02 -070065 ToolchainContextKey key = (ToolchainContextKey) skyKey.argument();
John Cater77a49622019-04-19 07:23:33 -070066
67 try {
John Caterbd7abd62020-05-12 10:07:05 -070068 UnloadedToolchainContextImpl.Builder builder =
69 UnloadedToolchainContextImpl.builder().setKey(key);
John Cater77a49622019-04-19 07:23:33 -070070
71 // Determine the configuration being used.
72 BuildConfigurationValue value =
73 (BuildConfigurationValue) env.getValue(key.configurationKey());
74 if (value == null) {
75 throw new ValueMissingException();
76 }
77 BuildConfiguration configuration = value.getConfiguration();
78 PlatformConfiguration platformConfiguration =
John Cater72f73142019-04-19 10:08:22 -070079 Preconditions.checkNotNull(configuration.getFragment(PlatformConfiguration.class));
John Cater77a49622019-04-19 07:23:33 -070080
81 // Check if debug output should be generated.
82 boolean debug =
83 configuration.getOptions().get(PlatformOptions.class).toolchainResolutionDebug;
84
John Cater004099d2019-05-17 11:21:59 -070085 // Load the configured target for the toolchain types to ensure that they are valid and
86 // resolve aliases.
87 ImmutableMap<Label, ToolchainTypeInfo> resolvedToolchainTypes =
88 loadToolchainTypes(
89 env,
90 configuration,
91 key.requiredToolchainTypeLabels(),
92 key.shouldSanityCheckConfiguration());
93 builder.setRequestedLabelToToolchainType(resolvedToolchainTypes);
94 ImmutableSet<Label> resolvedToolchainTypeLabels =
95 resolvedToolchainTypes.values().stream()
96 .map(ToolchainTypeInfo::typeLabel)
97 .collect(toImmutableSet());
98
John Cater77a49622019-04-19 07:23:33 -070099 // Create keys for all platforms that will be used, and validate them early.
100 PlatformKeys platformKeys =
101 loadPlatformKeys(
102 env,
103 debug,
104 key.configurationKey(),
105 configuration,
106 platformConfiguration,
107 key.execConstraintLabels(),
108 key.shouldSanityCheckConfiguration());
109 if (env.valuesMissing()) {
110 return null;
111 }
112
113 // Determine the actual toolchain implementations to use.
114 determineToolchainImplementations(
115 env,
John Cater77a49622019-04-19 07:23:33 -0700116 key.configurationKey(),
John Cater004099d2019-05-17 11:21:59 -0700117 resolvedToolchainTypeLabels,
John Cater72f73142019-04-19 10:08:22 -0700118 builder,
John Cater77a49622019-04-19 07:23:33 -0700119 platformKeys,
120 key.shouldSanityCheckConfiguration());
121
John Cater72f73142019-04-19 10:08:22 -0700122 UnloadedToolchainContext unloadedToolchainContext = builder.build();
123 if (debug) {
124 String selectedToolchains =
125 unloadedToolchainContext.toolchainTypeToResolved().entrySet().stream()
126 .map(
127 e ->
128 String.format(
129 "type %s -> toolchain %s", e.getKey().typeLabel(), e.getValue()))
130 .collect(joining(", "));
131 env.getListener()
132 .handle(
133 Event.info(
134 String.format(
135 "ToolchainResolution: Selected execution platform %s, %s",
136 unloadedToolchainContext.executionPlatform().label(), selectedToolchains)));
137 }
138 return unloadedToolchainContext;
John Cater77a49622019-04-19 07:23:33 -0700139 } catch (ToolchainException e) {
140 throw new ToolchainResolutionFunctionException(e);
141 } catch (ValueMissingException e) {
142 return null;
143 }
144 }
145
John Cater004099d2019-05-17 11:21:59 -0700146 /** Returns a map from the requested toolchain type to the {@link ToolchainTypeInfo} provider. */
147 private ImmutableMap<Label, ToolchainTypeInfo> loadToolchainTypes(
148 Environment environment,
149 BuildConfiguration configuration,
150 ImmutableSet<Label> requestedToolchainTypeLabels,
151 boolean shouldSanityCheckConfiguration)
152 throws InvalidToolchainTypeException, InterruptedException, ValueMissingException {
153 ImmutableSet<ConfiguredTargetKey> toolchainTypeKeys =
154 requestedToolchainTypeLabels.stream()
jcater83221e32020-05-28 11:37:39 -0700155 .map(
156 label ->
157 ConfiguredTargetKey.builder()
158 .setLabel(label)
159 .setConfiguration(configuration)
160 .build())
John Cater004099d2019-05-17 11:21:59 -0700161 .collect(toImmutableSet());
162
163 ImmutableMap<Label, ToolchainTypeInfo> resolvedToolchainTypes =
164 ToolchainTypeLookupUtil.resolveToolchainTypes(
165 environment, toolchainTypeKeys, shouldSanityCheckConfiguration);
166 if (environment.valuesMissing()) {
167 throw new ValueMissingException();
168 }
169 return resolvedToolchainTypes;
170 }
171
John Cater77a49622019-04-19 07:23:33 -0700172 @AutoValue
173 abstract static class PlatformKeys {
174 abstract ConfiguredTargetKey hostPlatformKey();
175
176 abstract ConfiguredTargetKey targetPlatformKey();
177
178 abstract ImmutableList<ConfiguredTargetKey> executionPlatformKeys();
179
180 static PlatformKeys create(
181 ConfiguredTargetKey hostPlatformKey,
182 ConfiguredTargetKey targetPlatformKey,
183 List<ConfiguredTargetKey> executionPlatformKeys) {
184 return new AutoValue_ToolchainResolutionFunction_PlatformKeys(
185 hostPlatformKey, targetPlatformKey, ImmutableList.copyOf(executionPlatformKeys));
186 }
187 }
188
189 private PlatformKeys loadPlatformKeys(
190 SkyFunction.Environment environment,
191 boolean debug,
192 BuildConfigurationValue.Key configurationKey,
193 BuildConfiguration configuration,
194 PlatformConfiguration platformConfiguration,
195 ImmutableSet<Label> execConstraintLabels,
196 boolean shouldSanityCheckConfiguration)
197 throws InterruptedException, ValueMissingException, InvalidConstraintValueException,
198 InvalidPlatformException {
199 // Determine the target and host platform keys.
200 Label hostPlatformLabel = platformConfiguration.getHostPlatform();
201 Label targetPlatformLabel = platformConfiguration.getTargetPlatform();
202
jcater83221e32020-05-28 11:37:39 -0700203 ConfiguredTargetKey hostPlatformKey =
204 ConfiguredTargetKey.builder()
205 .setLabel(hostPlatformLabel)
206 .setConfiguration(configuration)
207 .build();
John Cater77a49622019-04-19 07:23:33 -0700208 ConfiguredTargetKey targetPlatformKey =
jcater83221e32020-05-28 11:37:39 -0700209 ConfiguredTargetKey.builder()
210 .setLabel(targetPlatformLabel)
211 .setConfiguration(configuration)
212 .build();
John Cater77a49622019-04-19 07:23:33 -0700213
214 // Load the host and target platforms early, to check for errors.
215 PlatformLookupUtil.getPlatformInfo(
216 ImmutableList.of(hostPlatformKey, targetPlatformKey),
217 environment,
218 shouldSanityCheckConfiguration);
219 if (environment.valuesMissing()) {
220 throw new ValueMissingException();
221 }
222
223 ImmutableList<ConfiguredTargetKey> executionPlatformKeys =
224 loadExecutionPlatformKeys(
225 environment,
226 debug,
227 configurationKey,
228 configuration,
229 hostPlatformKey,
230 execConstraintLabels,
231 shouldSanityCheckConfiguration);
232
233 return PlatformKeys.create(hostPlatformKey, targetPlatformKey, executionPlatformKeys);
234 }
235
236 private ImmutableList<ConfiguredTargetKey> loadExecutionPlatformKeys(
237 SkyFunction.Environment environment,
238 boolean debug,
239 BuildConfigurationValue.Key configurationKey,
240 BuildConfiguration configuration,
241 ConfiguredTargetKey defaultPlatformKey,
242 ImmutableSet<Label> execConstraintLabels,
243 boolean shouldSanityCheckConfiguration)
244 throws InterruptedException, ValueMissingException, InvalidConstraintValueException,
245 InvalidPlatformException {
246 RegisteredExecutionPlatformsValue registeredExecutionPlatforms =
247 (RegisteredExecutionPlatformsValue)
248 environment.getValueOrThrow(
249 RegisteredExecutionPlatformsValue.key(configurationKey),
250 InvalidPlatformException.class);
251 if (registeredExecutionPlatforms == null) {
252 throw new ValueMissingException();
253 }
254
255 ImmutableList<ConfiguredTargetKey> availableExecutionPlatformKeys =
256 new ImmutableList.Builder<ConfiguredTargetKey>()
257 .addAll(registeredExecutionPlatforms.registeredExecutionPlatformKeys())
258 .add(defaultPlatformKey)
259 .build();
260
261 // Filter out execution platforms that don't satisfy the extra constraints.
262 ImmutableList<ConfiguredTargetKey> execConstraintKeys =
263 execConstraintLabels.stream()
jcater83221e32020-05-28 11:37:39 -0700264 .map(
265 label ->
266 ConfiguredTargetKey.builder()
267 .setLabel(label)
268 .setConfiguration(configuration)
269 .build())
John Cater77a49622019-04-19 07:23:33 -0700270 .collect(toImmutableList());
271
272 return filterAvailablePlatforms(
273 environment,
274 debug,
275 availableExecutionPlatformKeys,
276 execConstraintKeys,
277 shouldSanityCheckConfiguration);
278 }
279
280 /** Returns only the platform keys that match the given constraints. */
281 private ImmutableList<ConfiguredTargetKey> filterAvailablePlatforms(
282 SkyFunction.Environment environment,
283 boolean debug,
284 ImmutableList<ConfiguredTargetKey> platformKeys,
285 ImmutableList<ConfiguredTargetKey> constraintKeys,
286 boolean shouldSanityCheckConfiguration)
287 throws InterruptedException, ValueMissingException, InvalidConstraintValueException,
288 InvalidPlatformException {
289
290 // Short circuit if not needed.
291 if (constraintKeys.isEmpty()) {
292 return platformKeys;
293 }
294
295 // At this point the host and target platforms have been loaded, but not necessarily the chosen
296 // execution platform (it might be the same as the host platform, and might not).
297 //
298 // It's not worth trying to optimize away this call, since in the optimizable case (the exec
299 // platform is the host platform), Skyframe will return the correct results immediately without
300 // need of a restart.
301 Map<ConfiguredTargetKey, PlatformInfo> platformInfoMap =
302 PlatformLookupUtil.getPlatformInfo(
303 platformKeys, environment, shouldSanityCheckConfiguration);
304 if (platformInfoMap == null) {
305 throw new ValueMissingException();
306 }
307 List<ConstraintValueInfo> constraints =
308 ConstraintValueLookupUtil.getConstraintValueInfo(constraintKeys, environment);
309 if (constraints == null) {
310 throw new ValueMissingException();
311 }
312
313 return platformKeys.stream()
314 .filter(key -> filterPlatform(environment, debug, platformInfoMap.get(key), constraints))
315 .collect(toImmutableList());
316 }
317
318 /** Returns {@code true} if the given platform has all of the constraints. */
319 private boolean filterPlatform(
320 SkyFunction.Environment environment,
321 boolean debug,
322 PlatformInfo platformInfo,
323 List<ConstraintValueInfo> constraints) {
324 ImmutableList<ConstraintValueInfo> missingConstraints =
325 platformInfo.constraints().findMissing(constraints);
326 if (debug) {
327 for (ConstraintValueInfo constraint : missingConstraints) {
328 // The value for this setting is not present in the platform, or doesn't match the expected
329 // value.
330 environment
331 .getListener()
332 .handle(
333 Event.info(
334 String.format(
John Catere39e5c92019-04-23 10:28:02 -0700335 "ToolchainResolution: Removed execution platform %s from"
John Cater77a49622019-04-19 07:23:33 -0700336 + " available execution platforms, it is missing constraint %s",
337 platformInfo.label(), constraint.label())));
338 }
339 }
340
341 return missingConstraints.isEmpty();
342 }
343
344 private void determineToolchainImplementations(
John Catere39e5c92019-04-23 10:28:02 -0700345 Environment environment,
John Cater77a49622019-04-19 07:23:33 -0700346 BuildConfigurationValue.Key configurationKey,
347 ImmutableSet<Label> requiredToolchainTypeLabels,
jcater5fa42ae2020-04-14 11:56:57 -0700348 UnloadedToolchainContextImpl.Builder builder,
John Cater77a49622019-04-19 07:23:33 -0700349 PlatformKeys platformKeys,
350 boolean shouldSanityCheckConfiguration)
351 throws InterruptedException, ValueMissingException, InvalidPlatformException,
352 NoMatchingPlatformException, UnresolvedToolchainsException,
353 InvalidToolchainLabelException {
354
355 // Find the toolchains for the required toolchain types.
John Catera4baa3c2019-11-26 08:27:41 -0800356 List<SingleToolchainResolutionKey> registeredToolchainKeys = new ArrayList<>();
John Cater77a49622019-04-19 07:23:33 -0700357 for (Label toolchainTypeLabel : requiredToolchainTypeLabels) {
358 registeredToolchainKeys.add(
359 SingleToolchainResolutionValue.key(
360 configurationKey,
361 toolchainTypeLabel,
362 platformKeys.targetPlatformKey(),
363 platformKeys.executionPlatformKeys()));
364 }
365
366 Map<SkyKey, ValueOrException2<NoToolchainFoundException, InvalidToolchainLabelException>>
367 results =
368 environment.getValuesOrThrow(
369 registeredToolchainKeys,
370 NoToolchainFoundException.class,
371 InvalidToolchainLabelException.class);
372 boolean valuesMissing = false;
373
374 // Determine the potential set of toolchains.
375 Table<ConfiguredTargetKey, ToolchainTypeInfo, Label> resolvedToolchains =
376 HashBasedTable.create();
377 ImmutableSet.Builder<ToolchainTypeInfo> requiredToolchainTypesBuilder = ImmutableSet.builder();
378 List<Label> missingToolchains = new ArrayList<>();
379 for (Map.Entry<
380 SkyKey, ValueOrException2<NoToolchainFoundException, InvalidToolchainLabelException>>
381 entry : results.entrySet()) {
382 try {
383 ValueOrException2<NoToolchainFoundException, InvalidToolchainLabelException>
384 valueOrException = entry.getValue();
385 SingleToolchainResolutionValue singleToolchainResolutionValue =
386 (SingleToolchainResolutionValue) valueOrException.get();
387 if (singleToolchainResolutionValue == null) {
388 valuesMissing = true;
389 continue;
390 }
391
392 ToolchainTypeInfo requiredToolchainType = singleToolchainResolutionValue.toolchainType();
393 requiredToolchainTypesBuilder.add(requiredToolchainType);
394 resolvedToolchains.putAll(
395 findPlatformsAndLabels(requiredToolchainType, singleToolchainResolutionValue));
396 } catch (NoToolchainFoundException e) {
397 // Save the missing type and continue looping to check for more.
398 missingToolchains.add(e.missingToolchainTypeLabel());
399 }
400 }
401
402 if (!missingToolchains.isEmpty()) {
403 throw new UnresolvedToolchainsException(missingToolchains);
404 }
405
406 if (valuesMissing) {
407 throw new ValueMissingException();
408 }
409
410 ImmutableSet<ToolchainTypeInfo> requiredToolchainTypes = requiredToolchainTypesBuilder.build();
411
412 // Find and return the first execution platform which has all required toolchains.
413 Optional<ConfiguredTargetKey> selectedExecutionPlatformKey;
414 if (!requiredToolchainTypeLabels.isEmpty()) {
415 selectedExecutionPlatformKey =
416 findExecutionPlatformForToolchains(
John Cater77a49622019-04-19 07:23:33 -0700417 requiredToolchainTypes,
418 platformKeys.executionPlatformKeys(),
419 resolvedToolchains);
John Cater77a49622019-04-19 07:23:33 -0700420 } else if (!platformKeys.executionPlatformKeys().isEmpty()) {
421 // Just use the first execution platform.
422 selectedExecutionPlatformKey = Optional.of(platformKeys.executionPlatformKeys().get(0));
423 } else {
424 selectedExecutionPlatformKey = Optional.empty();
425 }
426
427 if (!selectedExecutionPlatformKey.isPresent()) {
428 throw new NoMatchingPlatformException(
429 requiredToolchainTypeLabels,
430 platformKeys.executionPlatformKeys(),
431 platformKeys.targetPlatformKey());
432 }
433
434 Map<ConfiguredTargetKey, PlatformInfo> platforms =
435 PlatformLookupUtil.getPlatformInfo(
436 ImmutableList.of(selectedExecutionPlatformKey.get(), platformKeys.targetPlatformKey()),
437 environment,
438 shouldSanityCheckConfiguration);
439 if (platforms == null) {
440 throw new ValueMissingException();
441 }
442
John Cater72f73142019-04-19 10:08:22 -0700443 builder.setRequiredToolchainTypes(requiredToolchainTypes);
444 builder.setExecutionPlatform(platforms.get(selectedExecutionPlatformKey.get()));
445 builder.setTargetPlatform(platforms.get(platformKeys.targetPlatformKey()));
John Cater77a49622019-04-19 07:23:33 -0700446
447 Map<ToolchainTypeInfo, Label> toolchains =
448 resolvedToolchains.row(selectedExecutionPlatformKey.get());
John Cater72f73142019-04-19 10:08:22 -0700449 builder.setToolchainTypeToResolved(ImmutableBiMap.copyOf(toolchains));
John Cater77a49622019-04-19 07:23:33 -0700450 }
451
452 /**
John Catere39e5c92019-04-23 10:28:02 -0700453 * Adds all of toolchain labels from {@code toolchainResolutionValue} to {@code
John Cater77a49622019-04-19 07:23:33 -0700454 * resolvedToolchains}.
455 */
456 private static Table<ConfiguredTargetKey, ToolchainTypeInfo, Label> findPlatformsAndLabels(
457 ToolchainTypeInfo requiredToolchainType,
458 SingleToolchainResolutionValue singleToolchainResolutionValue) {
459
460 Table<ConfiguredTargetKey, ToolchainTypeInfo, Label> resolvedToolchains =
461 HashBasedTable.create();
462 for (Map.Entry<ConfiguredTargetKey, Label> entry :
463 singleToolchainResolutionValue.availableToolchainLabels().entrySet()) {
464 resolvedToolchains.put(entry.getKey(), requiredToolchainType, entry.getValue());
465 }
466 return resolvedToolchains;
467 }
468
469 /**
470 * Finds the first platform from {@code availableExecutionPlatformKeys} that is present in {@code
471 * resolvedToolchains} and has all required toolchain types.
472 */
473 private static Optional<ConfiguredTargetKey> findExecutionPlatformForToolchains(
John Cater77a49622019-04-19 07:23:33 -0700474 ImmutableSet<ToolchainTypeInfo> requiredToolchainTypes,
475 ImmutableList<ConfiguredTargetKey> availableExecutionPlatformKeys,
476 Table<ConfiguredTargetKey, ToolchainTypeInfo, Label> resolvedToolchains) {
477 for (ConfiguredTargetKey executionPlatformKey : availableExecutionPlatformKeys) {
478 if (!resolvedToolchains.containsRow(executionPlatformKey)) {
479 continue;
480 }
481
482 Map<ToolchainTypeInfo, Label> toolchains = resolvedToolchains.row(executionPlatformKey);
483 if (!toolchains.keySet().containsAll(requiredToolchainTypes)) {
484 // Not all toolchains are present, ignore this execution platform.
485 continue;
486 }
487
John Cater77a49622019-04-19 07:23:33 -0700488 return Optional.of(executionPlatformKey);
489 }
490
491 return Optional.empty();
492 }
493
494 @Nullable
495 @Override
496 public String extractTag(SkyKey skyKey) {
497 return null;
498 }
499
500 private static final class ValueMissingException extends Exception {
501 private ValueMissingException() {
502 super();
503 }
504 }
505
506 /** Exception used when no execution platform can be found. */
507 static final class NoMatchingPlatformException extends ToolchainException {
508 NoMatchingPlatformException(
509 Set<Label> requiredToolchainTypeLabels,
510 ImmutableList<ConfiguredTargetKey> availableExecutionPlatformKeys,
511 ConfiguredTargetKey targetPlatformKey) {
512 super(
513 formatError(
514 requiredToolchainTypeLabels, availableExecutionPlatformKeys, targetPlatformKey));
515 }
516
517 private static String formatError(
518 Set<Label> requiredToolchainTypeLabels,
519 ImmutableList<ConfiguredTargetKey> availableExecutionPlatformKeys,
520 ConfiguredTargetKey targetPlatformKey) {
521 if (requiredToolchainTypeLabels.isEmpty()) {
522 return String.format(
523 "Unable to find an execution platform for target platform %s"
524 + " from available execution platforms [%s]",
525 targetPlatformKey.getLabel(),
526 availableExecutionPlatformKeys.stream()
527 .map(key -> key.getLabel().toString())
528 .collect(Collectors.joining(", ")));
529 }
530 return String.format(
531 "Unable to find an execution platform for toolchains [%s] and target platform %s"
532 + " from available execution platforms [%s]",
533 requiredToolchainTypeLabels.stream().map(Label::toString).collect(joining(", ")),
534 targetPlatformKey.getLabel(),
535 availableExecutionPlatformKeys.stream()
536 .map(key -> key.getLabel().toString())
537 .collect(Collectors.joining(", ")));
538 }
539 }
540
541 /** Exception used when a toolchain type is required but no matching toolchain is found. */
542 static final class UnresolvedToolchainsException extends ToolchainException {
543 UnresolvedToolchainsException(List<Label> missingToolchainTypes) {
hlopko23f052f2019-11-15 06:55:09 -0800544 super(getMessage(missingToolchainTypes));
545 }
546
547 private static String getMessage(List<Label> missingToolchainTypes) {
548 if (missingToolchainTypes.size() == 1
549 && Iterables.getOnlyElement(missingToolchainTypes)
550 .toString()
551 .equals("@bazel_tools//tools/cpp:toolchain_type")) {
552 return "No matching toolchains found for types @bazel_tools//tools/cpp:toolchain_type. "
553 + "Maybe --incompatible_use_cc_configure_from_rules_cc has been flipped and there "
554 + "is no default C++ toolchain added in the WORKSPACE file? See "
555 + "https://github.com/bazelbuild/bazel/issues/10134 for details and migration "
556 + "instructions.";
557 }
558
559 return String.format(
560 "no matching toolchains found for types %s",
561 missingToolchainTypes.stream().map(Label::toString).collect(joining(", ")));
John Cater77a49622019-04-19 07:23:33 -0700562 }
563 }
564
jcater5fa42ae2020-04-14 11:56:57 -0700565 /** Used to indicate errors during the computation of an {@link UnloadedToolchainContextImpl}. */
John Cater77a49622019-04-19 07:23:33 -0700566 private static final class ToolchainResolutionFunctionException extends SkyFunctionException {
567 public ToolchainResolutionFunctionException(ToolchainException e) {
568 super(e, Transience.PERSISTENT);
569 }
570 }
571}