Search in sources :

Example 1 with LateBoundDefault

use of com.google.devtools.build.lib.packages.Attribute.LateBoundDefault in project bazel by bazelbuild.

the class DependencyResolver method resolveLateBoundAttribute.

/**
   * Returns the label dependencies for the given late-bound attribute in this rule.
   *
   * @param rule the rule being evaluated
   * @param attribute the attribute to evaluate
   * @param config the configuration to evaluate the attribute in
   * @param attributeMap mapper to attribute values
   */
private Iterable<Label> resolveLateBoundAttribute(Rule rule, Attribute attribute, BuildConfiguration config, AttributeMap attributeMap) throws EvalException, InterruptedException {
    Preconditions.checkArgument(attribute.isLateBound());
    @SuppressWarnings("unchecked") LateBoundDefault<BuildConfiguration> lateBoundDefault = (LateBoundDefault<BuildConfiguration>) attribute.getLateBoundDefault();
    // TODO(bazel-team): This might be too expensive - can we cache this somehow?
    if (!lateBoundDefault.getRequiredConfigurationFragments().isEmpty()) {
        if (!config.hasAllFragments(lateBoundDefault.getRequiredConfigurationFragments())) {
            return ImmutableList.<Label>of();
        }
    }
    // TODO(bazel-team): We should check if the implementation tries to access an undeclared
    // fragment.
    Object actualValue = lateBoundDefault.resolve(rule, attributeMap, config);
    if (EvalUtils.isNullOrNone(actualValue)) {
        return ImmutableList.<Label>of();
    }
    try {
        ImmutableList.Builder<Label> deps = ImmutableList.builder();
        if (attribute.getType() == BuildType.LABEL) {
            deps.add(rule.getLabel().resolveRepositoryRelative(BuildType.LABEL.cast(actualValue)));
        } else if (attribute.getType() == BuildType.LABEL_LIST) {
            for (Label label : BuildType.LABEL_LIST.cast(actualValue)) {
                deps.add(rule.getLabel().resolveRepositoryRelative(label));
            }
        } else {
            throw new IllegalStateException(String.format("Late bound attribute '%s' is not a label or a label list", attribute.getName()));
        }
        return deps.build();
    } catch (ClassCastException e) {
        // From either of the cast calls above.
        throw new EvalException(rule.getLocation(), String.format("When computing the default value of %s, expected '%s', got '%s'", attribute.getName(), attribute.getType(), EvalUtils.getDataTypeName(actualValue, true)));
    }
}
Also used : BuildConfiguration(com.google.devtools.build.lib.analysis.config.BuildConfiguration) ImmutableList(com.google.common.collect.ImmutableList) Label(com.google.devtools.build.lib.cmdline.Label) LateBoundDefault(com.google.devtools.build.lib.packages.Attribute.LateBoundDefault) EvalException(com.google.devtools.build.lib.syntax.EvalException)

Example 2 with LateBoundDefault

use of com.google.devtools.build.lib.packages.Attribute.LateBoundDefault in project bazel by bazelbuild.

the class DependencyResolver method resolveLateBoundAttributes.

/**
   * Resolves the dependencies for all late-bound attributes in this rule.
   *
   * <p>Late-bound attributes need special handling because they require configuration
   * transitions to determine their values.
   *
   * <p>In other words, the normal process of dependency resolution is:
   * <ol>
   *   <li>Find every label value in the rule's attributes</li>
   *   <li>Apply configuration transitions over each value to get its dep configuration
   *   <li>Return each value with its dep configuration</li>
   * </ol>
   *
   * This doesn't work for late-bound attributes because you can't get their values without
   * knowing the configuration first. And that configuration may not be the owning rule's
   * configuration. Specifically, {@link LateBoundDefault#useHostConfiguration()} switches to the
   * host config and late-bound split attributes branch into multiple split configs.
   *
   * <p>This method implements that logic and makes sure the normal configuration
   * transition logic mixes with it cleanly.
   *
   * @param depResolver the resolver for this rule's deps
   * @param ruleConfig the rule's configuration
   * @param hostConfig the equivalent host configuration
   */
