From a413c8236f6c7add235e9555966c537a72a79f2d Mon Sep 17 00:00:00 2001 From: Googler Date: Thu, 6 Jul 2023 10:20:32 -0700 Subject: [PATCH] Adjust --top_level_targets_for_symlinks. Old semantics: New semantics: Fixes https://github.com/bazelbuild/bazel/issues/17081. PiperOrigin-RevId: 546025529 Change-Id: I095564bb9233eba4b008df7f9e6aedae3e973b23 --- .../build/lib/buildtool/ExecutionTool.java | 41 ++++++++++++++----- .../buildtool/OutputDirectoryLinksUtils.java | 4 +- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java b/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java index 3a871c2901af85..1e565e44633a53 100644 --- a/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java +++ b/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java @@ -766,16 +766,35 @@ private ImmutableList createConvenienceSymlinks( Reporter reporter = env.getReporter(); // Gather configurations to consider. - Set targetConfigurations = - buildRequestOptions.useTopLevelTargetsForSymlinks() && !targetsToBuild.isEmpty() - ? targetsToBuild.stream() - .map(ConfiguredTarget::getActual) - .map(ConfiguredTarget::getConfigurationKey) - .filter(Objects::nonNull) - .distinct() - .map((key) -> executor.getConfiguration(reporter, key)) - .collect(toImmutableSet()) - : ImmutableSet.of(configuration); + ImmutableSet targetConfigs; + if (buildRequestOptions.useTopLevelTargetsForSymlinks() && !targetsToBuild.isEmpty()) { + // Collect the configuration of each top-level requested target. These may be different than + // the build's top-level configuration because of self-transitions. + ImmutableSet requestedTargetConfigs = + targetsToBuild.stream() + .map(ConfiguredTarget::getActual) + .map(ConfiguredTarget::getConfigurationKey) + .filter(Objects::nonNull) + .distinct() + .map((key) -> executor.getConfiguration(reporter, key)) + .collect(toImmutableSet()); + if (requestedTargetConfigs.size() == 1) { + // All top-level targets have the same configuration, so use that one. + targetConfigs = requestedTargetConfigs; + } else if (requestedTargetConfigs.contains(configuration)) { + // Mixed configs but at least one of them includes the top-level config. Set symlinks to the + // top-level config so at least non-transitioned targets resolve. See + // https://github.com/bazelbuild/bazel/issues/17081. + targetConfigs = ImmutableSet.of(configuration); + } else { + // Mixed configs, none of which include the top-level config. Delete the symlinks because + // they won't contain any relevant data. This is handled in the + // createOutputDirectorySymlinks call below. + targetConfigs = requestedTargetConfigs; + } + } else { + targetConfigs = ImmutableSet.of(configuration); + } String productName = runtime.getProductName(); try (SilentCloseable c = @@ -787,7 +806,7 @@ private ImmutableList createConvenienceSymlinks( env.getWorkspace(), env.getDirectories(), getReporter(), - targetConfigurations, + targetConfigs, options -> getConfiguration(executor, reporter, options), productName); } diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/OutputDirectoryLinksUtils.java b/src/main/java/com/google/devtools/build/lib/buildtool/OutputDirectoryLinksUtils.java index 47ba5a408ff0f3..23cf130bd66a75 100644 --- a/src/main/java/com/google/devtools/build/lib/buildtool/OutputDirectoryLinksUtils.java +++ b/src/main/java/com/google/devtools/build/lib/buildtool/OutputDirectoryLinksUtils.java @@ -169,7 +169,9 @@ static ImmutableList createOutputDirectoryLinks( eventHandler.handle( Event.warn( String.format( - "cleared convenience symlink(s) %s because their destinations would be ambiguous", + "cleared convenience symlink(s) %s because they wouldn't contain 0 " + + "requested targets' outputs. Those targets self-transition to multiple " + + "distinct configurations", Joiner.on(", ").join(ambiguousLinks)))); } return convenienceSymlinksBuilder.build();