Search in sources :

Example 51 with Attribute

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

the class BuildDocCollector method processAttributeDocs.

/**
   * Go through all attributes of all documented rules and search the best attribute documentation
   * if exists. The best documentation is the closest documentation in the ancestor graph. E.g. if
   * java_library.deps documented in $rule and $java_rule then the one in $java_rule is going to
   * apply since it's a closer ancestor of java_library.
   */
private void processAttributeDocs(Iterable<RuleDocumentation> ruleDocEntries, ListMultimap<String, RuleDocumentationAttribute> attributeDocEntries) throws BuildEncyclopediaDocException {
    for (RuleDocumentation ruleDoc : ruleDocEntries) {
        RuleClass ruleClass = ruleClassProvider.getRuleClassMap().get(ruleDoc.getRuleName());
        if (ruleClass != null) {
            if (ruleClass.isDocumented()) {
                Class<? extends RuleDefinition> ruleDefinition = ruleClassProvider.getRuleClassDefinition(ruleDoc.getRuleName()).getClass();
                for (Attribute attribute : ruleClass.getAttributes()) {
                    String attrName = attribute.getName();
                    List<RuleDocumentationAttribute> attributeDocList = attributeDocEntries.get(attrName);
                    if (attributeDocList != null) {
                        // There are attribute docs for this attribute.
                        // Search the closest one in the ancestor graph.
                        // Note that there can be only one 'closest' attribute since we forbid multiple
                        // inheritance of the same attribute in RuleClass.
                        int minLevel = Integer.MAX_VALUE;
                        RuleDocumentationAttribute bestAttributeDoc = null;
                        for (RuleDocumentationAttribute attributeDoc : attributeDocList) {
                            int level = attributeDoc.getDefinitionClassAncestryLevel(ruleDefinition, ruleClassProvider);
                            if (level >= 0 && level < minLevel) {
                                bestAttributeDoc = attributeDoc;
                                minLevel = level;
                            }
                        }
                        if (bestAttributeDoc != null) {
                            // Add reference to the Attribute that the attribute doc is associated with
                            // in order to generate documentation for the Attribute.
                            bestAttributeDoc.setAttribute(attribute);
                            ruleDoc.addAttribute(bestAttributeDoc);
                        // If there is no matching attribute doc try to add the common.
                        } else if (ruleDoc.getRuleType().equals(RuleType.BINARY) && PredefinedAttributes.BINARY_ATTRIBUTES.containsKey(attrName)) {
                            ruleDoc.addAttribute(PredefinedAttributes.BINARY_ATTRIBUTES.get(attrName));
                        } else if (ruleDoc.getRuleType().equals(RuleType.TEST) && PredefinedAttributes.TEST_ATTRIBUTES.containsKey(attrName)) {
                            ruleDoc.addAttribute(PredefinedAttributes.TEST_ATTRIBUTES.get(attrName));
                        } else if (PredefinedAttributes.COMMON_ATTRIBUTES.containsKey(attrName)) {
                            ruleDoc.addAttribute(PredefinedAttributes.COMMON_ATTRIBUTES.get(attrName));
                        }
                    }
                }
            }
        } else {
            throw ruleDoc.createException("Can't find RuleClass for " + ruleDoc.getRuleName());
        }
    }
}
Also used : Attribute(com.google.devtools.build.lib.packages.Attribute) RuleClass(com.google.devtools.build.lib.packages.RuleClass)

Example 52 with Attribute

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

the class SkylarkRuleContext method buildAttributesCollection.

