Use `SkyKeyComputeState` to address a major inefficiency in `ConfiguredTargetFunction` and `AspectFunction`. In my benchmarks of a diverse set of targets, this reduces the analysis phase wall time by between 3% and 6.5%. See the description of https://github.com/bazelbuild/bazel/commit/ed279ab4fa2d4356be00b54266f56edcc5aeae78 for some background on the inefficiency. And see the description of https://github.com/bazelbuild/bazel/commit/343ba438a93f8c56a7b524ac7a54666c57a969d9 for how this CL here is able to be a strict performance win even when Blaze is memory constrained. PiperOrigin-RevId: 419918993
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationResolver.java b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationResolver.java index ef8c2f1..e10d746 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationResolver.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationResolver.java
@@ -208,20 +208,23 @@ * Keep this in mind when making modifications and performance-test any changes you make. * * @param dependencyKeys the transition requests for each dep and each dependency kind + * @param eventHandler the handler for events * @return a mapping from each dependency kind in the source target to the {@link * BuildConfigurationValue}s and {@link Label}s for the deps under that dependency kind . * Returns null if not all Skyframe dependencies are available. */ @Nullable public OrderedSetMultimap<DependencyKind, Dependency> resolveConfigurations( - OrderedSetMultimap<DependencyKind, DependencyKey> dependencyKeys) + OrderedSetMultimap<DependencyKind, DependencyKey> dependencyKeys, + ExtendedEventHandler eventHandler) throws ConfiguredValueCreationException, InterruptedException { OrderedSetMultimap<DependencyKind, Dependency> resolvedDeps = OrderedSetMultimap.create(); boolean needConfigsFromSkyframe = false; for (Map.Entry<DependencyKind, DependencyKey> entry : dependencyKeys.entries()) { DependencyKind dependencyKind = entry.getKey(); DependencyKey dependencyKey = entry.getValue(); - ImmutableList<Dependency> depConfig = resolveConfiguration(dependencyKind, dependencyKey); + ImmutableList<Dependency> depConfig = + resolveConfiguration(dependencyKind, dependencyKey, eventHandler); if (depConfig == null) { // Instead of returning immediately, give the loop a chance to queue up every missing // dependency, then return all at once. That prevents re-executing this code an unnecessary @@ -243,7 +246,7 @@ */ @Nullable public ImmutableList<Dependency> resolveConfiguration( - DependencyKind dependencyKind, DependencyKey dependencyKey) + DependencyKind dependencyKind, DependencyKey dependencyKey, ExtendedEventHandler eventHandler) throws ConfiguredValueCreationException, InterruptedException { Dependency.Builder dependencyBuilder = dependencyKey.getDependencyBuilder(); @@ -251,7 +254,8 @@ ConfigurationTransition transition = dependencyKey.getTransition(); if (transition == NullTransition.INSTANCE) { - Dependency resolvedDep = resolveNullTransition(dependencyBuilder, dependencyKind); + Dependency resolvedDep = + resolveNullTransition(dependencyBuilder, dependencyKind, eventHandler); if (resolvedDep == null) { return null; // Need Skyframe deps. } @@ -260,19 +264,22 @@ return ImmutableList.of(resolveHostTransition(dependencyBuilder, dependencyKey)); } - return resolveGenericTransition(dependencyBuilder, dependencyKey); + return resolveGenericTransition(dependencyBuilder, dependencyKey, eventHandler); } @Nullable private Dependency resolveNullTransition( - Dependency.Builder dependencyBuilder, DependencyKind dependencyKind) + Dependency.Builder dependencyBuilder, + DependencyKind dependencyKind, + ExtendedEventHandler eventHandler) throws ConfiguredValueCreationException, InterruptedException { // The null configuration can be trivially computed (it's, well, null), so special-case that // transition here and skip the rest of the logic. A *lot* of targets have null deps, so // this produces real savings. Profiling tests over a simple cc_binary show this saves ~1% of // total analysis phase time. if (dependencyKind.getAttribute() != null) { - ImmutableList<String> transitionKeys = collectTransitionKeys(dependencyKind.getAttribute()); + ImmutableList<String> transitionKeys = + collectTransitionKeys(dependencyKind.getAttribute(), eventHandler); if (transitionKeys == null) { return null; // Need Skyframe deps. } @@ -293,7 +300,8 @@ @Nullable private ImmutableList<Dependency> resolveGenericTransition( Dependency.Builder dependencyBuilder, - DependencyKey dependencyKey) + DependencyKey dependencyKey, + ExtendedEventHandler eventHandler) throws ConfiguredValueCreationException, InterruptedException { Map<String, BuildOptions> toOptions; try { @@ -302,7 +310,7 @@ getCurrentConfiguration().getOptions(), dependencyKey.getTransition(), env, - env.getListener()); + eventHandler); if (toOptions == null) { return null; // Need more Skyframe deps for a Starlark transition. } @@ -380,7 +388,8 @@ } @Nullable - private ImmutableList<String> collectTransitionKeys(Attribute attribute) + private ImmutableList<String> collectTransitionKeys( + Attribute attribute, ExtendedEventHandler eventHandler) throws ConfiguredValueCreationException, InterruptedException { TransitionFactory<AttributeTransitionData> transitionFactory = attribute.getTransitionFactory(); if (transitionFactory.isSplit()) { @@ -397,7 +406,7 @@ try { toOptions = applyTransitionWithSkyframe( - getCurrentConfiguration().getOptions(), baseTransition, env, env.getListener()); + getCurrentConfiguration().getOptions(), baseTransition, env, eventHandler); if (toOptions == null) { return null; // Need more Skyframe deps for a Starlark transition. }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java index fe141a9..dcb2189 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
@@ -315,8 +315,11 @@ } SkyframeDependencyResolver resolver = new SkyframeDependencyResolver(env); - NestedSetBuilder<Package> transitivePackagesForPackageRootResolution = - storeTransitivePackagesForPackageRootResolution ? NestedSetBuilder.stableOrder() : null; + ConfiguredTargetFunction.State state = + env.getState( + () -> + new ConfiguredTargetFunction.State( + storeTransitivePackagesForPackageRootResolution)); TargetAndConfiguration originalTargetAndConfiguration = new TargetAndConfiguration(target, configuration); @@ -327,16 +330,14 @@ return null; } - NestedSetBuilder<Cause> transitiveRootCauses = NestedSetBuilder.stableOrder(); - // Get the configuration targets that trigger this rule's configurable attributes. ConfigConditions configConditions = ConfiguredTargetFunction.getConfigConditions( env, originalTargetAndConfiguration, - transitivePackagesForPackageRootResolution, + state.transitivePackagesForPackageRootResolution, unloadedToolchainContext == null ? null : unloadedToolchainContext.targetPlatform(), - transitiveRootCauses); + state.transitiveRootCauses); if (configConditions == null) { // Those targets haven't yet been resolved. return null; @@ -346,6 +347,7 @@ try { depValueMap = ConfiguredTargetFunction.computeDependencies( + state, env, resolver, originalTargetAndConfiguration, @@ -358,9 +360,7 @@ .build(), shouldUseToolchainTransition(configuration, aspect.getDefinition()), ruleClassProvider, - buildViewProvider.getSkyframeBuildView().getHostConfiguration(), - transitivePackagesForPackageRootResolution, - transitiveRootCauses); + buildViewProvider.getSkyframeBuildView().getHostConfiguration()); } catch (ConfiguredValueCreationException e) { throw new AspectCreationException( e.getMessage(), key.getLabel(), configuration, e.getDetailedExitCode()); @@ -368,8 +368,8 @@ if (depValueMap == null) { return null; } - if (!transitiveRootCauses.isEmpty()) { - NestedSet<Cause> causes = transitiveRootCauses.build(); + if (!state.transitiveRootCauses.isEmpty()) { + NestedSet<Cause> causes = state.transitiveRootCauses.build(); throw new AspectFunctionException( new AspectCreationException( "Loading failed", @@ -403,7 +403,7 @@ configConditions, toolchainContext, depValueMap, - transitivePackagesForPackageRootResolution); + state.transitivePackagesForPackageRootResolution); } catch (DependencyEvaluationException e) { // TODO(bazel-team): consolidate all env.getListener().handle() calls in this method, like in // ConfiguredTargetFunction. This encourages clear, consistent user messages (ideally without @@ -636,7 +636,8 @@ originalTargetAndAspectConfiguration, hostConfiguration, configConditions.asProviders()); - ImmutableList<Dependency> deps = resolver.resolveConfiguration(depKind, depKey); + ImmutableList<Dependency> deps = + resolver.resolveConfiguration(depKind, depKey, env.getListener()); if (deps == null) { return null; }
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 2d9ee1d..e5ef4c9 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
@@ -84,6 +84,7 @@ import com.google.devtools.build.lib.util.DetailedExitCode.DetailedExitCodeComparator; import com.google.devtools.build.lib.util.OrderedSetMultimap; import com.google.devtools.build.skyframe.SkyFunction; +import com.google.devtools.build.skyframe.SkyFunction.Environment.SkyKeyComputeState; import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; @@ -183,9 +184,61 @@ } } + static class State implements SkyKeyComputeState { + /** Null if ConfiguredTargetFuncton is not storing this information. */ + @Nullable NestedSetBuilder<Package> transitivePackagesForPackageRootResolution; + + NestedSetBuilder<Cause> transitiveRootCauses = NestedSetBuilder.stableOrder(); + + /** Null if not yet computed or if {@link #resolveConfigurationsResult} is non-null. */ + @Nullable private OrderedSetMultimap<DependencyKind, DependencyKey> dependentNodeMapResult; + + /** Null if not yet computed or if {@link #computeDependenciesResult} is non-null. */ + @Nullable private OrderedSetMultimap<DependencyKind, Dependency> resolveConfigurationsResult; + + /** Null if not yet computed or if {@link #computeDependenciesResult} is non-null. */ + @Nullable + private Map<SkyKey, ConfiguredTargetAndData> resolveConfiguredTargetDependenciesResult; + + /** Null if not yet computed or if {@link #computeDependenciesResult} is non-null. */ + @Nullable + private OrderedSetMultimap<Dependency, ConfiguredAspect> resolveAspectDependenciesResult; + + /** + * Non-null if all the work in {@link #computeDependencies} is already done. This field contains + * the result. + */ + @Nullable + private OrderedSetMultimap<DependencyKind, ConfiguredTargetAndData> computeDependenciesResult; + + /** + * Non-null if either {@link #resolveConfigurationsResult} or {@link #computeDependenciesResult} + * are non-null. This field contains events (from {@link + * ConfigurationResolver#resolveConfigurations}) that should be replayed. + * + * <p>When {@link #resolveConfigurationsResult} or {@link #computeDependenciesResult} are + * non-null (e.g. populated on a previous call to {@link #computeDependencies} on a previous + * call to {@link #compute}), we don't freshly do the work that would cause these events to be + * freshly emitted. So instead we replay these events from the actual call to {@link + * ConfigurationResolver#resolveConfigurations} we did in the past. This is important because + * Skyframe retains and uses only the events emitted to {@code env.getListener()} on a call to + * {@link #compute} that had no missing deps. That is, if our earlier {@link #compute}'s call to + * {@link ConfigurationResolver#resolveConfigurations} emitted events to {@code + * env.getListener()}, and that {@link #compute} call returned null, then those events would be + * thrown away. + */ + @Nullable private StoredEventHandler storedEventHandlerFromResolveConfigurations; + + State(boolean storeTransitivePackagesForPackageRootResolution) { + this.transitivePackagesForPackageRootResolution = + storeTransitivePackagesForPackageRootResolution ? NestedSetBuilder.stableOrder() : null; + } + } + @Override public SkyValue compute(SkyKey key, Environment env) throws ReportedException, UnreportedException, InterruptedException { + State state = env.getState(() -> new State(storeTransitivePackagesForPackageRootResolution)); if (shouldUnblockCpuWorkWhenFetchingDeps) { env = new StateInformingSkyFunctionEnvironment( @@ -194,9 +247,6 @@ /*postFetch=*/ () -> maybeAcquireSemaphoreWithLogging(key)); } SkyframeBuildView view = buildViewProvider.getSkyframeBuildView(); - NestedSetBuilder<Package> transitivePackagesForPackageRootResolution = - storeTransitivePackagesForPackageRootResolution ? NestedSetBuilder.stableOrder() : null; - NestedSetBuilder<Cause> transitiveRootCauses = NestedSetBuilder.stableOrder(); ConfiguredTargetKey configuredTargetKey = (ConfiguredTargetKey) key.argument(); Label label = configuredTargetKey.getLabel(); @@ -241,10 +291,11 @@ } if (pkg.containsErrors()) { FailureDetail failureDetail = pkg.contextualizeFailureDetailForTarget(target); - transitiveRootCauses.add(new LoadingFailedCause(label, DetailedExitCode.of(failureDetail))); + state.transitiveRootCauses.add( + new LoadingFailedCause(label, DetailedExitCode.of(failureDetail))); } - if (transitivePackagesForPackageRootResolution != null) { - transitivePackagesForPackageRootResolution.add(pkg); + if (state.transitivePackagesForPackageRootResolution != null) { + state.transitivePackagesForPackageRootResolution.add(pkg); } if (target.isConfigurable() == (configuredTargetKey.getConfigurationKey() == null)) { // We somehow ended up in a target that requires a non-null configuration as a dependency of @@ -254,9 +305,9 @@ // not prepared for it. return new NonRuleConfiguredTargetValue( new EmptyConfiguredTarget(target.getLabel(), configuredTargetKey.getConfigurationKey()), - transitivePackagesForPackageRootResolution == null + state.transitivePackagesForPackageRootResolution == null ? null - : transitivePackagesForPackageRootResolution.build()); + : state.transitivePackagesForPackageRootResolution.build()); } TargetAndConfiguration ctgValue = new TargetAndConfiguration(target, configuration); @@ -287,11 +338,11 @@ getConfigConditions( env, ctgValue, - transitivePackagesForPackageRootResolution, + state.transitivePackagesForPackageRootResolution, unloadedToolchainContexts == null ? null : unloadedToolchainContexts.getTargetPlatform(), - transitiveRootCauses); + state.transitiveRootCauses); if (env.valuesMissing()) { return null; } @@ -302,9 +353,9 @@ // more root causes during computeDependencies. // Note that this doesn't apply to AspectFunction, because aspects can't have configurable // attributes. - if (!transitiveRootCauses.isEmpty() + if (!state.transitiveRootCauses.isEmpty() && !Objects.equals(configConditions, ConfigConditions.EMPTY)) { - NestedSet<Cause> causes = transitiveRootCauses.build(); + NestedSet<Cause> causes = state.transitiveRootCauses.build(); env.getListener() .handle(Event.error(target.getLocation(), "Cannot compute config conditions")); throw new ReportedException( @@ -318,6 +369,7 @@ // Calculate the dependencies of this target. OrderedSetMultimap<DependencyKind, ConfiguredTargetAndData> depValueMap = computeDependencies( + state, env, resolver, ctgValue, @@ -328,11 +380,9 @@ : unloadedToolchainContexts.asToolchainContexts(), DependencyResolver.shouldUseToolchainTransition(configuration, ctgValue.getTarget()), ruleClassProvider, - view.getHostConfiguration(), - transitivePackagesForPackageRootResolution, - transitiveRootCauses); - if (!transitiveRootCauses.isEmpty()) { - NestedSet<Cause> causes = transitiveRootCauses.build(); + view.getHostConfiguration()); + if (!state.transitiveRootCauses.isEmpty()) { + NestedSet<Cause> causes = state.transitiveRootCauses.build(); // TODO(bazel-team): consider reporting the error in this class vs. exporting it for // BuildTool to handle. Calling code needs to be untangled for that to work and pass tests. throw new UnreportedException( @@ -372,7 +422,7 @@ configConditions, toolchainContexts, execGroupCollectionBuilder, - transitivePackagesForPackageRootResolution); + state.transitivePackagesForPackageRootResolution); if (ans != null && configuredTargetProgress != null) { configuredTargetProgress.doneConfigureTarget(); } @@ -615,6 +665,7 @@ * <p>Returns null if Skyframe hasn't evaluated the required dependencies yet. In this case, the * caller should also return null to Skyframe. * + * @param state the compute state * @param env the Skyframe environment * @param resolver the dependency resolver * @param ctgValue the label and the configuration of the node @@ -626,8 +677,11 @@ * instantiating this on demand for every dependency that wants it, so it's best to compute * the host configuration as early as possible and pass this reference to all consumers */ + // TODO(b/213351014): Make the control flow of this helper function more readable. This will + // involve making a corresponding change to State to match the control flow. @Nullable static OrderedSetMultimap<DependencyKind, ConfiguredTargetAndData> computeDependencies( + State state, Environment env, SkyframeDependencyResolver resolver, TargetAndConfiguration ctgValue, @@ -636,42 +690,71 @@ @Nullable ToolchainCollection<ToolchainContext> toolchainContexts, boolean useToolchainTransition, RuleClassProvider ruleClassProvider, - BuildConfigurationValue hostConfiguration, - @Nullable NestedSetBuilder<Package> transitivePackagesForPackageRootResolution, - NestedSetBuilder<Cause> transitiveRootCauses) + BuildConfigurationValue hostConfiguration) throws DependencyEvaluationException, ConfiguredValueCreationException, AspectCreationException, InterruptedException { - // Create the map from attributes to set of (target, transition) pairs. - OrderedSetMultimap<DependencyKind, DependencyKey> initialDependencies; - BuildConfigurationValue configuration = ctgValue.getConfiguration(); - Label label = ctgValue.getLabel(); - try { - initialDependencies = - resolver.dependentNodeMap( - ctgValue, - aspects, - configConditions, - toolchainContexts, - useToolchainTransition, - transitiveRootCauses, - ((ConfiguredRuleClassProvider) ruleClassProvider).getTrimmingTransitionFactory()); - } catch (DependencyResolver.Failure e) { - env.getListener().post(new AnalysisRootCauseEvent(configuration, label, e.getMessage())); - throw new DependencyEvaluationException( - new ConfiguredValueCreationException( - e.getLocation(), e.getMessage(), label, configuration.getEventId(), null, null), - // These errors occur within DependencyResolver, which is attached to the current target. - // i.e. no dependent ConfiguredTargetFunction call happens to report its own error. - /*depReportedOwnError=*/ false); - } catch (InconsistentAspectOrderException e) { - throw new DependencyEvaluationException(e); + if (state.computeDependenciesResult != null) { + state.storedEventHandlerFromResolveConfigurations.replayOn(env.getListener()); + return state.computeDependenciesResult; } - // Trim each dep's configuration so it only includes the fragments needed by its transitive - // closure. - ConfigurationResolver configResolver = - new ConfigurationResolver(env, ctgValue, hostConfiguration, configConditions); - OrderedSetMultimap<DependencyKind, Dependency> depValueNames = - configResolver.resolveConfigurations(initialDependencies); + + OrderedSetMultimap<DependencyKind, Dependency> depValueNames; + if (state.resolveConfigurationsResult != null) { + depValueNames = state.resolveConfigurationsResult; + } else { + // Create the map from attributes to set of (target, transition) pairs. + OrderedSetMultimap<DependencyKind, DependencyKey> initialDependencies; + if (state.dependentNodeMapResult != null) { + initialDependencies = state.dependentNodeMapResult; + } else { + BuildConfigurationValue configuration = ctgValue.getConfiguration(); + Label label = ctgValue.getLabel(); + try { + initialDependencies = + resolver.dependentNodeMap( + ctgValue, + aspects, + configConditions, + toolchainContexts, + useToolchainTransition, + state.transitiveRootCauses, + ((ConfiguredRuleClassProvider) ruleClassProvider).getTrimmingTransitionFactory()); + } catch (DependencyResolver.Failure e) { + env.getListener().post(new AnalysisRootCauseEvent(configuration, label, e.getMessage())); + throw new DependencyEvaluationException( + new ConfiguredValueCreationException( + e.getLocation(), e.getMessage(), label, configuration.getEventId(), null, null), + // These errors occur within DependencyResolver, which is attached to the current + // target. i.e. no dependent ConfiguredTargetFunction call happens to report its own + // error. + /*depReportedOwnError=*/ false); + } catch (InconsistentAspectOrderException e) { + throw new DependencyEvaluationException(e); + } + if (!env.valuesMissing()) { + state.dependentNodeMapResult = initialDependencies; + } + } + // Trim each dep's configuration so it only includes the fragments needed by its transitive + // closure. + ConfigurationResolver configResolver = + new ConfigurationResolver(env, ctgValue, hostConfiguration, configConditions); + StoredEventHandler storedEventHandler = new StoredEventHandler(); + try { + depValueNames = + configResolver.resolveConfigurations(initialDependencies, storedEventHandler); + } catch (ConfiguredValueCreationException e) { + storedEventHandler.replayOn(env.getListener()); + throw e; + } + if (!env.valuesMissing()) { + state.resolveConfigurationsResult = depValueNames; + state.storedEventHandlerFromResolveConfigurations = storedEventHandler; + + // We won't need this anymore. + state.dependentNodeMapResult = null; + } + } // Return early in case packages were not loaded yet. In theory, we could start configuring // dependent targets in loaded packages. However, that creates an artificial sync boundary @@ -682,33 +765,58 @@ } // Resolve configured target dependencies and handle errors. - Map<SkyKey, ConfiguredTargetAndData> depValues = - resolveConfiguredTargetDependencies( - env, - ctgValue, - depValueNames.values(), - transitivePackagesForPackageRootResolution, - transitiveRootCauses); - if (depValues == null) { - return null; + Map<SkyKey, ConfiguredTargetAndData> depValues; + if (state.resolveConfiguredTargetDependenciesResult != null) { + depValues = state.resolveConfiguredTargetDependenciesResult; + } else { + depValues = + resolveConfiguredTargetDependencies( + env, + ctgValue, + depValueNames.values(), + state.transitivePackagesForPackageRootResolution, + state.transitiveRootCauses); + if (env.valuesMissing()) { + return null; + } + state.resolveConfiguredTargetDependenciesResult = depValues; } // Resolve required aspects. - OrderedSetMultimap<Dependency, ConfiguredAspect> depAspects = - AspectResolver.resolveAspectDependencies( - env, depValues, depValueNames.values(), transitivePackagesForPackageRootResolution); - if (depAspects == null) { - return null; + OrderedSetMultimap<Dependency, ConfiguredAspect> depAspects; + if (state.resolveAspectDependenciesResult != null) { + depAspects = state.resolveAspectDependenciesResult; + } else { + depAspects = + AspectResolver.resolveAspectDependencies( + env, + depValues, + depValueNames.values(), + state.transitivePackagesForPackageRootResolution); + if (env.valuesMissing()) { + return null; + } + state.resolveAspectDependenciesResult = depAspects; } // Merge the dependent configured targets and aspects into a single map. + OrderedSetMultimap<DependencyKind, ConfiguredTargetAndData> mergeAspectsResult; try { - return AspectResolver.mergeAspects(depValueNames, depValues, depAspects); + mergeAspectsResult = AspectResolver.mergeAspects(depValueNames, depValues, depAspects); } catch (DuplicateException e) { throw new DependencyEvaluationException( new ConfiguredValueCreationException(ctgValue, e.getMessage()), /*depReportedOwnError=*/ false); } + state.computeDependenciesResult = mergeAspectsResult; + state.storedEventHandlerFromResolveConfigurations.replayOn(env.getListener()); + + // We won't need these anymore. + state.resolveConfigurationsResult = null; + state.resolveConfiguredTargetDependenciesResult = null; + state.resolveAspectDependenciesResult = null; + + return mergeAspectsResult; } /**
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/ConfigurationsForTargetsTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/ConfigurationsForTargetsTest.java index 5080367..05a4f41 100644 --- a/src/test/java/com/google/devtools/build/lib/skyframe/ConfigurationsForTargetsTest.java +++ b/src/test/java/com/google/devtools/build/lib/skyframe/ConfigurationsForTargetsTest.java
@@ -33,7 +33,6 @@ import com.google.devtools.build.lib.analysis.config.ConfigurationResolver; import com.google.devtools.build.lib.analysis.util.AnalysisMock; import com.google.devtools.build.lib.analysis.util.AnalysisTestCase; -import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.packages.Attribute; import com.google.devtools.build.lib.packages.RuleClassProvider; import com.google.devtools.build.lib.packages.Target; @@ -119,6 +118,8 @@ try { OrderedSetMultimap<DependencyKind, ConfiguredTargetAndData> depMap = ConfiguredTargetFunction.computeDependencies( + new ConfiguredTargetFunction.State( + /*storeTransitivePackagesForPackageRootResolution=*/ false), env, new SkyframeDependencyResolver(env), (TargetAndConfiguration) skyKey.argument(), @@ -127,9 +128,7 @@ /*toolchainContexts=*/ null, /*useToolchainTransition=*/ false, stateProvider.lateBoundRuleClassProvider(), - stateProvider.lateBoundHostConfig(), - NestedSetBuilder.stableOrder(), - NestedSetBuilder.stableOrder()); + stateProvider.lateBoundHostConfig()); return env.valuesMissing() ? null : new Value(depMap); } catch (RuntimeException e) { throw e;