use of com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment in project bazel by bazelbuild.
the class TransitiveTargetFunction method computeSkyValue.
@Override
public SkyValue computeSkyValue(TargetAndErrorIfAny targetAndErrorIfAny, TransitiveTargetValueBuilder builder) {
Target target = targetAndErrorIfAny.getTarget();
NoSuchTargetException errorLoadingTarget = targetAndErrorIfAny.getErrorLoadingTarget();
// Get configuration fragments directly required by this rule.
if (target instanceof Rule) {
Rule rule = (Rule) target;
// Declared by the rule class:
ConfigurationFragmentPolicy configurationFragmentPolicy = rule.getRuleClassObject().getConfigurationFragmentPolicy();
for (ConfigurationFragmentFactory factory : ruleClassProvider.getConfigurationFragments()) {
Class<? extends Fragment> fragment = factory.creates();
// (named) fragments.
if (configurationFragmentPolicy.isLegalConfigurationFragment(fragment)) {
addFragmentIfNew(builder, fragment.asSubclass(BuildConfiguration.Fragment.class));
}
}
// Declared by late-bound attributes:
for (Attribute attr : rule.getAttributes()) {
if (attr.isLateBound()) {
addFragmentsIfNew(builder, attr.getLateBoundDefault().getRequiredConfigurationFragments());
}
}
// corresponding fragments in their configurations to properly resolve:
if (rule.getRuleClass().equals(ConfigSettingRule.RULE_NAME)) {
addFragmentsIfNew(builder, ConfigSettingRule.requiresConfigurationFragments(rule, optionsToFragmentMap));
}
// Fragments to unconditionally include:
addFragmentIfNew(builder, ruleClassProvider.getUniversalFragment().asSubclass(BuildConfiguration.Fragment.class));
}
return builder.build(errorLoadingTarget);
}
use of com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment in project bazel by bazelbuild.
the class BuildConfigurationFunction method compute.
@Override
public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException, BuildConfigurationFunctionException {
BuildConfigurationValue.Key key = (BuildConfigurationValue.Key) skyKey.argument();
Set<Fragment> fragments;
try {
fragments = getConfigurationFragments(key, env);
} catch (InvalidConfigurationException e) {
throw new BuildConfigurationFunctionException(e);
}
if (fragments == null) {
return null;
}
ClassToInstanceMap<Fragment> fragmentsMap = MutableClassToInstanceMap.create();
for (Fragment fragment : fragments) {
fragmentsMap.put(fragment.getClass(), fragment);
}
BuildConfiguration config = new BuildConfiguration(directories, fragmentsMap, key.getBuildOptions(), !key.actionsEnabled());
// Unlike static configurations, dynamic configurations don't need to embed transition logic
// within the configuration itself. However we still use this interface to provide a mapping
// between Transition types (e.g. HOST) and the dynamic transitions that apply those
// transitions. Once static configurations are cleaned out we won't need this interface
// any more (all the centralized logic that maintains the transition logic can be distributed
// to the actual rule code that uses it).
config.setConfigurationTransitions(collectionFactory.getDynamicTransitionLogic(config));
return new BuildConfigurationValue(config);
}
use of com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment in project bazel by bazelbuild.
the class ConfigurationFactory method getConfiguration.
/**
* Returns a {@link com.google.devtools.build.lib.analysis.config.BuildConfiguration} based on the
* given set of build options.
*
* <p>If the configuration has already been created, re-uses it, otherwise, creates a new one.
*/
@Nullable
public BuildConfiguration getConfiguration(PackageProviderForConfigurations loadedPackageProvider, BuildOptions buildOptions, boolean actionsDisabled, Cache<String, BuildConfiguration> cache) throws InvalidConfigurationException, InterruptedException {
String cacheKey = buildOptions.computeCacheKey();
BuildConfiguration result = cache.getIfPresent(cacheKey);
if (result != null) {
return result;
}
Map<Class<? extends Fragment>, Fragment> fragments = new HashMap<>();
// Create configuration fragments
for (ConfigurationFragmentFactory factory : configurationFragmentFactories) {
Class<? extends Fragment> fragmentType = factory.creates();
Fragment fragment = loadedPackageProvider.getFragment(buildOptions, fragmentType);
if (fragment != null && fragments.get(fragment.getClass()) == null) {
fragments.put(fragment.getClass(), fragment);
}
}
BlazeDirectories directories = loadedPackageProvider.getDirectories();
if (loadedPackageProvider.valuesMissing()) {
return null;
}
result = new BuildConfiguration(directories, fragments, buildOptions, actionsDisabled);
cache.put(cacheKey, result);
return result;
}
use of com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment in project bazel by bazelbuild.
the class TransitiveTargetFunction method computeOptionsToFragmentMap.
/**
* Computes the option name --> config fragments map. Note that this mapping is technically
* one-to-many: a single option may be required by multiple fragments (e.g. Java options are
* used by both JavaConfiguration and Jvm). In such cases, we arbitrarily choose one fragment
* since that's all that's needed to satisfy the config_setting.
*/
private static Map<String, Class<? extends Fragment>> computeOptionsToFragmentMap(ConfiguredRuleClassProvider ruleClassProvider) {
Map<String, Class<? extends Fragment>> result = new LinkedHashMap<>();
Map<Class<? extends FragmentOptions>, Integer> visitedOptionsClasses = new HashMap<>();
for (ConfigurationFragmentFactory factory : ruleClassProvider.getConfigurationFragments()) {
Set<Class<? extends FragmentOptions>> requiredOpts = factory.requiredOptions();
for (Class<? extends FragmentOptions> optionsClass : requiredOpts) {
Integer previousBest = visitedOptionsClasses.get(optionsClass);
if (previousBest != null && previousBest <= requiredOpts.size()) {
// on as few options classes as possible (not necessarily unique).
continue;
}
visitedOptionsClasses.put(optionsClass, requiredOpts.size());
for (Field field : optionsClass.getFields()) {
if (field.isAnnotationPresent(Option.class)) {
result.put(field.getAnnotation(Option.class).name(), factory.creates());
}
}
}
}
return result;
}
use of com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment in project bazel by bazelbuild.
the class TransitiveTargetFunction method processDeps.
@Override
void processDeps(TransitiveTargetValueBuilder builder, EventHandler eventHandler, TargetAndErrorIfAny targetAndErrorIfAny, Iterable<Entry<SkyKey, ValueOrException2<NoSuchPackageException, NoSuchTargetException>>> depEntries) throws InterruptedException {
boolean successfulTransitiveLoading = builder.isSuccessfulTransitiveLoading();
Target target = targetAndErrorIfAny.getTarget();
NestedSetBuilder<Label> transitiveRootCauses = builder.getTransitiveRootCauses();
for (Entry<SkyKey, ValueOrException2<NoSuchPackageException, NoSuchTargetException>> entry : depEntries) {
Label depLabel = (Label) entry.getKey().argument();
TransitiveTargetValue transitiveTargetValue;
try {
transitiveTargetValue = (TransitiveTargetValue) entry.getValue().get();
if (transitiveTargetValue == null) {
continue;
}
} catch (NoSuchPackageException | NoSuchTargetException e) {
successfulTransitiveLoading = false;
transitiveRootCauses.add(depLabel);
maybeReportErrorAboutMissingEdge(target, depLabel, e, eventHandler);
continue;
}
builder.getTransitiveSuccessfulPkgs().addTransitive(transitiveTargetValue.getTransitiveSuccessfulPackages());
builder.getTransitiveUnsuccessfulPkgs().addTransitive(transitiveTargetValue.getTransitiveUnsuccessfulPackages());
builder.getTransitiveTargets().addTransitive(transitiveTargetValue.getTransitiveTargets());
NestedSet<Label> rootCauses = transitiveTargetValue.getTransitiveRootCauses();
if (rootCauses != null) {
successfulTransitiveLoading = false;
transitiveRootCauses.addTransitive(rootCauses);
if (transitiveTargetValue.getErrorLoadingTarget() != null) {
maybeReportErrorAboutMissingEdge(target, depLabel, transitiveTargetValue.getErrorLoadingTarget(), eventHandler);
}
}
NestedSet<Class<? extends Fragment>> depFragments = transitiveTargetValue.getTransitiveConfigFragments();
Collection<Class<? extends Fragment>> depFragmentsAsCollection = depFragments.toCollection();
// The simplest collection technique would be to unconditionally add all deps' nested
// sets to the current target's nested set. But when there's large overlap between their
// fragment needs, this produces unnecessarily bloated nested sets and a lot of references
// that don't contribute anything unique to the required fragment set. So we optimize here
// by completely skipping sets that don't offer anything new. More fine-tuned optimization
// is possible, but this offers a good balance between simplicity and practical efficiency.
Set<Class<? extends Fragment>> addedConfigFragments = builder.getConfigFragmentsFromDeps();
if (!addedConfigFragments.containsAll(depFragmentsAsCollection)) {
builder.getTransitiveConfigFragments().addTransitive(depFragments);
addedConfigFragments.addAll(depFragmentsAsCollection);
}
}
builder.setSuccessfulTransitiveLoading(successfulTransitiveLoading);
}
Aggregations