private static SkylarkRuleAttributesCollection buildAttributesCollection(Collection<Attribute> attributes, RuleContext ruleContext, Function<Attribute, Object> attributeValueExtractor) {
    Builder<String, Object> attrBuilder = new Builder<>();
    Builder<String, Object> executableBuilder = new Builder<>();
    Builder<Artifact, FilesToRunProvider> executableRunfilesbuilder = new Builder<>();
    Builder<String, Object> fileBuilder = new Builder<>();
    Builder<String, Object> filesBuilder = new Builder<>();
    HashSet<Artifact> seenExecutables = new HashSet<>();
    for (Attribute a : attributes) {
        Type<?> type = a.getType();
        Object val = attributeValueExtractor.apply(a);
        // Skylark as a Map<String, Label>; this special case preserves that behavior temporarily.
        if (type.getLabelClass() != LabelClass.DEPENDENCY || type == BuildType.LABEL_DICT_UNARY) {
            attrBuilder.put(a.getPublicName(), val == null ? Runtime.NONE : // Attribute values should be type safe
            SkylarkType.convertToSkylark(val, null));
            continue;
        }
        String skyname = a.getPublicName();
        if (a.isExecutable()) {
            // In Skylark only label (not label list) type attributes can have the Executable flag.
            FilesToRunProvider provider = ruleContext.getExecutablePrerequisite(a.getName(), Mode.DONT_CHECK);
            if (provider != null && provider.getExecutable() != null) {
                Artifact executable = provider.getExecutable();
                executableBuilder.put(skyname, executable);
                if (!seenExecutables.contains(executable)) {
                    // todo(dslomov,laurentlb): In general, this is incorrect.
                    // We associate the first encountered FilesToRunProvider with
                    // the executable (this provider is later used to build the spawn).
                    // However ideally we should associate a provider with the attribute name,
                    // and pass the correct FilesToRunProvider to the spawn depending on
                    // what attribute is used to access the executable.
                    executableRunfilesbuilder.put(executable, provider);
                    seenExecutables.add(executable);
                }
            } else {
                executableBuilder.put(skyname, Runtime.NONE);
            }
        }
        if (a.isSingleArtifact()) {
            // In Skylark only label (not label list) type attributes can have the SingleArtifact flag.
            Artifact artifact = ruleContext.getPrerequisiteArtifact(a.getName(), Mode.DONT_CHECK);
            if (artifact != null) {
                fileBuilder.put(skyname, artifact);
            } else {
                fileBuilder.put(skyname, Runtime.NONE);
            }
        }
        filesBuilder.put(skyname, ruleContext.getPrerequisiteArtifacts(a.getName(), Mode.DONT_CHECK).list());
        if (type == BuildType.LABEL && !a.hasSplitConfigurationTransition()) {
            Object prereq = ruleContext.getPrerequisite(a.getName(), Mode.DONT_CHECK);
            if (prereq == null) {
                prereq = Runtime.NONE;
            }
            attrBuilder.put(skyname, prereq);
        } else if (type == BuildType.LABEL_LIST || (type == BuildType.LABEL && a.hasSplitConfigurationTransition())) {
            List<?> allPrereq = ruleContext.getPrerequisites(a.getName(), Mode.DONT_CHECK);
            attrBuilder.put(skyname, SkylarkList.createImmutable(allPrereq));
        } else if (type == BuildType.LABEL_KEYED_STRING_DICT) {
            ImmutableMap.Builder<TransitiveInfoCollection, String> builder = new ImmutableMap.Builder<>();
            Map<Label, String> original = BuildType.LABEL_KEYED_STRING_DICT.cast(val);
            List<? extends TransitiveInfoCollection> allPrereq = ruleContext.getPrerequisites(a.getName(), Mode.DONT_CHECK);
            for (TransitiveInfoCollection prereq : allPrereq) {
                builder.put(prereq, original.get(prereq.getLabel()));
            }
            attrBuilder.put(skyname, SkylarkType.convertToSkylark(builder.build(), null));
        } else if (type == BuildType.LABEL_DICT_UNARY) {
            Map<Label, TransitiveInfoCollection> prereqsByLabel = new LinkedHashMap<>();
            for (TransitiveInfoCollection target : ruleContext.getPrerequisites(a.getName(), Mode.DONT_CHECK)) {
                prereqsByLabel.put(target.getLabel(), target);
            }
            ImmutableMap.Builder<String, TransitiveInfoCollection> attrValue = new ImmutableMap.Builder<>();
            for (Map.Entry<String, Label> entry : ((Map<String, Label>) val).entrySet()) {
                attrValue.put(entry.getKey(), prereqsByLabel.get(entry.getValue()));
            }
            attrBuilder.put(skyname, attrValue.build());
        } else {
            throw new IllegalArgumentException("Can't transform attribute " + a.getName() + " of type " + type + " to a Skylark object");
        }
    }
    return new SkylarkRuleAttributesCollection(ruleContext.getRule().getRuleClass(), attrBuilder.build(), executableBuilder.build(), fileBuilder.build(), filesBuilder.build(), executableRunfilesbuilder.build());
}
Also used : FilesToRunProvider(com.google.devtools.build.lib.analysis.FilesToRunProvider) Attribute(com.google.devtools.build.lib.packages.Attribute) Builder(com.google.common.collect.ImmutableMap.Builder) Label(com.google.devtools.build.lib.cmdline.Label) Artifact(com.google.devtools.build.lib.actions.Artifact) ImmutableMap(com.google.common.collect.ImmutableMap) Entry(java.util.Map.Entry) SkylarkClassObject(com.google.devtools.build.lib.packages.SkylarkClassObject) List(java.util.List) SkylarkList(com.google.devtools.build.lib.syntax.SkylarkList) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) LinkedList(java.util.LinkedList) TransitiveInfoCollection(com.google.devtools.build.lib.analysis.TransitiveInfoCollection) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) HashSet(java.util.HashSet)

Example 53 with Attribute

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

the class SkylarkRuleContext method buildSplitAttributeInfo.