private void resolveLateBoundAttributes(RuleResolver depResolver, BuildConfiguration ruleConfig, BuildConfiguration hostConfig) throws EvalException, InvalidConfigurationException, InconsistentAspectOrderException, InterruptedException {
    ConfiguredAttributeMapper attributeMap = depResolver.attributeMap;
    for (AttributeAndOwner attributeAndOwner : depResolver.attributes) {
        Attribute attribute = attributeAndOwner.attribute;
        if (!attribute.isLateBound() || !attribute.getCondition().apply(attributeMap)) {
            continue;
        }
        @SuppressWarnings("unchecked") LateBoundDefault<BuildConfiguration> lateBoundDefault = (LateBoundDefault<BuildConfiguration>) attribute.getLateBoundDefault();
        Collection<BuildOptions> splitOptions = getSplitOptions(depResolver.rule, attribute, ruleConfig);
        if (!splitOptions.isEmpty()) {
            // Late-bound attribute with a split transition:
            // Since we want to get the same results as BuildConfiguration.evaluateTransition (but
            // skip it since we've already applied the split), we want to make sure this logic
            // doesn't do anything differently. evaluateTransition has additional logic
            // for host configs and attributes with configurators. So we check here that neither of
            // of those apply, in the name of keeping the fork as simple as possible.
            Verify.verify(attribute.getConfigurator() == null);
            Verify.verify(!lateBoundDefault.useHostConfiguration());
            Iterable<BuildConfiguration> splitConfigs;
            if (!ruleConfig.useDynamicConfigurations()) {
                splitConfigs = ruleConfig.getSplitConfigurations(attribute.getSplitTransition(depResolver.rule));
            } else {
                splitConfigs = getConfigurations(ruleConfig.fragmentClasses(), splitOptions);
                if (splitConfigs == null) {
                    // Need Skyframe deps.
                    continue;
                }
            }
            for (BuildConfiguration splitConfig : splitConfigs) {
                for (Label dep : resolveLateBoundAttribute(depResolver.rule, attribute, splitConfig, attributeMap)) {
                    // Skip the normal config transition pipeline and directly feed the split config. This
                    // is because the split already had to be applied to determine the attribute's value.
                    // This makes the split logic in the normal pipeline redundant and potentially
                    // incorrect.
                    depResolver.resolveDep(attributeAndOwner, dep, splitConfig);
                }
            }
        } else {
            // Late-bound attribute without a split transition:
            for (Label dep : resolveLateBoundAttribute(depResolver.rule, attribute, lateBoundDefault.useHostConfiguration() ? hostConfig : ruleConfig, attributeMap)) {
                // Process this dep like a normal attribute.
                depResolver.resolveDep(attributeAndOwner, dep);
            }
        }
    }
}
Also used : BuildConfiguration(com.google.devtools.build.lib.analysis.config.BuildConfiguration) Attribute(com.google.devtools.build.lib.packages.Attribute) BuildOptions(com.google.devtools.build.lib.analysis.config.BuildOptions) Label(com.google.devtools.build.lib.cmdline.Label) LateBoundDefault(com.google.devtools.build.lib.packages.Attribute.LateBoundDefault)

Aggregations

BuildConfiguration (com.google.devtools.build.lib.analysis.config.BuildConfiguration)2 Label (com.google.devtools.build.lib.cmdline.Label)2 LateBoundDefault (com.google.devtools.build.lib.packages.Attribute.LateBoundDefault)2 ImmutableList (com.google.common.collect.ImmutableList)1 BuildOptions (com.google.devtools.build.lib.analysis.config.BuildOptions)1 Attribute (com.google.devtools.build.lib.packages.Attribute)1 EvalException (com.google.devtools.build.lib.syntax.EvalException)1