blob: fd4f4675df4bc00e22a18aa35a37bb5fa695125c [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
Irina Iancu2f235992017-01-10 16:03:29 +000017import com.google.common.collect.ListMultimap;
Lukacs Berki7894c182016-05-10 12:07:01 +000018import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010019import com.google.devtools.build.lib.collect.nestedset.NestedSet;
20import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
21import com.google.devtools.build.lib.collect.nestedset.Order;
22import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
Irina Iancu2f235992017-01-10 16:03:29 +000023import com.google.devtools.build.lib.packages.Attribute;
24import com.google.devtools.build.lib.packages.AttributeMap;
Lukacs Berki7894c182016-05-10 12:07:01 +000025import com.google.devtools.build.lib.packages.License;
26import com.google.devtools.build.lib.packages.Rule;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010027
28/**
29 * A {@link ConfiguredTarget} that has licensed targets in its transitive closure.
30 */
31@Immutable
32public final class LicensesProviderImpl implements LicensesProvider {
33 public static final LicensesProvider EMPTY =
Irina Iancu2f235992017-01-10 16:03:29 +000034 new LicensesProviderImpl(NestedSetBuilder.<TargetLicense>emptySet(Order.LINK_ORDER), null);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010035
36 private final NestedSet<TargetLicense> transitiveLicenses;
Irina Iancu2f235992017-01-10 16:03:29 +000037 private final TargetLicense outputLicenses;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010038
Irina Iancu2f235992017-01-10 16:03:29 +000039 public LicensesProviderImpl(
40 NestedSet<TargetLicense> transitiveLicenses, TargetLicense outputLicenses) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010041 this.transitiveLicenses = transitiveLicenses;
Irina Iancu2f235992017-01-10 16:03:29 +000042 this.outputLicenses = outputLicenses;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010043 }
44
Lukacs Berki7894c182016-05-10 12:07:01 +000045 /**
46 * Create the appropriate {@link LicensesProvider} for a rule based on its {@code RuleContext}
47 */
48 public static LicensesProvider of(RuleContext ruleContext) {
49 if (!ruleContext.getConfiguration().checkLicenses()) {
50 return EMPTY;
51 }
52
53 NestedSetBuilder<TargetLicense> builder = NestedSetBuilder.linkOrder();
54 BuildConfiguration configuration = ruleContext.getConfiguration();
55 Rule rule = ruleContext.getRule();
Irina Iancu2f235992017-01-10 16:03:29 +000056 AttributeMap attributes = ruleContext.attributes();
57 License toolOutputLicense = rule.getToolOutputLicense(attributes);
58 TargetLicense outputLicenses =
59 toolOutputLicense == null ? null : new TargetLicense(rule.getLabel(), toolOutputLicense);
60
Lukacs Berki7894c182016-05-10 12:07:01 +000061 if (configuration.isHostConfiguration() && toolOutputLicense != null) {
62 if (toolOutputLicense != License.NO_LICENSE) {
Irina Iancu2f235992017-01-10 16:03:29 +000063 builder.add(outputLicenses);
Lukacs Berki7894c182016-05-10 12:07:01 +000064 }
65 } else {
66 if (rule.getLicense() != License.NO_LICENSE) {
67 builder.add(new TargetLicense(rule.getLabel(), rule.getLicense()));
68 }
69
Irina Iancu2f235992017-01-10 16:03:29 +000070 ListMultimap<String, ? extends TransitiveInfoCollection> configuredMap =
71 ruleContext.getConfiguredTargetMap();
72
73 for (String depAttrName : attributes.getAttributeNames()) {
74 // Only add the transitive licenses for the attributes that do not have the output_licenses.
75 Attribute attribute = attributes.getAttributeDefinition(depAttrName);
76 for (TransitiveInfoCollection dep : configuredMap.get(depAttrName)) {
77 LicensesProvider provider = dep.getProvider(LicensesProvider.class);
78 if (provider == null) {
79 continue;
80 }
81 if (useOutputLicenses(attribute, configuration) && provider.hasOutputLicenses()) {
82 builder.add(provider.getOutputLicenses());
83 } else {
84 builder.addTransitive(provider.getTransitiveLicenses());
85 }
Lukacs Berki7894c182016-05-10 12:07:01 +000086 }
87 }
88 }
89
Irina Iancu2f235992017-01-10 16:03:29 +000090 return new LicensesProviderImpl(builder.build(), outputLicenses);
91 }
92
93 private static boolean useOutputLicenses(Attribute attribute, BuildConfiguration configuration) {
94 return configuration.isHostConfiguration() || attribute.useOutputLicenses();
Lukacs Berki7894c182016-05-10 12:07:01 +000095 }
96
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010097 @Override
98 public NestedSet<TargetLicense> getTransitiveLicenses() {
99 return transitiveLicenses;
100 }
Irina Iancu2f235992017-01-10 16:03:29 +0000101
102 @Override
103 public TargetLicense getOutputLicenses() {
104 return outputLicenses;
105 }
106
107 @Override
108 public boolean hasOutputLicenses() {
109 return outputLicenses != null;
110 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100111}