private static SkylarkClassObject buildSplitAttributeInfo(Collection<Attribute> attributes, RuleContext ruleContext) {
    ImmutableMap.Builder<String, Object> splitAttrInfos = ImmutableMap.builder();
    for (Attribute attr : attributes) {
        if (attr.hasSplitConfigurationTransition()) {
            Map<Optional<String>, ? extends List<? extends TransitiveInfoCollection>> splitPrereqs = ruleContext.getSplitPrerequisites(attr.getName());
            Map<Object, Object> splitPrereqsMap = new LinkedHashMap<>();
            for (Entry<Optional<String>, ? extends List<? extends TransitiveInfoCollection>> splitPrereq : splitPrereqs.entrySet()) {
                Object value;
                if (attr.getType() == BuildType.LABEL) {
                    Preconditions.checkState(splitPrereq.getValue().size() == 1);
                    value = splitPrereq.getValue().get(0);
                } else {
                    // BuildType.LABEL_LIST
                    value = SkylarkList.createImmutable(splitPrereq.getValue());
                }
                if (splitPrereq.getKey().isPresent()) {
                    splitPrereqsMap.put(splitPrereq.getKey().get(), value);
                } else {
                    // If the split transition is not in effect, then the key will be missing since there's
                    // nothing to key on because the dependencies aren't split and getSplitPrerequisites()
                    // behaves like getPrerequisites(). This also means there should be only one entry in
                    // the map. Use None in Skylark to represent this.
                    Preconditions.checkState(splitPrereqs.size() == 1);
                    splitPrereqsMap.put(Runtime.NONE, value);
                }
            }
            splitAttrInfos.put(attr.getPublicName(), SkylarkDict.copyOf(null, splitPrereqsMap));
        }
    }
    return NativeClassObjectConstructor.STRUCT.create(splitAttrInfos.build(), "No attribute '%s' in split_attr. Make sure that this attribute is defined with a " + "split configuration.");
}
Also used : Optional(com.google.common.base.Optional) Attribute(com.google.devtools.build.lib.packages.Attribute) SkylarkClassObject(com.google.devtools.build.lib.packages.SkylarkClassObject) ImmutableMap(com.google.common.collect.ImmutableMap) LinkedHashMap(java.util.LinkedHashMap)

Example 54 with Attribute

use of com.google.devtools.build.lib.packages.Attribute 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)

Example 55 with Attribute

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

the class PreciseAspectResolver method computeAspectDependencies.

@Override
public ImmutableMultimap<Attribute, Label> computeAspectDependencies(Target target, DependencyFilter dependencyFilter) throws InterruptedException {
    Multimap<Attribute, Label> result = LinkedListMultimap.create();
    if (target instanceof Rule) {
        Multimap<Attribute, Label> transitions = ((Rule) target).getTransitions(DependencyFilter.NO_NODEP_ATTRIBUTES);
        for (Entry<Attribute, Label> entry : transitions.entries()) {
            Target toTarget;
            try {
                toTarget = packageProvider.getTarget(eventHandler, entry.getValue());
                result.putAll(AspectDefinition.visitAspectsIfRequired(target, entry.getKey(), toTarget, dependencyFilter));
            } catch (NoSuchThingException e) {
            // Do nothing. One of target direct deps has an error. The dependency on the BUILD file
            // (or one of the files included in it) will be reported in the query result of :BUILD.
            }
        }
    }
    return ImmutableMultimap.copyOf(result);
}
Also used : Target(com.google.devtools.build.lib.packages.Target) NoSuchThingException(com.google.devtools.build.lib.packages.NoSuchThingException) Attribute(com.google.devtools.build.lib.packages.Attribute) Label(com.google.devtools.build.lib.cmdline.Label) Rule(com.google.devtools.build.lib.packages.Rule)

Aggregations

Attribute (com.google.devtools.build.lib.packages.Attribute)76 Test (org.junit.Test)37 Label (com.google.devtools.build.lib.cmdline.Label)20 Rule (com.google.devtools.build.lib.packages.Rule)20 BuildConfiguration (com.google.devtools.build.lib.analysis.config.BuildConfiguration)7 AttributeMap (com.google.devtools.build.lib.packages.AttributeMap)7 Target (com.google.devtools.build.lib.packages.Target)7 ArrayList (java.util.ArrayList)7 LinkedHashMap (java.util.LinkedHashMap)7 ImmutableList (com.google.common.collect.ImmutableList)6 ImmutableMap (com.google.common.collect.ImmutableMap)6 ConfiguredTarget (com.google.devtools.build.lib.analysis.ConfiguredTarget)6 ConfigMatchingProvider (com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider)6 RuleClass (com.google.devtools.build.lib.packages.RuleClass)6 SkyKey (com.google.devtools.build.skyframe.SkyKey)6 LinkedHashSet (java.util.LinkedHashSet)6 Nullable (javax.annotation.Nullable)6 AspectDescriptor (com.google.devtools.build.lib.packages.AspectDescriptor)5 Map (java.util.Map)5 Dependency (com.google.devtools.build.lib.analysis.Dependency)4