Search in sources :

Example 1 with SkylarkComputedDefaultTemplate

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

the class RuleClass method populateDefaultRuleAttributeValues.

/**
   * Populates the attributes table of the new {@link Rule} with default values provided by this
   * {@link RuleClass} and the {@code pkgBuilder}. This will only provide values for attributes that
   * haven't already been populated, using {@code definedAttrIndices} to determine whether an
   * attribute was populated.
   *
   * <p>Errors are reported on {@code eventHandler}.
   */
private void populateDefaultRuleAttributeValues(Rule rule, Package.Builder pkgBuilder, BitSet definedAttrIndices, EventHandler eventHandler) throws InterruptedException, CannotPrecomputeDefaultsException {
    // Set defaults; ensure that every mandatory attribute has a value. Use the default if none
    // is specified.
    List<Attribute> attrsWithComputedDefaults = new ArrayList<>();
    int numAttributes = getAttributeCount();
    for (int attrIndex = 0; attrIndex < numAttributes; ++attrIndex) {
        if (definedAttrIndices.get(attrIndex)) {
            continue;
        }
        Attribute attr = getAttribute(attrIndex);
        if (attr.isMandatory()) {
            rule.reportError(String.format("%s: missing value for mandatory attribute '%s' in '%s' rule", rule.getLabel(), attr.getName(), name), eventHandler);
        }
        if (attr.hasComputedDefault()) {
            // Note that it is necessary to set all non-computed default values before calling
            // Attribute#getDefaultValue for computed default attributes. Computed default attributes
            // may have a condition predicate (i.e. the predicate returned by Attribute#getCondition)
            // that depends on non-computed default attribute values, and that condition predicate is
            // evaluated by the call to Attribute#getDefaultValue.
            attrsWithComputedDefaults.add(attr);
        } else {
            Object defaultValue = getAttributeNoncomputedDefaultValue(attr, pkgBuilder);
            rule.setAttributeValue(attr, defaultValue, /*explicit=*/
            false);
            checkAllowedValues(rule, attr, eventHandler);
        }
    }
    // have been set.
    for (Attribute attr : attrsWithComputedDefaults) {
        // If Attribute#hasComputedDefault was true above, Attribute#getDefaultValue returns the
        // computed default function object or a Skylark computed default template. Note that we
        // cannot determine the exact value of the computed default function here because it may
        // depend on other attribute values that are configurable (i.e. they came from select({..})
        // expressions in the build language, and they require configuration data from the analysis
        // phase to be resolved). Instead, we're setting the attribute value to a reference to the
        // computed default function, or if #getDefaultValue is a Skylark computed default
        // template, setting the attribute value to a reference to the SkylarkComputedDefault
        // returned from SkylarkComputedDefaultTemplate#computePossibleValues.
        //
        // SkylarkComputedDefaultTemplate#computePossibleValues pre-computes all possible values the
        // function may evaluate to, and records them in a lookup table. By calling it here, with an
        // EventHandler, any errors that might occur during the function's evaluation can
        // be discovered and propagated here.
        Object valueToSet;
        Object defaultValue = attr.getDefaultValue(rule);
        if (defaultValue instanceof SkylarkComputedDefaultTemplate) {
            SkylarkComputedDefaultTemplate template = (SkylarkComputedDefaultTemplate) defaultValue;
            valueToSet = template.computePossibleValues(attr, rule, eventHandler);
        } else {
            valueToSet = defaultValue;
        }
        rule.setAttributeValue(attr, valueToSet, /*explicit=*/
        false);
    }
}
Also used : ArrayList(java.util.ArrayList) SkylarkComputedDefaultTemplate(com.google.devtools.build.lib.packages.Attribute.SkylarkComputedDefaultTemplate)

Example 2 with SkylarkComputedDefaultTemplate

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

the class SkylarkAttr method createAttribute.

