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());
}
}
}
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());
}
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.");
}
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;
}
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);
}
Aggregations