Skip to content

Commit 5c7a159

Browse files
zhengwei143copybara-github
authored andcommitted
Add source_aspect_name to the Attribute message that indicates the source aspect that the attribute comes from (empty if not from an aspect) when used with query --output=proto --proto:include_attribute_source_aspects.
RELNOTES[INC]: Duplicates in <rule-inputs> when using `query --output=xml --aspect_deps=precise` are removed. Added flag `--proto:include_attribute_source_aspects` that will include a new field `source_aspect_name` to the `Attribute` message that indicates the source aspect that the attribute comes from. PiperOrigin-RevId: 534347046 Change-Id: I4fdac6b5ef8887ffd36f1a64508fd97bc9d70bff
1 parent 6584fea commit 5c7a159

File tree

12 files changed

+223
-77
lines changed

12 files changed

+223
-77
lines changed

src/main/java/com/google/devtools/build/lib/packages/AttributeFormatter.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,15 +92,36 @@ public static Build.Attribute getAttributeProto(
9292
attr.getType(),
9393
value,
9494
explicitlySpecified,
95-
encodeBooleanAndTriStateAsIntegerAndString);
95+
encodeBooleanAndTriStateAsIntegerAndString,
96+
/* sourceAspect= */ null,
97+
/* includeAttributeSourceAspects */ false);
98+
}
99+
100+
public static Build.Attribute getAttributeProto(
101+
Attribute attr,
102+
@Nullable Object value,
103+
boolean explicitlySpecified,
104+
boolean encodeBooleanAndTriStateAsIntegerAndString,
105+
@Nullable Aspect sourceAspect,
106+
boolean includeAttributeSourceAspects) {
107+
return getAttributeProto(
108+
attr.getName(),
109+
attr.getType(),
110+
value,
111+
explicitlySpecified,
112+
encodeBooleanAndTriStateAsIntegerAndString,
113+
sourceAspect,
114+
includeAttributeSourceAspects);
96115
}
97116

98117
private static Build.Attribute getAttributeProto(
99118
String name,
100119
Type<?> type,
101120
@Nullable Object value,
102121
boolean explicitlySpecified,
103-
boolean encodeBooleanAndTriStateAsIntegerAndString) {
122+
boolean encodeBooleanAndTriStateAsIntegerAndString,
123+
@Nullable Aspect sourceAspect,
124+
boolean includeAttributeSourceAspects) {
104125
Build.Attribute.Builder attrPb = Build.Attribute.newBuilder();
105126
attrPb.setName(name);
106127
attrPb.setExplicitlySpecified(explicitlySpecified);
@@ -118,6 +139,11 @@ private static Build.Attribute getAttributeProto(
118139
}
119140
}
120141

142+
if (includeAttributeSourceAspects) {
143+
attrPb.setSourceAspectName(
144+
sourceAspect != null ? sourceAspect.getAspectClass().getName() : "");
145+
}
146+
121147
return attrPb.build();
122148
}
123149

src/main/java/com/google/devtools/build/lib/query2/common/CommonQueryOptions.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,16 @@ public Set<Setting> toSettings() {
276276
+ "Starlark call stack at the moment the rule's class was defined.")
277277
public boolean protoIncludeDefinitionStack;
278278

279+
@Option(
280+
name = "proto:include_attribute_source_aspects",
281+
defaultValue = "false",
282+
documentationCategory = OptionDocumentationCategory.QUERY,
283+
effectTags = {OptionEffectTag.TERMINAL_OUTPUT},
284+
help =
285+
"Populate the source_aspect_name proto field of each Attribute with the source aspect "
286+
+ "that the attribute came from (empty string if it did not).")
287+
public boolean protoIncludeAttributeSourceAspects;
288+
279289
/** An enum converter for {@code AspectResolver.Mode} . Should be used internally only. */
280290
public static class AspectResolutionModeConverter extends EnumConverter<Mode> {
281291
public AspectResolutionModeConverter() {

src/main/java/com/google/devtools/build/lib/query2/cquery/ProtoOutputFormatterCallback.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,9 @@ protected void addAttributes(
294294
attr,
295295
attributeValue,
296296
rule.isAttributeValueExplicitlySpecified(attr),
297-
/*encodeBooleanAndTriStateAsIntegerAndString=*/ true);
297+
/* encodeBooleanAndTriStateAsIntegerAndString= */ true,
298+
/* sourceAspect= */ null,
299+
includeAttributeSourceAspects);
298300
rulePb.addAttribute(serializedAttribute);
299301
}
300302
}

