Search in sources :

Example 1 with Fragment

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);
}
Also used : Target(com.google.devtools.build.lib.packages.Target) ConfigurationFragmentPolicy(com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy) NoSuchTargetException(com.google.devtools.build.lib.packages.NoSuchTargetException) Attribute(com.google.devtools.build.lib.packages.Attribute) ConfigSettingRule(com.google.devtools.build.lib.analysis.config.ConfigRuleClasses.ConfigSettingRule) Rule(com.google.devtools.build.lib.packages.Rule) ConfigurationFragmentFactory(com.google.devtools.build.lib.analysis.config.ConfigurationFragmentFactory) Fragment(com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment)

Example 2 with Fragment

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);
}
Also used : BuildConfiguration(com.google.devtools.build.lib.analysis.config.BuildConfiguration) Fragment(com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment) SkyKey(com.google.devtools.build.skyframe.SkyKey) InvalidConfigurationException(com.google.devtools.build.lib.analysis.config.InvalidConfigurationException)

Example 3 with Fragment

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;
}
Also used : BlazeDirectories(com.google.devtools.build.lib.analysis.BlazeDirectories) HashMap(java.util.HashMap) Fragment(com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment) Nullable(javax.annotation.Nullable)

Example 4 with Fragment

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;
}
Also used : FragmentOptions(com.google.devtools.build.lib.analysis.config.FragmentOptions) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ConfigurationFragmentFactory(com.google.devtools.build.lib.analysis.config.ConfigurationFragmentFactory) Fragment(com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment) LinkedHashMap(java.util.LinkedHashMap) Field(java.lang.reflect.Field)

Example 5 with Fragment

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);
}
Also used : SkyKey(com.google.devtools.build.skyframe.SkyKey) Label(com.google.devtools.build.lib.cmdline.Label) ValueOrException2(com.google.devtools.build.skyframe.ValueOrException2) Fragment(com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment) Target(com.google.devtools.build.lib.packages.Target) NoSuchPackageException(com.google.devtools.build.lib.packages.NoSuchPackageException) NoSuchTargetException(com.google.devtools.build.lib.packages.NoSuchTargetException)

Aggregations

Fragment (com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment)7 ConfigurationFragmentFactory (com.google.devtools.build.lib.analysis.config.ConfigurationFragmentFactory)3 InvalidConfigurationException (com.google.devtools.build.lib.analysis.config.InvalidConfigurationException)3 SkyKey (com.google.devtools.build.skyframe.SkyKey)3 BuildConfiguration (com.google.devtools.build.lib.analysis.config.BuildConfiguration)2 NoSuchTargetException (com.google.devtools.build.lib.packages.NoSuchTargetException)2 Target (com.google.devtools.build.lib.packages.Target)2 HashMap (java.util.HashMap)2 ImmutableSet (com.google.common.collect.ImmutableSet)1 BlazeDirectories (com.google.devtools.build.lib.analysis.BlazeDirectories)1 BuildOptions (com.google.devtools.build.lib.analysis.config.BuildOptions)1 ConfigSettingRule (com.google.devtools.build.lib.analysis.config.ConfigRuleClasses.ConfigSettingRule)1 ConfigurationEnvironment (com.google.devtools.build.lib.analysis.config.ConfigurationEnvironment)1 FragmentOptions (com.google.devtools.build.lib.analysis.config.FragmentOptions)1 PackageProviderForConfigurations (com.google.devtools.build.lib.analysis.config.PackageProviderForConfigurations)1 Label (com.google.devtools.build.lib.cmdline.Label)1 Attribute (com.google.devtools.build.lib.packages.Attribute)1 ConfigurationFragmentPolicy (com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy)1 NoSuchPackageException (com.google.devtools.build.lib.packages.NoSuchPackageException)1 Rule (com.google.devtools.build.lib.packages.Rule)1