blob: e99d134c837d7a296cea0c9d824c159c0fc4ab83 [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;
tomlua155b532017-11-08 20:12:47 +010020import com.google.common.base.Preconditions;
tomlu39a0a382018-06-22 09:43:23 -070021import com.google.common.collect.ImmutableList;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010022import com.google.common.collect.ImmutableMap;
Carmi Grushko4076e442016-01-21 20:05:42 +000023import com.google.common.collect.ImmutableSet;
Rumou Duan33bab462016-04-25 17:55:12 +000024import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
tomlu39a0a382018-06-22 09:43:23 -070025import com.google.devtools.build.lib.actions.Actions;
26import com.google.devtools.build.lib.actions.Actions.GeneratingActions;
Dmitry Lomove2033b12015-08-19 16:57:49 +000027import com.google.devtools.build.lib.actions.Artifact;
tomlu39a0a382018-06-22 09:43:23 -070028import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
Dmitry Lomove2033b12015-08-19 16:57:49 +000029import com.google.devtools.build.lib.collect.nestedset.NestedSet;
30import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010031import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
Dmitry Lomov0b832ce2015-10-20 10:03:14 +000032import com.google.devtools.build.lib.events.Location;
Dmitry Lomovdce01702016-11-28 15:51:32 +000033import com.google.devtools.build.lib.packages.AspectClass;
Dmitry Lomov15756522016-12-16 16:52:37 +000034import com.google.devtools.build.lib.packages.AspectDescriptor;
Dmitry Lomovdce01702016-11-28 15:51:32 +000035import com.google.devtools.build.lib.packages.AspectParameters;
dslomovde965ac2017-07-31 21:07:51 +020036import com.google.devtools.build.lib.packages.Info;
37import com.google.devtools.build.lib.packages.Provider;
dslomovea7d4822017-05-03 13:01:27 +020038import com.google.devtools.build.lib.packages.SkylarkProviderIdentifier;
janakrbffa2db2018-03-25 12:42:11 -070039import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
Dmitry Lomov2aa1a982015-10-20 12:18:36 +000040import com.google.devtools.build.lib.syntax.EvalException;
Googler94d35de2016-09-16 15:21:39 +000041import java.util.Arrays;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010042import java.util.Map;
Dmitry Lomove2033b12015-08-19 16:57:49 +000043import java.util.TreeMap;
Dmitry Lomove2033b12015-08-19 16:57:49 +000044import javax.annotation.Nullable;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010045
46/**
47 * Extra information about a configured target computed on request of a dependent.
48 *
49 * <p>Analogous to {@link ConfiguredTarget}: contains a bunch of transitive info providers, which
Googler4e0a5cb2017-04-09 17:58:18 -040050 * are merged with the providers of the associated configured target before they are passed to the
51 * configured target factories that depend on the configured target to which this aspect is added.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010052 *
53 * <p>Aspects are created alongside configured targets on request from dependents.
Lukacs Berki2300cd62016-05-19 11:06:37 +000054 *
Googler4e0a5cb2017-04-09 17:58:18 -040055 * <p>For more information about aspects, see {@link
56 * com.google.devtools.build.lib.packages.AspectClass}.
Lukacs Berki2300cd62016-05-19 11:06:37 +000057 *
ulfjack26d0e492017-08-07 13:42:33 +020058 * @see com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory
Lukacs Berki2300cd62016-05-19 11:06:37 +000059 * @see com.google.devtools.build.lib.packages.AspectClass
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010060 */
61@Immutable
janakrbffa2db2018-03-25 12:42:11 -070062@AutoCodec
Googler4e0a5cb2017-04-09 17:58:18 -040063public final class ConfiguredAspect {
Dmitry Lomovdce01702016-11-28 15:51:32 +000064 private final AspectDescriptor descriptor;
tomlu39a0a382018-06-22 09:43:23 -070065 private final ImmutableList<ActionAnalysisMetadata> actions;
66 private final ImmutableMap<Artifact, Integer> generatingActionIndex;
67 private final TransitiveInfoProviderMap providers;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010068
janakrbffa2db2018-03-25 12:42:11 -070069 @AutoCodec.VisibleForSerialization
tomlu39a0a382018-06-22 09:43:23 -070070 ConfiguredAspect(
71 AspectDescriptor descriptor,
72 ImmutableList<ActionAnalysisMetadata> actions,
73 ImmutableMap<Artifact, Integer> generatingActionIndex,
74 TransitiveInfoProviderMap providers) {
Dmitry Lomovdce01702016-11-28 15:51:32 +000075 this.descriptor = descriptor;
tomlu39a0a382018-06-22 09:43:23 -070076 this.actions = actions;
77 this.generatingActionIndex = generatingActionIndex;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010078 this.providers = providers;
79 }
80
81 /**
Dmitry Lomove2033b12015-08-19 16:57:49 +000082 * Returns the aspect name.
83 */
84 public String getName() {
Dmitry Lomovdce01702016-11-28 15:51:32 +000085 return descriptor.getAspectClass().getName();
86 }
87
88 /**
89 * The aspect descriptor originating this ConfiguredAspect.
90 */
91 public AspectDescriptor getDescriptor() {
92 return descriptor;
Dmitry Lomove2033b12015-08-19 16:57:49 +000093 }
94
tomlu39a0a382018-06-22 09:43:23 -070095 public ImmutableList<ActionAnalysisMetadata> getActions() {
96 return actions;
97 }
98
99 /**
100 * Returns a map where keys are artifacts that are action outputs of this rule, and values are the
101 * index of the action that generates that artifact.
102 */
103 public ImmutableMap<Artifact, Integer> getGeneratingActionIndex() {
104 return generatingActionIndex;
105 }
106
Googler94d35de2016-09-16 15:21:39 +0000107 /** Returns the providers created by the aspect. */
108 public TransitiveInfoProviderMap getProviders() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100109 return providers;
110 }
111
Dmitry Lomove2033b12015-08-19 16:57:49 +0000112 @Nullable
Dmitry Lomov2473b9f2015-09-14 08:53:10 +0000113 @VisibleForTesting
114 public <P extends TransitiveInfoProvider> P getProvider(Class<P> providerClass) {
dslomov211a3ba2017-05-16 00:21:22 +0200115 AnalysisUtils.checkProvider(providerClass);
Googler94d35de2016-09-16 15:21:39 +0000116 return providers.getProvider(providerClass);
Dmitry Lomove2033b12015-08-19 16:57:49 +0000117 }
118
dslomovea7d4822017-05-03 13:01:27 +0200119 public Object getProvider(SkylarkProviderIdentifier id) {
120 if (id.isLegacy()) {
121 return get(id.getLegacyId());
122 } else {
123 return get(id.getKey());
124 }
125 }
126
dslomovde965ac2017-07-31 21:07:51 +0200127 public Info get(Provider.Key key) {
dslomovf6a7e5a2017-07-05 07:23:31 -0400128 return providers.getProvider(key);
dslomovea7d4822017-05-03 13:01:27 +0200129 }
130
131 public Object get(String legacyKey) {
dslomov69c45f82017-12-14 11:15:43 -0500132 if (OutputGroupInfo.SKYLARK_NAME.equals(legacyKey)) {
133 return get(OutputGroupInfo.SKYLARK_CONSTRUCTOR.getKey());
dslomovea7d4822017-05-03 13:01:27 +0200134 }
dslomovf6a7e5a2017-07-05 07:23:31 -0400135 return providers.getProvider(legacyKey);
dslomovea7d4822017-05-03 13:01:27 +0200136 }
137
Lukacs Berki549bfce2016-04-22 15:29:12 +0000138 public static ConfiguredAspect forAlias(ConfiguredAspect real) {
tomlu39a0a382018-06-22 09:43:23 -0700139 return new ConfiguredAspect(
140 real.descriptor, real.getActions(), real.getGeneratingActionIndex(), real.getProviders());
Lukacs Berki549bfce2016-04-22 15:29:12 +0000141 }
142
Dmitry Lomov6cd98972017-03-01 15:44:00 +0000143 public static ConfiguredAspect forNonapplicableTarget(AspectDescriptor descriptor) {
tomlu39a0a382018-06-22 09:43:23 -0700144 return new ConfiguredAspect(
145 descriptor,
146 ImmutableList.of(),
147 ImmutableMap.of(),
148 new TransitiveInfoProviderMapBuilder().add().build());
Dmitry Lomov6cd98972017-03-01 15:44:00 +0000149 }
150
dslomov99ea6b42017-04-25 17:46:17 +0200151 public static Builder builder(
152 AspectClass aspectClass, AspectParameters parameters, RuleContext ruleContext) {
153 return new Builder(aspectClass, parameters, ruleContext);
154 }
155
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100156 /**
Dmitry Lomovb487ac62015-11-09 13:09:12 +0000157 * Builder for {@link ConfiguredAspect}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100158 */
159 public static class Builder {
Googler4b7aae42017-05-04 17:16:09 -0400160 private final TransitiveInfoProviderMapBuilder providers =
161 new TransitiveInfoProviderMapBuilder();
Dmitry Lomove2033b12015-08-19 16:57:49 +0000162 private final Map<String, NestedSetBuilder<Artifact>> outputGroupBuilders = new TreeMap<>();
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000163 private final RuleContext ruleContext;
Dmitry Lomovdce01702016-11-28 15:51:32 +0000164 private final AspectDescriptor descriptor;
Dmitry Lomove2033b12015-08-19 16:57:49 +0000165
Dmitry Lomovdce01702016-11-28 15:51:32 +0000166 public Builder(
167 AspectClass aspectClass,
168 AspectParameters parameters,
169 RuleContext context) {
170 this(new AspectDescriptor(aspectClass, parameters), context);
171 }
172
173 public Builder(AspectDescriptor descriptor, RuleContext ruleContext) {
174 this.descriptor = descriptor;
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000175 this.ruleContext = ruleContext;
Dmitry Lomove2033b12015-08-19 16:57:49 +0000176 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100177
Googler94d35de2016-09-16 15:21:39 +0000178 public <T extends TransitiveInfoProvider> Builder addProvider(
179 Class<? extends T> providerClass, T provider) {
180 Preconditions.checkNotNull(provider);
181 checkProviderClass(providerClass);
182 providers.put(providerClass, provider);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100183 return this;
184 }
185
Googler94d35de2016-09-16 15:21:39 +0000186 /** Adds a provider to the aspect. */
187 public Builder addProvider(TransitiveInfoProvider provider) {
188 Preconditions.checkNotNull(provider);
Googler4b7aae42017-05-04 17:16:09 -0400189 addProvider(TransitiveInfoProviderEffectiveClassHelper.get(provider), provider);
Googler94d35de2016-09-16 15:21:39 +0000190 return this;
191 }
192
193 private void checkProviderClass(Class<? extends TransitiveInfoProvider> providerClass) {
194 Preconditions.checkNotNull(providerClass);
Googler94d35de2016-09-16 15:21:39 +0000195 }
196
197 /** Adds providers to the aspect. */
198 public Builder addProviders(TransitiveInfoProviderMap providers) {
dslomovf6a7e5a2017-07-05 07:23:31 -0400199 this.providers.addAll(providers);
Googler94d35de2016-09-16 15:21:39 +0000200 return this;
201 }
202
203 /** Adds providers to the aspect. */
204 public Builder addProviders(TransitiveInfoProvider... providers) {
205 return addProviders(Arrays.asList(providers));
206 }
207
208 /** Adds providers to the aspect. */
209 public Builder addProviders(Iterable<TransitiveInfoProvider> providers) {
210 for (TransitiveInfoProvider provider : providers) {
211 addProvider(provider);
Carmi Grushkob8f0e862015-11-23 23:26:15 +0000212 }
213 return this;
214 }
215
Carmi Grushko65ac3552015-08-21 16:43:26 +0000216 /**
Dmitry Lomove2033b12015-08-19 16:57:49 +0000217 * Adds a set of files to an output group.
218 */
219 public Builder addOutputGroup(String name, NestedSet<Artifact> artifacts) {
220 NestedSetBuilder<Artifact> nestedSetBuilder = outputGroupBuilders.get(name);
221 if (nestedSetBuilder == null) {
222 nestedSetBuilder = NestedSetBuilder.<Artifact>stableOrder();
223 outputGroupBuilders.put(name, nestedSetBuilder);
224 }
225 nestedSetBuilder.addTransitive(artifacts);
226 return this;
227 }
228
Googler63ce8f22017-01-09 15:32:16 +0000229 public Builder addSkylarkTransitiveInfo(String name, Object value) {
dslomovf6a7e5a2017-07-05 07:23:31 -0400230 providers.put(name, value);
Googler63ce8f22017-01-09 15:32:16 +0000231 return this;
232 }
233
Dmitry Lomov2aa1a982015-10-20 12:18:36 +0000234 public Builder addSkylarkTransitiveInfo(String name, Object value, Location loc)
235 throws EvalException {
dslomovf6a7e5a2017-07-05 07:23:31 -0400236 providers.put(name, value);
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000237 return this;
238 }
239
brandjon11bcd242017-12-27 12:01:27 -0800240 public Builder addSkylarkDeclaredProvider(Info declaredProvider)
Vladimir Moskva6c28fe92017-03-03 12:55:08 +0000241 throws EvalException {
dslomovde965ac2017-07-31 21:07:51 +0200242 Provider constructor = declaredProvider.getProvider();
Vladimir Moskva6c28fe92017-03-03 12:55:08 +0000243 if (!constructor.isExported()) {
244 throw new EvalException(
245 constructor.getLocation(), "All providers must be top level values");
246 }
dslomov11da2202017-07-27 23:48:56 +0200247 addDeclaredProvider(declaredProvider);
Vladimir Moskva6c28fe92017-03-03 12:55:08 +0000248 return this;
249 }
250
dslomovde965ac2017-07-31 21:07:51 +0200251 private void addDeclaredProvider(Info declaredProvider) {
dslomov11da2202017-07-27 23:48:56 +0200252 providers.put(declaredProvider);
dslomovea7d4822017-05-03 13:01:27 +0200253 }
254
dslomovde965ac2017-07-31 21:07:51 +0200255 public Builder addNativeDeclaredProvider(Info declaredProvider) {
256 Provider constructor = declaredProvider.getProvider();
dslomovf9697342017-05-02 16:26:39 +0200257 Preconditions.checkState(constructor.isExported());
dslomov11da2202017-07-27 23:48:56 +0200258 addDeclaredProvider(declaredProvider);
dslomovf9697342017-05-02 16:26:39 +0200259 return this;
260 }
261
tomlu39a0a382018-06-22 09:43:23 -0700262 public ConfiguredAspect build() throws ActionConflictException {
Dmitry Lomove2033b12015-08-19 16:57:49 +0000263 if (!outputGroupBuilders.isEmpty()) {
264 ImmutableMap.Builder<String, NestedSet<Artifact>> outputGroups = ImmutableMap.builder();
265 for (Map.Entry<String, NestedSetBuilder<Artifact>> entry : outputGroupBuilders.entrySet()) {
266 outputGroups.put(entry.getKey(), entry.getValue().build());
267 }
268
dslomov69c45f82017-12-14 11:15:43 -0500269 if (providers.contains(OutputGroupInfo.SKYLARK_CONSTRUCTOR.getKey())) {
Dmitry Lomove2033b12015-08-19 16:57:49 +0000270 throw new IllegalStateException(
dslomov69c45f82017-12-14 11:15:43 -0500271 "OutputGroupInfo was provided explicitly; do not use addOutputGroup");
Dmitry Lomove2033b12015-08-19 16:57:49 +0000272 }
dslomov69c45f82017-12-14 11:15:43 -0500273 addDeclaredProvider(new OutputGroupInfo(outputGroups.build()));
Dmitry Lomove2033b12015-08-19 16:57:49 +0000274 }
275
Carmi Grushko4076e442016-01-21 20:05:42 +0000276 addProvider(
Carmi Grushko4076e442016-01-21 20:05:42 +0000277 createExtraActionProvider(
cushon8c6b7ab2018-04-27 01:25:50 -0700278 /* actionsWithoutExtraAction= */ ImmutableSet.<ActionAnalysisMetadata>of(),
Rumou Duan33bab462016-04-25 17:55:12 +0000279 ruleContext));
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000280
tomlu39a0a382018-06-22 09:43:23 -0700281 AnalysisEnvironment analysisEnvironment = ruleContext.getAnalysisEnvironment();
282 GeneratingActions generatingActions =
283 Actions.filterSharedActionsAndThrowActionConflict(
284 analysisEnvironment.getActionKeyContext(),
285 analysisEnvironment.getRegisteredActions());
286
287 return new ConfiguredAspect(
288 descriptor,
289 generatingActions.getActions(),
290 generatingActions.getGeneratingActionIndex(),
291 providers.build());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100292 }
293 }
Carmi Grushko65ac3552015-08-21 16:43:26 +0000294}