blob: 18c00f91565cb2ffd7e7b8a4f15f892fa28815cd [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2014 The Bazel Authors. All rights reserved.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package com.google.devtools.build.lib.analysis;
16
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +000017import static com.google.devtools.build.lib.analysis.ExtraActionUtils.createExtraActionProvider;
18
Dmitry Lomov2473b9f2015-09-14 08:53:10 +000019import com.google.common.annotations.VisibleForTesting;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010020import com.google.common.collect.ImmutableMap;
Carmi Grushko4076e442016-01-21 20:05:42 +000021import com.google.common.collect.ImmutableSet;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010022import com.google.common.collect.UnmodifiableIterator;
Rumou Duan33bab462016-04-25 17:55:12 +000023import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
Dmitry Lomove2033b12015-08-19 16:57:49 +000024import com.google.devtools.build.lib.actions.Artifact;
25import com.google.devtools.build.lib.collect.nestedset.NestedSet;
26import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010027import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
Dmitry Lomov0b832ce2015-10-20 10:03:14 +000028import com.google.devtools.build.lib.events.Location;
Dmitry Lomovdce01702016-11-28 15:51:32 +000029import com.google.devtools.build.lib.packages.AspectClass;
Dmitry Lomov15756522016-12-16 16:52:37 +000030import com.google.devtools.build.lib.packages.AspectDescriptor;
Dmitry Lomovdce01702016-11-28 15:51:32 +000031import com.google.devtools.build.lib.packages.AspectParameters;
Dmitry Lomov654717f2017-03-02 14:39:52 +000032import com.google.devtools.build.lib.packages.ClassObjectConstructor;
dslomovf9697342017-05-02 16:26:39 +020033import com.google.devtools.build.lib.packages.ClassObjectConstructor.Key;
Dmitry Lomov37a1c1c2016-09-01 09:11:02 +000034import com.google.devtools.build.lib.packages.SkylarkClassObject;
Vladimir Moskva6c28fe92017-03-03 12:55:08 +000035import com.google.devtools.build.lib.packages.SkylarkClassObjectConstructor;
Dmitry Lomov2aa1a982015-10-20 12:18:36 +000036import com.google.devtools.build.lib.syntax.EvalException;
Mark Schaller6df81792015-12-10 18:47:47 +000037import com.google.devtools.build.lib.util.Preconditions;
Googler94d35de2016-09-16 15:21:39 +000038import java.util.Arrays;
dslomovf9697342017-05-02 16:26:39 +020039import java.util.LinkedHashMap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010040import java.util.Map;
Dmitry Lomove2033b12015-08-19 16:57:49 +000041import java.util.TreeMap;
Dmitry Lomove2033b12015-08-19 16:57:49 +000042import javax.annotation.Nullable;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010043
44/**
45 * Extra information about a configured target computed on request of a dependent.
46 *
47 * <p>Analogous to {@link ConfiguredTarget}: contains a bunch of transitive info providers, which
48 * are merged with the providers of the associated configured target before they are passed to
49 * the configured target factories that depend on the configured target to which this aspect is
50 * added.
51 *
52 * <p>Aspects are created alongside configured targets on request from dependents.
Lukacs Berki2300cd62016-05-19 11:06:37 +000053 *
54 * <p>For more information about aspects, see
55 * {@link com.google.devtools.build.lib.packages.AspectClass}.
56 *
57 * @see com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory
58 * @see com.google.devtools.build.lib.packages.AspectClass
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010059 */
60@Immutable
Dmitry Lomovb487ac62015-11-09 13:09:12 +000061public final class ConfiguredAspect implements Iterable<TransitiveInfoProvider> {
Googler94d35de2016-09-16 15:21:39 +000062 private final TransitiveInfoProviderMap providers;
Dmitry Lomovdce01702016-11-28 15:51:32 +000063 private final AspectDescriptor descriptor;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010064
Dmitry Lomovdce01702016-11-28 15:51:32 +000065 private ConfiguredAspect(AspectDescriptor descriptor, TransitiveInfoProviderMap providers) {
66 this.descriptor = descriptor;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010067 this.providers = providers;
68 }
69
70 /**
Dmitry Lomove2033b12015-08-19 16:57:49 +000071 * Returns the aspect name.
72 */
73 public String getName() {
Dmitry Lomovdce01702016-11-28 15:51:32 +000074 return descriptor.getAspectClass().getName();
75 }
76
77 /**
78 * The aspect descriptor originating this ConfiguredAspect.
79 */
80 public AspectDescriptor getDescriptor() {
81 return descriptor;
Dmitry Lomove2033b12015-08-19 16:57:49 +000082 }
83
Googler94d35de2016-09-16 15:21:39 +000084 /** Returns the providers created by the aspect. */
85 public TransitiveInfoProviderMap getProviders() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010086 return providers;
87 }
88
Dmitry Lomove2033b12015-08-19 16:57:49 +000089 @Nullable
Dmitry Lomov2473b9f2015-09-14 08:53:10 +000090 @VisibleForTesting
91 public <P extends TransitiveInfoProvider> P getProvider(Class<P> providerClass) {
Googler94d35de2016-09-16 15:21:39 +000092 return providers.getProvider(providerClass);
Dmitry Lomove2033b12015-08-19 16:57:49 +000093 }
94
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010095 @Override
96 public UnmodifiableIterator<TransitiveInfoProvider> iterator() {
97 return providers.values().iterator();
98 }
99
Lukacs Berki549bfce2016-04-22 15:29:12 +0000100 public static ConfiguredAspect forAlias(ConfiguredAspect real) {
Dmitry Lomovdce01702016-11-28 15:51:32 +0000101 return new ConfiguredAspect(real.descriptor, real.getProviders());
Lukacs Berki549bfce2016-04-22 15:29:12 +0000102 }
103
Dmitry Lomov6cd98972017-03-01 15:44:00 +0000104 public static ConfiguredAspect forNonapplicableTarget(AspectDescriptor descriptor) {
105 return new ConfiguredAspect(descriptor, TransitiveInfoProviderMap.of());
106 }
107
dslomov99ea6b42017-04-25 17:46:17 +0200108 public static Builder builder(
109 AspectClass aspectClass, AspectParameters parameters, RuleContext ruleContext) {
110 return new Builder(aspectClass, parameters, ruleContext);
111 }
112
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100113 /**
Dmitry Lomovb487ac62015-11-09 13:09:12 +0000114 * Builder for {@link ConfiguredAspect}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100115 */
116 public static class Builder {
Googler94d35de2016-09-16 15:21:39 +0000117 private final TransitiveInfoProviderMap.Builder providers = TransitiveInfoProviderMap.builder();
Dmitry Lomove2033b12015-08-19 16:57:49 +0000118 private final Map<String, NestedSetBuilder<Artifact>> outputGroupBuilders = new TreeMap<>();
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000119 private final ImmutableMap.Builder<String, Object> skylarkProviderBuilder =
120 ImmutableMap.builder();
dslomovf9697342017-05-02 16:26:39 +0200121 private final LinkedHashMap<Key, SkylarkClassObject>
122 skylarkDeclaredProvidersBuilder = new LinkedHashMap<>();
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000123 private final RuleContext ruleContext;
Dmitry Lomovdce01702016-11-28 15:51:32 +0000124 private final AspectDescriptor descriptor;
Dmitry Lomove2033b12015-08-19 16:57:49 +0000125
Dmitry Lomovdce01702016-11-28 15:51:32 +0000126 public Builder(
127 AspectClass aspectClass,
128 AspectParameters parameters,
129 RuleContext context) {
130 this(new AspectDescriptor(aspectClass, parameters), context);
131 }
132
133 public Builder(AspectDescriptor descriptor, RuleContext ruleContext) {
134 this.descriptor = descriptor;
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000135 this.ruleContext = ruleContext;
Dmitry Lomove2033b12015-08-19 16:57:49 +0000136 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100137
Googler94d35de2016-09-16 15:21:39 +0000138 public <T extends TransitiveInfoProvider> Builder addProvider(
139 Class<? extends T> providerClass, T provider) {
140 Preconditions.checkNotNull(provider);
141 checkProviderClass(providerClass);
142 providers.put(providerClass, provider);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100143 return this;
144 }
145
Googler94d35de2016-09-16 15:21:39 +0000146 /** Adds a provider to the aspect. */
147 public Builder addProvider(TransitiveInfoProvider provider) {
148 Preconditions.checkNotNull(provider);
149 addProvider(TransitiveInfoProviderMap.getEffectiveProviderClass(provider), provider);
150 return this;
151 }
152
153 private void checkProviderClass(Class<? extends TransitiveInfoProvider> providerClass) {
154 Preconditions.checkNotNull(providerClass);
155 Preconditions.checkArgument(
156 !SkylarkProviders.class.equals(providerClass),
157 "Do not provide SkylarkProviders directly");
158 }
159
160 /** Adds providers to the aspect. */
161 public Builder addProviders(TransitiveInfoProviderMap providers) {
162 for (Map.Entry<Class<? extends TransitiveInfoProvider>, TransitiveInfoProvider> entry :
Carmi Grushko261f5bb2015-12-09 19:38:38 +0000163 providers.entrySet()) {
Googler94d35de2016-09-16 15:21:39 +0000164 addProvider(entry.getKey(), entry.getKey().cast(entry.getValue()));
165 }
166 return this;
167 }
168
169 /** Adds providers to the aspect. */
170 public Builder addProviders(TransitiveInfoProvider... providers) {
171 return addProviders(Arrays.asList(providers));
172 }
173
174 /** Adds providers to the aspect. */
175 public Builder addProviders(Iterable<TransitiveInfoProvider> providers) {
176 for (TransitiveInfoProvider provider : providers) {
177 addProvider(provider);
Carmi Grushkob8f0e862015-11-23 23:26:15 +0000178 }
179 return this;
180 }
181
Carmi Grushko65ac3552015-08-21 16:43:26 +0000182 /**
Dmitry Lomove2033b12015-08-19 16:57:49 +0000183 * Adds a set of files to an output group.
184 */
185 public Builder addOutputGroup(String name, NestedSet<Artifact> artifacts) {
186 NestedSetBuilder<Artifact> nestedSetBuilder = outputGroupBuilders.get(name);
187 if (nestedSetBuilder == null) {
188 nestedSetBuilder = NestedSetBuilder.<Artifact>stableOrder();
189 outputGroupBuilders.put(name, nestedSetBuilder);
190 }
191 nestedSetBuilder.addTransitive(artifacts);
192 return this;
193 }
194
Googler63ce8f22017-01-09 15:32:16 +0000195 public Builder addSkylarkTransitiveInfo(String name, Object value) {
Googler63ce8f22017-01-09 15:32:16 +0000196 skylarkProviderBuilder.put(name, value);
197 return this;
198 }
199
Dmitry Lomov2aa1a982015-10-20 12:18:36 +0000200 public Builder addSkylarkTransitiveInfo(String name, Object value, Location loc)
201 throws EvalException {
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000202 skylarkProviderBuilder.put(name, value);
203 return this;
204 }
205
Vladimir Moskva6c28fe92017-03-03 12:55:08 +0000206 public Builder addSkylarkDeclaredProvider(SkylarkClassObject declaredProvider, Location loc)
207 throws EvalException {
208 ClassObjectConstructor constructor = declaredProvider.getConstructor();
Vladimir Moskva6c28fe92017-03-03 12:55:08 +0000209 if (!constructor.isExported()) {
210 throw new EvalException(
211 constructor.getLocation(), "All providers must be top level values");
212 }
213 skylarkDeclaredProvidersBuilder.put(constructor.getKey(), declaredProvider);
214 return this;
215 }
216
dslomovf9697342017-05-02 16:26:39 +0200217 public Builder addNativeDeclaredProvider(SkylarkClassObject declaredProvider) {
218 ClassObjectConstructor constructor = declaredProvider.getConstructor();
219 Preconditions.checkState(constructor.isExported());
220 skylarkDeclaredProvidersBuilder.put(constructor.getKey(), declaredProvider);
221 return this;
222 }
223
224
Dmitry Lomovb487ac62015-11-09 13:09:12 +0000225 public ConfiguredAspect build() {
Dmitry Lomove2033b12015-08-19 16:57:49 +0000226 if (!outputGroupBuilders.isEmpty()) {
227 ImmutableMap.Builder<String, NestedSet<Artifact>> outputGroups = ImmutableMap.builder();
228 for (Map.Entry<String, NestedSetBuilder<Artifact>> entry : outputGroupBuilders.entrySet()) {
229 outputGroups.put(entry.getKey(), entry.getValue().build());
230 }
231
dslomovf9697342017-05-02 16:26:39 +0200232 if (skylarkDeclaredProvidersBuilder.containsKey(
233 OutputGroupProvider.SKYLARK_CONSTRUCTOR.getKey())) {
Dmitry Lomove2033b12015-08-19 16:57:49 +0000234 throw new IllegalStateException(
235 "OutputGroupProvider was provided explicitly; do not use addOutputGroup");
236 }
dslomovf9697342017-05-02 16:26:39 +0200237 skylarkDeclaredProvidersBuilder.put(
238 OutputGroupProvider.SKYLARK_CONSTRUCTOR.getKey(),
239 new OutputGroupProvider(outputGroups.build()));
Dmitry Lomove2033b12015-08-19 16:57:49 +0000240 }
241
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000242 ImmutableMap<String, Object> skylarkProvidersMap = skylarkProviderBuilder.build();
Vladimir Moskva6c28fe92017-03-03 12:55:08 +0000243 ImmutableMap<SkylarkClassObjectConstructor.Key, SkylarkClassObject>
dslomovf9697342017-05-02 16:26:39 +0200244 skylarkDeclaredProvidersMap = ImmutableMap.copyOf(skylarkDeclaredProvidersBuilder);
Vladimir Moskva6c28fe92017-03-03 12:55:08 +0000245 if (!skylarkProvidersMap.isEmpty() || !skylarkDeclaredProvidersMap.isEmpty()) {
246 providers.add(new SkylarkProviders(skylarkProvidersMap, skylarkDeclaredProvidersMap));
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000247 }
248
Carmi Grushko4076e442016-01-21 20:05:42 +0000249 addProvider(
Carmi Grushko4076e442016-01-21 20:05:42 +0000250 createExtraActionProvider(
Rumou Duan33bab462016-04-25 17:55:12 +0000251 ImmutableSet.<ActionAnalysisMetadata>of() /* actionsWithoutExtraAction */,
252 ruleContext));
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000253
Dmitry Lomovdce01702016-11-28 15:51:32 +0000254 return new ConfiguredAspect(descriptor, providers.build());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100255 }
256 }
Carmi Grushko65ac3552015-08-21 16:43:26 +0000257}