Allow accessing the configuration of a dependency during resolution.
This is necessary because with trimming, the configuration that a configured
target was analyzed with may not be the configuration that it was requested
with.
Progress on #6524.
PiperOrigin-RevId: 244209432
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
index fd9e90e..854ffe3 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
@@ -736,12 +736,32 @@
}
}
try {
+ BuildConfiguration depConfiguration = dep.getConfiguration();
+ BuildConfigurationValue.Key depKey =
+ depValue.getConfiguredTarget().getConfigurationKey();
+ // Retroactive trimming may change the configuration associated with the dependency.
+ // If it does, we need to get that instance.
+ // TODO(mstaib): doing these individually instead of doing them all at once may end up
+ // being wasteful use of Skyframe. Although these configurations are guaranteed to be
+ // in the Skyframe cache (because the dependency would have had to retrieve them to be
+ // created in the first place), looking them up repeatedly may be slower than just
+ // keeping a local cache and assigning the same configuration to all the CTs which
+ // need it. Profile this and see if there's a better way.
+ if (depKey != null && !depKey.equals(BuildConfigurationValue.key(depConfiguration))) {
+ if (!depConfiguration.trimConfigurationsRetroactively()) {
+ throw new AssertionError(
+ "Loading configurations mid-dependency resolution should ONLY happen when "
+ + "retroactive trimming is enabled.");
+ }
+ depConfiguration =
+ ((BuildConfigurationValue) env.getValue(depKey)).getConfiguration();
+ }
result.put(
key,
new ConfiguredTargetAndData(
depValue.getConfiguredTarget(),
pkgValue.getPackage().getTarget(depLabel.getName()),
- dep.getConfiguration()));
+ depConfiguration));
} catch (NoSuchTargetException e) {
throw new IllegalStateException("Target already verified for " + dep, e);
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
index 0298f62..eadebad 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
@@ -1739,15 +1739,34 @@
try {
ConfiguredTarget mergedTarget =
MergedConfiguredTarget.of(configuredTarget, configuredAspects);
+ BuildConfigurationValue.Key configKey = mergedTarget.getConfigurationKey();
+ BuildConfiguration resolvedConfig = depConfig;
+ if (configKey == null) {
+ // Unfortunately, it's possible to get a configured target with a null configuration
+ // when depConfig is non-null, so we need to explicitly override it in that case.
+ resolvedConfig = null;
+ } else if (!configKey.equals(BuildConfigurationValue.key(depConfig))) {
+ // Retroactive trimming may change the configuration associated with the dependency.
+ // If it does, we need to get that instance.
+ // TODO(mstaib): doing these individually instead of doing them all at once may end
+ // up being wasteful use of Skyframe. Although these configurations are guaranteed
+ // to be in the Skyframe cache (because the dependency would have had to retrieve
+ // them to be created in the first place), looking them up repeatedly may be slower
+ // than just keeping a local cache and assigning the same configuration to all the
+ // CTs which need it. Profile this and see if there's a better way.
+ if (!depConfig.trimConfigurationsRetroactively()) {
+ throw new AssertionError(
+ "Loading configurations mid-dependency resolution should ONLY happen when "
+ + "retroactive trimming is enabled.");
+ }
+ resolvedConfig = getConfiguration(eventHandler, mergedTarget.getConfigurationKey());
+ }
cts.put(
key,
new ConfiguredTargetAndData(
mergedTarget,
packageValue.getPackage().getTarget(configuredTarget.getLabel().getName()),
- // This is terrible, but our tests' use of configurations is terrible. It's only
- // by accident that getting a null-configuration ConfiguredTarget works even if
- // depConfig is not null.
- mergedTarget.getConfigurationKey() == null ? null : depConfig));
+ resolvedConfig));
} catch (DuplicateException | NoSuchTargetException e) {
throw new IllegalStateException(