src/main/java/com/google/devtools/build/lib/query2/query/aspectresolvers/AspectResolver.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313
// limitations under the License.
1414
package com.google.devtools.build.lib.query2.query.aspectresolvers;
1515

16+
import com.google.common.collect.ImmutableMap;
1617
import com.google.common.collect.ImmutableMultimap;
1718
import com.google.devtools.build.lib.cmdline.Label;
1819
import com.google.devtools.build.lib.events.ExtendedEventHandler;
20+
import com.google.devtools.build.lib.packages.Aspect;
1921
import com.google.devtools.build.lib.packages.Attribute;
2022
import com.google.devtools.build.lib.packages.DependencyFilter;
2123
import com.google.devtools.build.lib.packages.Package;
@@ -62,11 +64,11 @@ public abstract AspectResolver createResolver(
6264
}
6365

6466
/**
65-
* Compute additional dependencies of target from aspects. This method may load the direct deps
66-
* of target to determine their types. Returns map of attributes and corresponding label values.
67+
* Compute additional dependencies of target from aspects. This method may load the direct deps of
68+
* target to determine their types. Returns map of attributes and corresponding label values.
6769
*/
68-
ImmutableMultimap<Attribute, Label> computeAspectDependencies(Target target,
69-
DependencyFilter dependencyFilter) throws InterruptedException;
70+
ImmutableMap<Aspect, ImmutableMultimap<Attribute, Label>> computeAspectDependencies(
71+
Target target, DependencyFilter dependencyFilter) throws InterruptedException;
7072