private static Attribute.Builder<?> createAttribute(Type<?> type, SkylarkDict<String, Object> arguments, FuncallExpression ast, Environment env) throws EvalException, ConversionException {
    // We use an empty name now so that we can set it later.
    // This trick makes sense only in the context of Skylark (builtin rules should not use it).
    Attribute.Builder<?> builder = Attribute.attr("", type);
    Object defaultValue = arguments.get(DEFAULT_ARG);
    if (!EvalUtils.isNullOrNone(defaultValue)) {
        if (defaultValue instanceof UserDefinedFunction) {
            // Computed attribute. Non label type attributes already caused a type check error.
            SkylarkCallbackFunction callback = new SkylarkCallbackFunction((UserDefinedFunction) defaultValue, ast, env);
            // SkylarkComputedDefaultTemplate needs to know the names of all attributes that it depends
            // on. However, this method does not know anything about other attributes.
            // We solve this problem by asking the SkylarkCallbackFunction for the parameter names used
            // in the function definition, which must be the names of attributes used by the callback.
            builder.value(new SkylarkComputedDefaultTemplate(type, callback.getParameterNames(), callback, ast.getLocation()));
        } else {
            builder.defaultValue(defaultValue, env.getGlobals().label());
        }
    }
    for (String flag : SkylarkList.castSkylarkListOrNoneToList(arguments.get(FLAGS_ARG), String.class, FLAGS_ARG)) {
        builder.setPropertyFlag(flag);
    }
    if (containsNonNoneKey(arguments, MANDATORY_ARG) && (Boolean) arguments.get(MANDATORY_ARG)) {
        builder.setPropertyFlag("MANDATORY");
    }
    // TODO(laurentlb): Deprecated, remove in August 2016 (use allow_empty instead).
    if (containsNonNoneKey(arguments, NON_EMPTY_ARG) && (Boolean) arguments.get(NON_EMPTY_ARG)) {
        builder.setPropertyFlag("NON_EMPTY");
    }
    if (containsNonNoneKey(arguments, ALLOW_EMPTY_ARG) && !(Boolean) arguments.get(ALLOW_EMPTY_ARG)) {
        builder.setPropertyFlag("NON_EMPTY");
    }
    if (containsNonNoneKey(arguments, EXECUTABLE_ARG) && (Boolean) arguments.get(EXECUTABLE_ARG)) {
        builder.setPropertyFlag("EXECUTABLE");
        if (!containsNonNoneKey(arguments, CONFIGURATION_ARG)) {
            throw new EvalException(ast.getLocation(), "cfg parameter is mandatory when executable=True is provided. Please see " + "https://www.bazel.build/versions/master/docs/skylark/rules.html#configurations " + "for more details.");
        }
    }
    // TODO(laurentlb): Deprecated, remove in August 2016 (use allow_single_file).
    if (containsNonNoneKey(arguments, SINGLE_FILE_ARG) && (Boolean) arguments.get(SINGLE_FILE_ARG)) {
        if (containsNonNoneKey(arguments, ALLOW_SINGLE_FILE_ARG)) {
            throw new EvalException(ast.getLocation(), "Cannot specify both single_file (deprecated) and allow_single_file");
        }
        builder.setPropertyFlag("SINGLE_ARTIFACT");
    }
    if (containsNonNoneKey(arguments, ALLOW_FILES_ARG) && containsNonNoneKey(arguments, ALLOW_SINGLE_FILE_ARG)) {
        throw new EvalException(ast.getLocation(), "Cannot specify both allow_files and allow_single_file");
    }
    if (containsNonNoneKey(arguments, ALLOW_FILES_ARG)) {
        Object fileTypesObj = arguments.get(ALLOW_FILES_ARG);
        setAllowedFileTypes(ALLOW_FILES_ARG, fileTypesObj, ast, builder);
    } else if (containsNonNoneKey(arguments, ALLOW_SINGLE_FILE_ARG)) {
        Object fileTypesObj = arguments.get(ALLOW_SINGLE_FILE_ARG);
        setAllowedFileTypes(ALLOW_SINGLE_FILE_ARG, fileTypesObj, ast, builder);
        builder.setPropertyFlag("SINGLE_ARTIFACT");
    } else if (type.getLabelClass() == LabelClass.DEPENDENCY) {
        builder.allowedFileTypes(FileTypeSet.NO_FILE);
    }
    Object ruleClassesObj = arguments.get(ALLOW_RULES_ARG);
    if (ruleClassesObj != null && ruleClassesObj != Runtime.NONE) {
        builder.allowedRuleClasses(SkylarkList.castSkylarkListOrNoneToList(ruleClassesObj, String.class, "allowed rule classes for attribute definition"));
    }
    List<Object> values = SkylarkList.castSkylarkListOrNoneToList(arguments.get(VALUES_ARG), Object.class, VALUES_ARG);
    if (!Iterables.isEmpty(values)) {
        builder.allowedValues(new AllowedValueSet(values));
    }
    if (containsNonNoneKey(arguments, PROVIDERS_ARG)) {
        Object obj = arguments.get(PROVIDERS_ARG);
        SkylarkType.checkType(obj, SkylarkList.class, PROVIDERS_ARG);
        ImmutableList<ImmutableSet<SkylarkProviderIdentifier>> providersList = buildProviderPredicate((SkylarkList<?>) obj, PROVIDERS_ARG, ast.getLocation());
        builder.mandatoryProvidersList(providersList);
    }
    if (containsNonNoneKey(arguments, CONFIGURATION_ARG)) {
        Object trans = arguments.get(CONFIGURATION_ARG);
        if (trans.equals("data")) {
            builder.cfg(ConfigurationTransition.DATA);
        } else if (trans.equals("host")) {
            builder.cfg(ConfigurationTransition.HOST);
        } else if (trans instanceof SplitTransition<?>) {
            builder.cfg((SplitTransition<?>) trans);
        } else if (!trans.equals("target")) {
            throw new EvalException(ast.getLocation(), "cfg must be either 'data', 'host', or 'target'.");
        }
    }
    if (containsNonNoneKey(arguments, ASPECTS_ARG)) {
        Object obj = arguments.get(ASPECTS_ARG);
        SkylarkType.checkType(obj, SkylarkList.class, ASPECTS_ARG);
        List<SkylarkAspect> aspects = ((SkylarkList<?>) obj).getContents(SkylarkAspect.class, "aspects");
        for (SkylarkAspect aspect : aspects) {
            builder.aspect(aspect, ast.getLocation());
        }
    }
    return builder;
}
Also used : SkylarkCallbackFunction(com.google.devtools.build.lib.syntax.SkylarkCallbackFunction) UserDefinedFunction(com.google.devtools.build.lib.syntax.UserDefinedFunction) Attribute(com.google.devtools.build.lib.packages.Attribute) EvalException(com.google.devtools.build.lib.syntax.EvalException) SkylarkList(com.google.devtools.build.lib.syntax.SkylarkList) SplitTransition(com.google.devtools.build.lib.packages.Attribute.SplitTransition) ImmutableSet(com.google.common.collect.ImmutableSet) SkylarkAspect(com.google.devtools.build.lib.packages.SkylarkAspect) SkylarkComputedDefaultTemplate(com.google.devtools.build.lib.packages.Attribute.SkylarkComputedDefaultTemplate) AllowedValueSet(com.google.devtools.build.lib.packages.Attribute.AllowedValueSet)

Aggregations

SkylarkComputedDefaultTemplate (com.google.devtools.build.lib.packages.Attribute.SkylarkComputedDefaultTemplate)2 ImmutableSet (com.google.common.collect.ImmutableSet)1 Attribute (com.google.devtools.build.lib.packages.Attribute)1 AllowedValueSet (com.google.devtools.build.lib.packages.Attribute.AllowedValueSet)1 SplitTransition (com.google.devtools.build.lib.packages.Attribute.SplitTransition)1 SkylarkAspect (com.google.devtools.build.lib.packages.SkylarkAspect)1 EvalException (com.google.devtools.build.lib.syntax.EvalException)1 SkylarkCallbackFunction (com.google.devtools.build.lib.syntax.SkylarkCallbackFunction)1 SkylarkList (com.google.devtools.build.lib.syntax.SkylarkList)1 UserDefinedFunction (com.google.devtools.build.lib.syntax.UserDefinedFunction)1 ArrayList (java.util.ArrayList)1