use of com.google.devtools.build.lib.analysis.config.BuildConfiguration in project bazel by bazelbuild.
the class SkyframeDependencyResolver method getConfigurations.
@Nullable
@Override
protected List<BuildConfiguration> getConfigurations(Set<Class<? extends BuildConfiguration.Fragment>> fragments, Iterable<BuildOptions> buildOptions) throws InvalidConfigurationException, InterruptedException {
List<SkyKey> keys = new ArrayList<>();
for (BuildOptions options : buildOptions) {
keys.add(BuildConfigurationValue.key(fragments, options));
}
Map<SkyKey, ValueOrException<InvalidConfigurationException>> configValues = env.getValuesOrThrow(keys, InvalidConfigurationException.class);
if (env.valuesMissing()) {
return null;
}
ImmutableList.Builder<BuildConfiguration> result = ImmutableList.builder();
for (SkyKey key : keys) {
result.add(((BuildConfigurationValue) configValues.get(key).get()).getConfiguration());
}
return result.build();
}
use of com.google.devtools.build.lib.analysis.config.BuildConfiguration in project bazel by bazelbuild.
the class SkyframeExecutor method getConfigurations.
/**
* Retrieves the configurations needed for the given deps. If {@link
* BuildConfiguration.Options#trimConfigurations()} is true, trims their fragments to only those
* needed by their transitive closures. Else unconditionally includes all fragments.
*
* <p>Skips targets with loading phase errors.
*/
public Multimap<Dependency, BuildConfiguration> getConfigurations(ExtendedEventHandler eventHandler, BuildOptions fromOptions, Iterable<Dependency> keys) {
Multimap<Dependency, BuildConfiguration> builder = ArrayListMultimap.<Dependency, BuildConfiguration>create();
Set<Dependency> depsToEvaluate = new HashSet<>();
// Check: if !Configuration.useDynamicConfigs then just return the original configs.
Set<Class<? extends BuildConfiguration.Fragment>> allFragments = null;
if (useUntrimmedDynamicConfigs(fromOptions)) {
allFragments = ((ConfiguredRuleClassProvider) ruleClassProvider).getAllFragments();
}
// Get the fragments needed for dynamic configuration nodes.
final List<SkyKey> transitiveFragmentSkyKeys = new ArrayList<>();
Map<Label, Set<Class<? extends BuildConfiguration.Fragment>>> fragmentsMap = new HashMap<>();
Set<Label> labelsWithErrors = new HashSet<>();
for (Dependency key : keys) {
if (key.hasStaticConfiguration()) {
builder.put(key, key.getConfiguration());
} else if (useUntrimmedDynamicConfigs(fromOptions)) {
fragmentsMap.put(key.getLabel(), allFragments);
} else {
depsToEvaluate.add(key);
transitiveFragmentSkyKeys.add(TransitiveTargetValue.key(key.getLabel()));
}
}
EvaluationResult<SkyValue> fragmentsResult = evaluateSkyKeys(eventHandler, transitiveFragmentSkyKeys, /*keepGoing=*/
true);
for (Map.Entry<SkyKey, ErrorInfo> entry : fragmentsResult.errorMap().entrySet()) {
reportCycles(eventHandler, entry.getValue().getCycleInfo(), entry.getKey());
}
for (Dependency key : keys) {
if (!depsToEvaluate.contains(key)) {
// No fragments to compute here.
} else if (fragmentsResult.getError(TransitiveTargetValue.key(key.getLabel())) != null) {
labelsWithErrors.add(key.getLabel());
} else {
TransitiveTargetValue ttv = (TransitiveTargetValue) fragmentsResult.get(TransitiveTargetValue.key(key.getLabel()));
fragmentsMap.put(key.getLabel(), ttv.getTransitiveConfigFragments().toSet());
}
}
// Now get the configurations.
final List<SkyKey> configSkyKeys = new ArrayList<>();
for (Dependency key : keys) {
if (labelsWithErrors.contains(key.getLabel()) || key.hasStaticConfiguration()) {
continue;
}
Set<Class<? extends BuildConfiguration.Fragment>> depFragments = fragmentsMap.get(key.getLabel());
if (depFragments != null) {
for (BuildOptions toOptions : ConfiguredTargetFunction.getDynamicTransitionOptions(fromOptions, key.getTransition(), depFragments, ruleClassProvider, true)) {
configSkyKeys.add(BuildConfigurationValue.key(depFragments, toOptions));
}
}
}
EvaluationResult<SkyValue> configsResult = evaluateSkyKeys(eventHandler, configSkyKeys, /*keepGoing=*/
true);
for (Dependency key : keys) {
if (labelsWithErrors.contains(key.getLabel()) || key.hasStaticConfiguration()) {
continue;
}
Set<Class<? extends BuildConfiguration.Fragment>> depFragments = fragmentsMap.get(key.getLabel());
if (depFragments != null) {
for (BuildOptions toOptions : ConfiguredTargetFunction.getDynamicTransitionOptions(fromOptions, key.getTransition(), depFragments, ruleClassProvider, true)) {
SkyKey configKey = BuildConfigurationValue.key(depFragments, toOptions);
builder.put(key, ((BuildConfigurationValue) configsResult.get(configKey)).getConfiguration());
}
}
}
return builder;
}
use of com.google.devtools.build.lib.analysis.config.BuildConfiguration in project bazel by bazelbuild.
the class PostConfiguredTargetFunction method compute.
@Nullable
@Override
public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException, InterruptedException {
ImmutableMap<ActionAnalysisMetadata, ConflictException> badActions = PrecomputedValue.BAD_ACTIONS.get(env);
ConfiguredTargetValue ctValue = (ConfiguredTargetValue) env.getValue(ConfiguredTargetValue.key((ConfiguredTargetKey) skyKey.argument()));
if (env.valuesMissing()) {
return null;
}
for (ActionAnalysisMetadata action : ctValue.getActions()) {
if (badActions.containsKey(action)) {
throw new ActionConflictFunctionException(badActions.get(action));
}
}
ConfiguredTarget ct = ctValue.getConfiguredTarget();
TargetAndConfiguration ctgValue = new TargetAndConfiguration(ct.getTarget(), ct.getConfiguration());
ImmutableMap<Label, ConfigMatchingProvider> configConditions = getConfigurableAttributeConditions(ctgValue, env);
if (configConditions == null) {
return null;
}
OrderedSetMultimap<Attribute, Dependency> deps;
try {
BuildConfiguration hostConfiguration = buildViewProvider.getSkyframeBuildView().getHostConfiguration(ct.getConfiguration());
SkyframeDependencyResolver resolver = buildViewProvider.getSkyframeBuildView().createDependencyResolver(env);
// We don't track root causes here - this function is only invoked for successfully analyzed
// targets - as long as we redo the exact same steps here as in ConfiguredTargetFunction, this
// can never fail.
deps = resolver.dependentNodeMap(ctgValue, hostConfiguration, /*aspect=*/
null, configConditions);
if (ct.getConfiguration() != null && ct.getConfiguration().useDynamicConfigurations()) {
deps = ConfiguredTargetFunction.getDynamicConfigurations(env, ctgValue, deps, hostConfiguration, ruleClassProvider);
}
} catch (EvalException | ConfiguredTargetFunction.DependencyEvaluationException | InvalidConfigurationException | InconsistentAspectOrderException e) {
throw new PostConfiguredTargetFunctionException(e);
}
env.getValues(Iterables.transform(deps.values(), TO_KEYS));
if (env.valuesMissing()) {
return null;
}
return new PostConfiguredTargetValue(ct);
}
use of com.google.devtools.build.lib.analysis.config.BuildConfiguration in project bazel by bazelbuild.
the class BazelConfigurationCollection method createConfigurations.
@Override
@Nullable
public BuildConfiguration createConfigurations(ConfigurationFactory configurationFactory, Cache<String, BuildConfiguration> cache, PackageProviderForConfigurations packageProvider, BuildOptions buildOptions, EventHandler eventHandler) throws InvalidConfigurationException, InterruptedException {
// Target configuration
BuildConfiguration targetConfiguration = configurationFactory.getConfiguration(packageProvider, buildOptions, false, cache);
if (targetConfiguration == null) {
return null;
}
BuildConfiguration dataConfiguration = targetConfiguration;
// Host configuration
// Note that this passes in the dataConfiguration, not the target
// configuration. This is intentional.
BuildConfiguration hostConfiguration = getHostConfigurationFromRequest(configurationFactory, packageProvider, dataConfiguration, buildOptions, cache);
if (hostConfiguration == null) {
return null;
}
ListMultimap<SplitTransition<?>, BuildConfiguration> splitTransitionsTable = ArrayListMultimap.create();
for (SplitTransition<BuildOptions> transition : buildOptions.getPotentialSplitTransitions()) {
for (BuildOptions splitOptions : transition.split(buildOptions)) {
BuildConfiguration splitConfig = configurationFactory.getConfiguration(packageProvider, splitOptions, false, cache);
splitTransitionsTable.put(transition, splitConfig);
}
}
if (packageProvider.valuesMissing()) {
return null;
}
BuildConfiguration result = setupTransitions(targetConfiguration, dataConfiguration, hostConfiguration, splitTransitionsTable);
result.reportInvalidOptions(eventHandler);
return result;
}
use of com.google.devtools.build.lib.analysis.config.BuildConfiguration in project bazel by bazelbuild.
the class SkyframeBuildView method getHostConfiguration.
/**
* Returns the host configuration trimmed to the same fragments as the input configuration. If
* the input is null, returns the top-level host configuration.
*
* <p>For static configurations, this unconditionally returns the (sole) top-level configuration.
*
* <p>This may only be called after {@link #setTopLevelHostConfiguration} has set the
* correct host configuration at the top-level.
*/
public BuildConfiguration getHostConfiguration(BuildConfiguration config) {
if (config == null || !config.useDynamicConfigurations()) {
return topLevelHostConfiguration;
}
// TODO(bazel-team): have the fragment classes be those required by the consuming target's
// transitive closure. This isn't the same as the input configuration's fragment classes -
// the latter may be a proper subset of the former.
//
// ConfigurationFactory.getConfiguration provides the reason why: if a declared required
// fragment is evaluated and returns null, it never gets added to the configuration. So if we
// use the configuration's fragments as the source of truth, that excludes required fragments
// that never made it in.
//
// If we're just trimming an existing configuration, this is no big deal (if the original
// configuration doesn't need the fragment, the trimmed one doesn't either). But this method
// trims a host configuration to the same scope as a target configuration. Since their options
// are different, the host instance may actually be able to produce the fragment. So it's
// wrong and potentially dangerous to unilaterally exclude it.
Set<Class<? extends BuildConfiguration.Fragment>> fragmentClasses = config.trimConfigurations() ? config.fragmentClasses() : ((ConfiguredRuleClassProvider) ruleClassProvider).getAllFragments();
BuildConfiguration hostConfig = hostConfigurationCache.get(fragmentClasses);
if (hostConfig != null) {
return hostConfig;
}
// TODO(bazel-team): investigate getting the trimmed config from Skyframe instead of cloning.
// This is the only place we instantiate BuildConfigurations outside of Skyframe, This can
// produce surprising effects, such as requesting a configuration that's in the Skyframe cache
// but still produces a unique instance because we don't check that cache. It'd be nice to
// guarantee that *all* instantiations happen through Skyframe. That could, for example,
// guarantee that config1.equals(config2) implies config1 == config2, which is nice for
// verifying we don't accidentally create extra configurations. But unfortunately,
// hostConfigurationCache was specifically created because Skyframe is too slow for this use
// case. So further optimization is necessary to make that viable (proto_library in particular
// contributes to much of the difference).
BuildConfiguration trimmedConfig = topLevelHostConfiguration.clone(fragmentClasses, ruleClassProvider);
hostConfigurationCache.put(fragmentClasses, trimmedConfig);
return trimmedConfig;
}
Aggregations