blob: 29fc277ec6a6d85e7f152068b3264adaf62371f5 [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
tomlua155b532017-11-08 20:12:47 +010019import com.google.common.base.Preconditions;
tomlu39a0a382018-06-22 09:43:23 -070020import com.google.common.collect.ImmutableList;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010021import com.google.common.collect.ImmutableMap;
Carmi Grushko4076e442016-01-21 20:05:42 +000022import com.google.common.collect.ImmutableSet;
Rumou Duan33bab462016-04-25 17:55:12 +000023import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
tomlu39a0a382018-06-22 09:43:23 -070024import com.google.devtools.build.lib.actions.Actions;
25import com.google.devtools.build.lib.actions.Actions.GeneratingActions;
Dmitry Lomove2033b12015-08-19 16:57:49 +000026import com.google.devtools.build.lib.actions.Artifact;
tomlu39a0a382018-06-22 09:43:23 -070027import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
gregce130feba2020-02-06 13:55:08 -080028import com.google.devtools.build.lib.analysis.config.CoreOptions;
29import com.google.devtools.build.lib.analysis.config.CoreOptions.IncludeConfigFragmentsEnum;
tomlu64416ce2018-10-02 12:46:08 -070030import com.google.devtools.build.lib.analysis.skylark.SkylarkApiProvider;
Dmitry Lomove2033b12015-08-19 16:57:49 +000031import com.google.devtools.build.lib.collect.nestedset.NestedSet;
32import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010033import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
Dmitry Lomovdce01702016-11-28 15:51:32 +000034import com.google.devtools.build.lib.packages.AspectClass;
Dmitry Lomov15756522016-12-16 16:52:37 +000035import com.google.devtools.build.lib.packages.AspectDescriptor;
Dmitry Lomovdce01702016-11-28 15:51:32 +000036import com.google.devtools.build.lib.packages.AspectParameters;
adonovana11e2d02019-12-06 07:11:35 -080037import com.google.devtools.build.lib.packages.Info;
dslomovde965ac2017-07-31 21:07:51 +020038import com.google.devtools.build.lib.packages.Provider;
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;
adonovanf5262c52020-04-02 09:25:14 -070041import com.google.devtools.build.lib.syntax.Location;
Googler94d35de2016-09-16 15:21:39 +000042import java.util.Arrays;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010043import java.util.Map;
Dmitry Lomove2033b12015-08-19 16:57:49 +000044import java.util.TreeMap;
Dmitry Lomove2033b12015-08-19 16:57:49 +000045import javax.annotation.Nullable;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010046
47/**
48 * Extra information about a configured target computed on request of a dependent.
49 *
50 * <p>Analogous to {@link ConfiguredTarget}: contains a bunch of transitive info providers, which
Googler4e0a5cb2017-04-09 17:58:18 -040051 * are merged with the providers of the associated configured target before they are passed to the
52 * configured target factories that depend on the configured target to which this aspect is added.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010053 *
54 * <p>Aspects are created alongside configured targets on request from dependents.
Lukacs Berki2300cd62016-05-19 11:06:37 +000055 *
Googler4e0a5cb2017-04-09 17:58:18 -040056 * <p>For more information about aspects, see {@link
57 * com.google.devtools.build.lib.packages.AspectClass}.
Lukacs Berki2300cd62016-05-19 11:06:37 +000058 *
ulfjack26d0e492017-08-07 13:42:33 +020059 * @see com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory
Lukacs Berki2300cd62016-05-19 11:06:37 +000060 * @see com.google.devtools.build.lib.packages.AspectClass
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010061 */
62@Immutable
janakrbffa2db2018-03-25 12:42:11 -070063@AutoCodec
janakr6d185b82020-03-30 14:08:01 -070064public final class ConfiguredAspect implements ProviderCollection {
Dmitry Lomovdce01702016-11-28 15:51:32 +000065 private final AspectDescriptor descriptor;
tomlu39a0a382018-06-22 09:43:23 -070066 private final ImmutableList<ActionAnalysisMetadata> actions;
tomlu39a0a382018-06-22 09:43:23 -070067 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,
tomlu39a0a382018-06-22 09:43:23 -070073 TransitiveInfoProviderMap providers) {
Dmitry Lomovdce01702016-11-28 15:51:32 +000074 this.descriptor = descriptor;
tomlu39a0a382018-06-22 09:43:23 -070075 this.actions = actions;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010076 this.providers = providers;
tomlu64416ce2018-10-02 12:46:08 -070077
78 // Initialize every SkylarkApiProvider
79 for (int i = 0; i < providers.getProviderCount(); i++) {
80 Object obj = providers.getProviderInstanceAt(i);
81 if (obj instanceof SkylarkApiProvider) {
82 ((SkylarkApiProvider) obj).init(providers);
83 }
84 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010085 }
86
87 /**
Dmitry Lomove2033b12015-08-19 16:57:49 +000088 * Returns the aspect name.
89 */
90 public String getName() {
Dmitry Lomovdce01702016-11-28 15:51:32 +000091 return descriptor.getAspectClass().getName();
92 }
93
94 /**
95 * The aspect descriptor originating this ConfiguredAspect.
96 */
97 public AspectDescriptor getDescriptor() {
98 return descriptor;
Dmitry Lomove2033b12015-08-19 16:57:49 +000099 }
100
tomlu39a0a382018-06-22 09:43:23 -0700101 public ImmutableList<ActionAnalysisMetadata> getActions() {
102 return actions;
103 }
104
Googler94d35de2016-09-16 15:21:39 +0000105 /** Returns the providers created by the aspect. */
106 public TransitiveInfoProviderMap getProviders() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100107 return providers;
108 }
109
janakr6d185b82020-03-30 14:08:01 -0700110 @Override
Dmitry Lomove2033b12015-08-19 16:57:49 +0000111 @Nullable
Dmitry Lomov2473b9f2015-09-14 08:53:10 +0000112 public <P extends TransitiveInfoProvider> P getProvider(Class<P> providerClass) {
dslomov211a3ba2017-05-16 00:21:22 +0200113 AnalysisUtils.checkProvider(providerClass);
Googler94d35de2016-09-16 15:21:39 +0000114 return providers.getProvider(providerClass);
Dmitry Lomove2033b12015-08-19 16:57:49 +0000115 }
116
janakr6d185b82020-03-30 14:08:01 -0700117 @Override
adonovana11e2d02019-12-06 07:11:35 -0800118 public Info get(Provider.Key key) {
tomlu64416ce2018-10-02 12:46:08 -0700119 return providers.get(key);
dslomovea7d4822017-05-03 13:01:27 +0200120 }
121
janakr6d185b82020-03-30 14:08:01 -0700122 @Override
dslomovea7d4822017-05-03 13:01:27 +0200123 public Object get(String legacyKey) {
dslomov69c45f82017-12-14 11:15:43 -0500124 if (OutputGroupInfo.SKYLARK_NAME.equals(legacyKey)) {
125 return get(OutputGroupInfo.SKYLARK_CONSTRUCTOR.getKey());
dslomovea7d4822017-05-03 13:01:27 +0200126 }
tomlu64416ce2018-10-02 12:46:08 -0700127 return providers.get(legacyKey);
dslomovea7d4822017-05-03 13:01:27 +0200128 }
129
Lukacs Berki549bfce2016-04-22 15:29:12 +0000130 public static ConfiguredAspect forAlias(ConfiguredAspect real) {
janakrefb3f152019-06-05 17:42:34 -0700131 return new ConfiguredAspect(real.descriptor, real.getActions(), real.getProviders());
Lukacs Berki549bfce2016-04-22 15:29:12 +0000132 }
133
Dmitry Lomov6cd98972017-03-01 15:44:00 +0000134 public static ConfiguredAspect forNonapplicableTarget(AspectDescriptor descriptor) {
tomlu39a0a382018-06-22 09:43:23 -0700135 return new ConfiguredAspect(
136 descriptor,
137 ImmutableList.of(),
tomlu39a0a382018-06-22 09:43:23 -0700138 new TransitiveInfoProviderMapBuilder().add().build());
Dmitry Lomov6cd98972017-03-01 15:44:00 +0000139 }
140
dslomov99ea6b42017-04-25 17:46:17 +0200141 public static Builder builder(
142 AspectClass aspectClass, AspectParameters parameters, RuleContext ruleContext) {
143 return new Builder(aspectClass, parameters, ruleContext);
144 }
145
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100146 /**
Dmitry Lomovb487ac62015-11-09 13:09:12 +0000147 * Builder for {@link ConfiguredAspect}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100148 */
149 public static class Builder {
Googler4b7aae42017-05-04 17:16:09 -0400150 private final TransitiveInfoProviderMapBuilder providers =
151 new TransitiveInfoProviderMapBuilder();
Dmitry Lomove2033b12015-08-19 16:57:49 +0000152 private final Map<String, NestedSetBuilder<Artifact>> outputGroupBuilders = new TreeMap<>();
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000153 private final RuleContext ruleContext;
Dmitry Lomovdce01702016-11-28 15:51:32 +0000154 private final AspectDescriptor descriptor;
Dmitry Lomove2033b12015-08-19 16:57:49 +0000155
Dmitry Lomovdce01702016-11-28 15:51:32 +0000156 public Builder(
157 AspectClass aspectClass,
158 AspectParameters parameters,
159 RuleContext context) {
160 this(new AspectDescriptor(aspectClass, parameters), context);
161 }
162
163 public Builder(AspectDescriptor descriptor, RuleContext ruleContext) {
164 this.descriptor = descriptor;
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000165 this.ruleContext = ruleContext;
Dmitry Lomove2033b12015-08-19 16:57:49 +0000166 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100167
Googler94d35de2016-09-16 15:21:39 +0000168 public <T extends TransitiveInfoProvider> Builder addProvider(
169 Class<? extends T> providerClass, T provider) {
170 Preconditions.checkNotNull(provider);
171 checkProviderClass(providerClass);
172 providers.put(providerClass, provider);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100173 return this;
174 }
175
Googler94d35de2016-09-16 15:21:39 +0000176 /** Adds a provider to the aspect. */
177 public Builder addProvider(TransitiveInfoProvider provider) {
178 Preconditions.checkNotNull(provider);
Googler4b7aae42017-05-04 17:16:09 -0400179 addProvider(TransitiveInfoProviderEffectiveClassHelper.get(provider), provider);
Googler94d35de2016-09-16 15:21:39 +0000180 return this;
181 }
182
183 private void checkProviderClass(Class<? extends TransitiveInfoProvider> providerClass) {
184 Preconditions.checkNotNull(providerClass);
Googler94d35de2016-09-16 15:21:39 +0000185 }
186
187 /** Adds providers to the aspect. */
188 public Builder addProviders(TransitiveInfoProviderMap providers) {
dslomovf6a7e5a2017-07-05 07:23:31 -0400189 this.providers.addAll(providers);
Googler94d35de2016-09-16 15:21:39 +0000190 return this;
191 }
192
193 /** Adds providers to the aspect. */
194 public Builder addProviders(TransitiveInfoProvider... providers) {
195 return addProviders(Arrays.asList(providers));
196 }
197
198 /** Adds providers to the aspect. */
199 public Builder addProviders(Iterable<TransitiveInfoProvider> providers) {
200 for (TransitiveInfoProvider provider : providers) {
201 addProvider(provider);
Carmi Grushkob8f0e862015-11-23 23:26:15 +0000202 }
203 return this;
204 }
205
Carmi Grushko65ac3552015-08-21 16:43:26 +0000206 /**
Dmitry Lomove2033b12015-08-19 16:57:49 +0000207 * Adds a set of files to an output group.
208 */
209 public Builder addOutputGroup(String name, NestedSet<Artifact> artifacts) {
210 NestedSetBuilder<Artifact> nestedSetBuilder = outputGroupBuilders.get(name);
211 if (nestedSetBuilder == null) {
212 nestedSetBuilder = NestedSetBuilder.<Artifact>stableOrder();
213 outputGroupBuilders.put(name, nestedSetBuilder);
214 }
215 nestedSetBuilder.addTransitive(artifacts);
216 return this;
217 }
218
Googler63ce8f22017-01-09 15:32:16 +0000219 public Builder addSkylarkTransitiveInfo(String name, Object value) {
dslomovf6a7e5a2017-07-05 07:23:31 -0400220 providers.put(name, value);
Googler63ce8f22017-01-09 15:32:16 +0000221 return this;
222 }
223
Dmitry Lomov2aa1a982015-10-20 12:18:36 +0000224 public Builder addSkylarkTransitiveInfo(String name, Object value, Location loc)
225 throws EvalException {
dslomovf6a7e5a2017-07-05 07:23:31 -0400226 providers.put(name, value);
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000227 return this;
228 }
229
adonovana11e2d02019-12-06 07:11:35 -0800230 public Builder addSkylarkDeclaredProvider(Info declaredProvider) throws EvalException {
dslomovde965ac2017-07-31 21:07:51 +0200231 Provider constructor = declaredProvider.getProvider();
Vladimir Moskva6c28fe92017-03-03 12:55:08 +0000232 if (!constructor.isExported()) {
233 throw new EvalException(
234 constructor.getLocation(), "All providers must be top level values");
235 }
dslomov11da2202017-07-27 23:48:56 +0200236 addDeclaredProvider(declaredProvider);
Vladimir Moskva6c28fe92017-03-03 12:55:08 +0000237 return this;
238 }
239
adonovana11e2d02019-12-06 07:11:35 -0800240 private void addDeclaredProvider(Info declaredProvider) {
dslomov11da2202017-07-27 23:48:56 +0200241 providers.put(declaredProvider);
dslomovea7d4822017-05-03 13:01:27 +0200242 }
243
adonovana11e2d02019-12-06 07:11:35 -0800244 public Builder addNativeDeclaredProvider(Info declaredProvider) {
dslomovde965ac2017-07-31 21:07:51 +0200245 Provider constructor = declaredProvider.getProvider();
dslomovf9697342017-05-02 16:26:39 +0200246 Preconditions.checkState(constructor.isExported());
dslomov11da2202017-07-27 23:48:56 +0200247 addDeclaredProvider(declaredProvider);
dslomovf9697342017-05-02 16:26:39 +0200248 return this;
249 }
250
tomlu39a0a382018-06-22 09:43:23 -0700251 public ConfiguredAspect build() throws ActionConflictException {
Dmitry Lomove2033b12015-08-19 16:57:49 +0000252 if (!outputGroupBuilders.isEmpty()) {
253 ImmutableMap.Builder<String, NestedSet<Artifact>> outputGroups = ImmutableMap.builder();
254 for (Map.Entry<String, NestedSetBuilder<Artifact>> entry : outputGroupBuilders.entrySet()) {
255 outputGroups.put(entry.getKey(), entry.getValue().build());
256 }
257
dslomov69c45f82017-12-14 11:15:43 -0500258 if (providers.contains(OutputGroupInfo.SKYLARK_CONSTRUCTOR.getKey())) {
Dmitry Lomove2033b12015-08-19 16:57:49 +0000259 throw new IllegalStateException(
dslomov69c45f82017-12-14 11:15:43 -0500260 "OutputGroupInfo was provided explicitly; do not use addOutputGroup");
Dmitry Lomove2033b12015-08-19 16:57:49 +0000261 }
dslomov69c45f82017-12-14 11:15:43 -0500262 addDeclaredProvider(new OutputGroupInfo(outputGroups.build()));
Dmitry Lomove2033b12015-08-19 16:57:49 +0000263 }
264
Carmi Grushko4076e442016-01-21 20:05:42 +0000265 addProvider(
Carmi Grushko4076e442016-01-21 20:05:42 +0000266 createExtraActionProvider(
cushon8c6b7ab2018-04-27 01:25:50 -0700267 /* actionsWithoutExtraAction= */ ImmutableSet.<ActionAnalysisMetadata>of(),
Rumou Duan33bab462016-04-25 17:55:12 +0000268 ruleContext));
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000269
tomlu39a0a382018-06-22 09:43:23 -0700270 AnalysisEnvironment analysisEnvironment = ruleContext.getAnalysisEnvironment();
271 GeneratingActions generatingActions =
janakrefb3f152019-06-05 17:42:34 -0700272 Actions.assignOwnersAndFilterSharedActionsAndThrowActionConflict(
tomlu39a0a382018-06-22 09:43:23 -0700273 analysisEnvironment.getActionKeyContext(),
janakrefb3f152019-06-05 17:42:34 -0700274 analysisEnvironment.getRegisteredActions(),
275 ruleContext.getOwner(),
276 /*outputFiles=*/ null);
tomlu39a0a382018-06-22 09:43:23 -0700277
gregce130feba2020-02-06 13:55:08 -0800278 if (ruleContext
279 .getConfiguration()
280 .getOptions()
281 .get(CoreOptions.class)
282 .includeRequiredConfigFragmentsProvider
283 != IncludeConfigFragmentsEnum.OFF) {
284 // This guarantees aspects pass through the requirements of their dependencies. But native
285 // aspects can also declare direct requirements.
286 // TODO(gregce): support native aspect direct requirements.
287 addProvider(new RequiredConfigFragmentsProvider(ruleContext.getRequiredConfigFragments()));
288 }
289
tomlu39a0a382018-06-22 09:43:23 -0700290 return new ConfiguredAspect(
291 descriptor,
292 generatingActions.getActions(),
tomlu39a0a382018-06-22 09:43:23 -0700293 providers.build());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100294 }
295 }
Carmi Grushko65ac3552015-08-21 16:43:26 +0000296}