7173
/**
7274
* Compute the labels of the BUILD Starlark files on which the results of the other two methods

src/main/java/com/google/devtools/build/lib/query2/query/aspectresolvers/ConservativeAspectResolver.java

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
package com.google.devtools.build.lib.query2.query.aspectresolvers;
1515

1616
import com.google.common.collect.ImmutableList;
17+
import com.google.common.collect.ImmutableMap;
1718
import com.google.common.collect.ImmutableMultimap;
18-
import com.google.common.collect.LinkedHashMultimap;
19-
import com.google.common.collect.Multimap;
19+
import com.google.common.collect.ImmutableSetMultimap;
2020
import com.google.devtools.build.lib.cmdline.Label;
2121
import com.google.devtools.build.lib.packages.Aspect;
2222
import com.google.devtools.build.lib.packages.AspectDefinition;
@@ -25,6 +25,7 @@
2525
import com.google.devtools.build.lib.packages.Package;
2626
import com.google.devtools.build.lib.packages.Rule;
2727
import com.google.devtools.build.lib.packages.Target;
28+
import java.util.LinkedHashMap;
2829

2930
/**
3031
* An aspect resolver that overestimates the required aspect dependencies.
@@ -33,24 +34,32 @@
3334
*/
3435
public class ConservativeAspectResolver implements AspectResolver {
3536
@Override
36-
public ImmutableMultimap<Attribute, Label> computeAspectDependencies(
37+
public ImmutableMap<Aspect, ImmutableMultimap<Attribute, Label>> computeAspectDependencies(
3738
Target target, DependencyFilter dependencyFilter) {
3839
if (!(target instanceof Rule)) {
39-
return ImmutableMultimap.of();
40+
return ImmutableMap.of();
4041
}
4142
Rule rule = (Rule) target;
4243
if (!rule.hasAspects()) {
43-
return ImmutableMultimap.of();
44+
return ImmutableMap.of();
4445
}
4546

46-
Multimap<Attribute, Label> result = LinkedHashMultimap.create();
47+
LinkedHashMap<Aspect, ImmutableMultimap<Attribute, Label>> results = new LinkedHashMap<>();
48+
4749
for (Attribute attribute : rule.getAttributes()) {
4850
for (Aspect aspect : attribute.getAspects(rule)) {
49-
AspectDefinition.addAllAttributesOfAspect(result, aspect, dependencyFilter);
51+
ImmutableSetMultimap.Builder<Attribute, Label> attributeLabelsBuilder =
52+
ImmutableSetMultimap.builder();
53+
AspectDefinition.forEachLabelDepFromAllAttributesOfAspect(
54+
aspect, dependencyFilter, attributeLabelsBuilder::put);
55+
ImmutableSetMultimap<Attribute, Label> attributeLabels = attributeLabelsBuilder.build();
56+
if (!attributeLabels.isEmpty()) {
57+
results.put(aspect, attributeLabels);
58+
}
5059
}
5160
}
5261

53-
return ImmutableMultimap.copyOf(result);
62+
return ImmutableMap.copyOf(results);
5463
}
5564

5665
@Override

src/main/java/com/google/devtools/build/lib/query2/query/aspectresolvers/NullAspectResolver.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
package com.google.devtools.build.lib.query2.query.aspectresolvers;
1515

1616
import com.google.common.collect.ImmutableList;
17+
import com.google.common.collect.ImmutableMap;
1718
import com.google.common.collect.ImmutableMultimap;
1819
import com.google.devtools.build.lib.cmdline.Label;
20+
import com.google.devtools.build.lib.packages.Aspect;
1921
import com.google.devtools.build.lib.packages.Attribute;
2022
import com.google.devtools.build.lib.packages.DependencyFilter;
2123
import com.google.devtools.build.lib.packages.Package;
@@ -28,9 +30,9 @@
2830
*/
2931
public class NullAspectResolver implements AspectResolver {
3032
@Override
31-
public ImmutableMultimap<Attribute, Label> computeAspectDependencies(
33+
public ImmutableMap<Aspect, ImmutableMultimap<Attribute, Label>> computeAspectDependencies(
3234
Target target, DependencyFilter dependencyFilter) {
33-
return ImmutableMultimap.of();
35+
return ImmutableMap.of();
3436
}
3537

3638
@Override

src/main/java/com/google/devtools/build/lib/query2/query/aspectresolvers/PreciseAspectResolver.java

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
// limitations under the License.
1414
package com.google.devtools.build.lib.query2.query.aspectresolvers;
1515

16+
import com.google.common.collect.ImmutableMap;
1617
import com.google.common.collect.ImmutableMultimap;
17-
import com.google.common.collect.LinkedListMultimap;
18+
import com.google.common.collect.ImmutableSetMultimap;
1819
import com.google.common.collect.Multimap;
1920
import com.google.devtools.build.lib.cmdline.Label;
2021
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
@@ -30,6 +31,7 @@
3031
import com.google.devtools.build.lib.packages.Rule;
3132
import com.google.devtools.build.lib.packages.Target;
3233
import com.google.devtools.build.lib.pkgcache.PackageProvider;
34+
import java.util.LinkedHashMap;
3335
import java.util.LinkedHashSet;
3436
import java.util.Set;
3537

@@ -49,27 +51,34 @@ public PreciseAspectResolver(PackageProvider packageProvider, ExtendedEventHandl
4951
}
5052

5153
@Override
52-
public ImmutableMultimap<Attribute, Label> computeAspectDependencies(
54+
public ImmutableMap<Aspect, ImmutableMultimap<Attribute, Label>> computeAspectDependencies(
5355
Target target, DependencyFilter dependencyFilter) throws InterruptedException {
5456
if (!(target instanceof Rule)) {
55-
return ImmutableMultimap.of();
57+
return ImmutableMap.of();
5658
}
5759
Rule rule = (Rule) target;
5860
if (!rule.hasAspects()) {
59-
return ImmutableMultimap.of();
61+
return ImmutableMap.of();
6062
}
61-
Multimap<Attribute, Label> result = LinkedListMultimap.create();
63+
64+
LinkedHashMap<Aspect, ImmutableMultimap<Attribute, Label>> results = new LinkedHashMap<>();
6265
Multimap<Attribute, Label> transitions =
6366
rule.getTransitions(DependencyFilter.NO_NODEP_ATTRIBUTES);
6467
for (Attribute attribute : transitions.keySet()) {
6568
for (Aspect aspect : attribute.getAspects(rule)) {
6669
if (hasDepThatSatisfies(aspect, transitions.get(attribute))) {
70+
ImmutableSetMultimap.Builder<Attribute, Label> attributeLabelsBuilder =
71+
ImmutableSetMultimap.builder();
6772
AspectDefinition.forEachLabelDepFromAllAttributesOfAspect(
68-
aspect, dependencyFilter, result::put);
73+
aspect, dependencyFilter, attributeLabelsBuilder::put);
74+
ImmutableSetMultimap<Attribute, Label> attributeLabels = attributeLabelsBuilder.build();
75+
if (!attributeLabels.isEmpty()) {
76+
results.put(aspect, attributeLabels);
77+
}
6978
}
7079
}
7180
}
72-
return ImmutableMultimap.copyOf(result);
81+
return ImmutableMap.copyOf(results);
7382
}
7483

7584
private boolean hasDepThatSatisfies(Aspect aspect, Iterable<Label> labelDeps)

src/main/java/com/google/devtools/build/lib/query2/query/output/ProtoOutputFormatter.java

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import com.google.devtools.build.lib.events.Event;
3636
import com.google.devtools.build.lib.events.EventHandler;
3737
import com.google.devtools.build.lib.packages.AggregatingAttributeMapper;
38+
import com.google.devtools.build.lib.packages.Aspect;
3839
import com.google.devtools.build.lib.packages.Attribute;
3940
import com.google.devtools.build.lib.packages.AttributeFormatter;
4041
import com.google.devtools.build.lib.packages.BuildType;
@@ -109,6 +110,7 @@ public class ProtoOutputFormatter extends AbstractUnorderedFormatter {
109110
private boolean includeSyntheticAttributeHash = false;
110111
private boolean includeInstantiationStack = false;
111112
private boolean includeDefinitionStack = false;
113+
protected boolean includeAttributeSourceAspects = false;
112114
private HashFunction hashFunction = null;
113115

114116
@Nullable private EventHandler eventHandler;
@@ -135,6 +137,7 @@ public void setOptions(
135137
this.includeSyntheticAttributeHash = options.protoIncludeSyntheticAttributeHash;
136138
this.includeInstantiationStack = options.protoIncludeInstantiationStack;
137139
this.includeDefinitionStack = options.protoIncludeDefinitionStack;
140+
this.includeAttributeSourceAspects = options.protoIncludeAttributeSourceAspects;
138141
this.hashFunction = hashFunction;
139142
}
140143

@@ -198,34 +201,42 @@ public Build.Target toTargetProtoBuffer(Target target, Object extraDataForAttrHa
198201
BaseEncoding.base16().lowerCase().encode(transitiveDigest))); // hexify
199202
}
200203

201-
ImmutableMultimap<Attribute, Label> aspectsDependencies =
204+
ImmutableMap<Aspect, ImmutableMultimap<Attribute, Label>> aspectsDependencies =
202205
aspectResolver.computeAspectDependencies(target, dependencyFilter);
203206
if (!aspectsDependencies.isEmpty()) {
204207
// Add information about additional attributes from aspects.
205-
List<Build.Attribute> attributes = new ArrayList<>(aspectsDependencies.asMap().size());
206-
for (Map.Entry<Attribute, Collection<Label>> entry :
207-
aspectsDependencies.asMap().entrySet()) {
208-
Attribute attribute = entry.getKey();
209-
Collection<Label> labels = entry.getValue();
210-
if (!includeAspectAttribute(attribute, labels)) {
211-
continue;
208+
List<Build.Attribute> attributes = new ArrayList<>();
209+
for (Map.Entry<Aspect, ImmutableMultimap<Attribute, Label>> aspectAttributes :
210+
aspectsDependencies.entrySet()) {
211+
Aspect aspect = aspectAttributes.getKey();
212+
for (Map.Entry<Attribute, Collection<Label>> entry :
213+
aspectAttributes.getValue().asMap().entrySet()) {
214+
Attribute attribute = entry.getKey();
215+
Collection<Label> labels = entry.getValue();
216+
if (!includeAspectAttribute(attribute, labels)) {
217+
continue;
218+
}
219+
Object attributeValue = getAspectAttributeValue(target, attribute, labels);
220+
Build.Attribute serializedAttribute =
221+
AttributeFormatter.getAttributeProto(
222+
attribute,
223+
attributeValue,
224+
/* explicitlySpecified= */ false,
225+
/* encodeBooleanAndTriStateAsIntegerAndString= */ true,
226+
/* sourceAspect= */ aspect,
227+
includeAttributeSourceAspects);
228+
attributes.add(serializedAttribute);
212229
}
213-
Object attributeValue = getAspectAttributeValue(target, attribute, labels);
214-
Build.Attribute serializedAttribute =
215-
AttributeFormatter.getAttributeProto(
216-
attribute,
217-
attributeValue,
218-
/*explicitlySpecified=*/ false,
219-
/*encodeBooleanAndTriStateAsIntegerAndString=*/ true);
220-
attributes.add(serializedAttribute);
221230
}
231+
222232
rulePb.addAllAttribute(
223233
attributes.stream().distinct().sorted(ATTRIBUTE_NAME).collect(Collectors.toList()));
224234
}
225235
if (includeRuleInputsAndOutputs) {
226236
// Add all deps from aspects as rule inputs of current target.
227237
if (!aspectsDependencies.isEmpty()) {
228238
aspectsDependencies.values().stream()
239+
.flatMap(m -> m.values().stream())
229240
.distinct()
230241
.forEach(dep -> rulePb.addRuleInput(dep.toString()));
231242
}
@@ -374,7 +385,9 @@ protected void addAttributes(Build.Rule.Builder rulePb, Rule rule, Object extraD
374385
attr,
375386
attributeValue,
376387
rule.isAttributeValueExplicitlySpecified(attr),
377-
/*encodeBooleanAndTriStateAsIntegerAndString=*/ true);
388+
/* encodeBooleanAndTriStateAsIntegerAndString= */ true,
389+
/* sourceAspect= */ null,
390+
includeAttributeSourceAspects);
378391
serializedAttributes.put(attr, serializedAttribute);
379392
}
380393
rulePb.addAllAttribute(
@@ -389,7 +402,11 @@ protected void addAttributes(Build.Rule.Builder rulePb, Rule rule, Object extraD
389402
.setName("$internal_attr_hash")
390403
.setStringValue(
391404
SyntheticAttributeHashCalculator.compute(
392-
rule, serializedAttributes, extraDataForAttrHash, hashFunction))
405+
rule,
406+
serializedAttributes,
407+
extraDataForAttrHash,
408+
hashFunction,
409+
includeAttributeSourceAspects))
393410
.setType(Discriminator.STRING));
394411
}
395412
}

src/main/java/com/google/devtools/build/lib/query2/query/output/SyntheticAttributeHashCalculator.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ static String compute(
5656
Rule rule,
5757
Map<Attribute, Build.Attribute> serializedAttributes,
5858
Object extraDataForAttrHash,
59-
HashFunction hashFunction) {
59+
HashFunction hashFunction,
60+
boolean includeAttributeSourceAspects) {
6061
HashingOutputStream hashingOutputStream =
6162
new HashingOutputStream(hashFunction, ByteStreams.nullOutputStream());
6263
CodedOutputStream codedOut = CodedOutputStream.newInstance(hashingOutputStream);
@@ -118,7 +119,9 @@ static String compute(
118119
attr,
119120
valueToHash,
120121
/* explicitlySpecified= */ false, // We care about value, not how it was set.
121-
/*encodeBooleanAndTriStateAsIntegerAndString=*/ false);
122+
/* encodeBooleanAndTriStateAsIntegerAndString= */ false,
123+
/* sourceAspect= */ null,
124+
includeAttributeSourceAspects);
122125
} else {
123126
attrPb = serializedAttributes.get(attr);
124127
}

0 commit comments

Comments
 (0)