From 2f23599dda8f580234fc5a97675561cc86127444 Mon Sep 17 00:00:00 2001 From: Irina Iancu Date: Tue, 10 Jan 2017 16:03:29 +0000 Subject: [PATCH] Add new flag to specify if output_licenses attribute should be checked for licenses. Also flipped :jvm attribute from HOST to TARGET and set the new flag on it. -- PiperOrigin-RevId: 144084000 MOS_MIGRATED_REVID=144084000 --- .../analysis/InputFileConfiguredTarget.java | 10 ++++ .../build/lib/analysis/LicensesProvider.java | 11 ++++ .../lib/analysis/LicensesProviderImpl.java | 54 +++++++++++++++---- .../analysis/OutputFileConfiguredTarget.java | 13 +++++ .../rules/java/BazelJavaRuleClasses.java | 2 +- .../build/lib/packages/Attribute.java | 20 +++++++ .../build/lib/rules/cpp/CcToolchain.java | 16 +++++- .../build/lib/rules/java/JavaBinary.java | 2 +- 8 files changed, 116 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/google/devtools/build/lib/analysis/InputFileConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/InputFileConfiguredTarget.java index 904b4e040231f3..237498100739b0 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/InputFileConfiguredTarget.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/InputFileConfiguredTarget.java @@ -65,4 +65,14 @@ public String toString() { public final NestedSet getTransitiveLicenses() { return licenses; } + + @Override + public TargetLicense getOutputLicenses() { + return null; + } + + @Override + public boolean hasOutputLicenses() { + return false; + } } diff --git a/src/main/java/com/google/devtools/build/lib/analysis/LicensesProvider.java b/src/main/java/com/google/devtools/build/lib/analysis/LicensesProvider.java index 831744d21ba56d..8115d9dea9462b 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/LicensesProvider.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/LicensesProvider.java @@ -34,6 +34,17 @@ public interface LicensesProvider extends TransitiveInfoProvider { */ NestedSet getTransitiveLicenses(); + /** + * A label - license association for output_licenses. If there are no output_licenses it returns + * null. + */ + TargetLicense getOutputLicenses(); + + /** + * Return whether there is an output_licenses. + */ + boolean hasOutputLicenses(); + /** * License association for a particular target. */ diff --git a/src/main/java/com/google/devtools/build/lib/analysis/LicensesProviderImpl.java b/src/main/java/com/google/devtools/build/lib/analysis/LicensesProviderImpl.java index 0952d69274d29f..fd4f4675df4bc0 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/LicensesProviderImpl.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/LicensesProviderImpl.java @@ -14,11 +14,14 @@ package com.google.devtools.build.lib.analysis; +import com.google.common.collect.ListMultimap; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.collect.nestedset.Order; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; +import com.google.devtools.build.lib.packages.Attribute; +import com.google.devtools.build.lib.packages.AttributeMap; import com.google.devtools.build.lib.packages.License; import com.google.devtools.build.lib.packages.Rule; @@ -28,12 +31,15 @@ @Immutable public final class LicensesProviderImpl implements LicensesProvider { public static final LicensesProvider EMPTY = - new LicensesProviderImpl(NestedSetBuilder.emptySet(Order.LINK_ORDER)); + new LicensesProviderImpl(NestedSetBuilder.emptySet(Order.LINK_ORDER), null); private final NestedSet transitiveLicenses; + private final TargetLicense outputLicenses; - public LicensesProviderImpl(NestedSet transitiveLicenses) { + public LicensesProviderImpl( + NestedSet transitiveLicenses, TargetLicense outputLicenses) { this.transitiveLicenses = transitiveLicenses; + this.outputLicenses = outputLicenses; } /** @@ -47,29 +53,59 @@ public static LicensesProvider of(RuleContext ruleContext) { NestedSetBuilder builder = NestedSetBuilder.linkOrder(); BuildConfiguration configuration = ruleContext.getConfiguration(); Rule rule = ruleContext.getRule(); - License toolOutputLicense = rule.getToolOutputLicense(ruleContext.attributes()); + AttributeMap attributes = ruleContext.attributes(); + License toolOutputLicense = rule.getToolOutputLicense(attributes); + TargetLicense outputLicenses = + toolOutputLicense == null ? null : new TargetLicense(rule.getLabel(), toolOutputLicense); + if (configuration.isHostConfiguration() && toolOutputLicense != null) { if (toolOutputLicense != License.NO_LICENSE) { - builder.add(new TargetLicense(rule.getLabel(), toolOutputLicense)); + builder.add(outputLicenses); } } else { if (rule.getLicense() != License.NO_LICENSE) { builder.add(new TargetLicense(rule.getLabel(), rule.getLicense())); } - for (TransitiveInfoCollection dep : ruleContext.getConfiguredTargetMap().values()) { - LicensesProvider provider = dep.getProvider(LicensesProvider.class); - if (provider != null) { - builder.addTransitive(provider.getTransitiveLicenses()); + ListMultimap configuredMap = + ruleContext.getConfiguredTargetMap(); + + for (String depAttrName : attributes.getAttributeNames()) { + // Only add the transitive licenses for the attributes that do not have the output_licenses. + Attribute attribute = attributes.getAttributeDefinition(depAttrName); + for (TransitiveInfoCollection dep : configuredMap.get(depAttrName)) { + LicensesProvider provider = dep.getProvider(LicensesProvider.class); + if (provider == null) { + continue; + } + if (useOutputLicenses(attribute, configuration) && provider.hasOutputLicenses()) { + builder.add(provider.getOutputLicenses()); + } else { + builder.addTransitive(provider.getTransitiveLicenses()); + } } } } - return new LicensesProviderImpl(builder.build()); + return new LicensesProviderImpl(builder.build(), outputLicenses); + } + + private static boolean useOutputLicenses(Attribute attribute, BuildConfiguration configuration) { + return configuration.isHostConfiguration() || attribute.useOutputLicenses(); } @Override public NestedSet getTransitiveLicenses() { return transitiveLicenses; } + + @Override + public TargetLicense getOutputLicenses() { + return outputLicenses; + } + + @Override + public boolean hasOutputLicenses() { + return outputLicenses != null; + } } diff --git a/src/main/java/com/google/devtools/build/lib/analysis/OutputFileConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/OutputFileConfiguredTarget.java index 8ba3211da1eba5..e193a79994e9dc 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/OutputFileConfiguredTarget.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/OutputFileConfiguredTarget.java @@ -53,6 +53,19 @@ public NestedSet getTransitiveLicenses() { .getTransitiveLicenses(); } + @Override + public TargetLicense getOutputLicenses() { + return getProvider(LicensesProvider.class, LicensesProviderImpl.EMPTY) + .getOutputLicenses(); + } + + @Override + public boolean hasOutputLicenses() { + return getProvider(LicensesProvider.class, LicensesProviderImpl.EMPTY) + .hasOutputLicenses(); + } + + @Override public NestedSet getInstrumentedFiles() { return getProvider(InstrumentedFilesProvider.class, InstrumentedFilesProviderImpl.EMPTY) diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaRuleClasses.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaRuleClasses.java index d17e3dffd4cb1b..38a4b8297bda75 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaRuleClasses.java @@ -107,7 +107,7 @@ public static final class JavaBaseRule implements RuleDefinition { @Override public RuleClass build(Builder builder, RuleDefinitionEnvironment env) { return builder - .add(attr(":jvm", LABEL).cfg(HOST).value(JavaSemantics.JVM)) + .add(attr(":jvm", LABEL).value(JavaSemantics.JVM).useOutputLicenses()) .add(attr(":host_jdk", LABEL).cfg(HOST).value(JavaSemantics.HOST_JDK)) .add(attr("$jacoco_instrumentation", LABEL).cfg(HOST)) .build(); diff --git a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java index 12b40e46979bd7..420e6b81d1a778 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java +++ b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java @@ -297,6 +297,11 @@ private enum PropertyFlag { * policy would check it. */ SKIP_CONSTRAINTS_OVERRIDE, + + /** + * Whether we should use output_licenses to check the licences on this attribute. + */ + OUTPUT_LICENSES, } // TODO(bazel-team): modify this interface to extend Predicate and have an extra error @@ -535,6 +540,14 @@ public Builder orderIndependent() { return setPropertyFlag(PropertyFlag.ORDER_INDEPENDENT, "order-independent"); } + /** + * Mark the built attribute as to use output_licenses for license checking. + */ + public Builder useOutputLicenses() { + Preconditions.checkState(BuildType.isLabelType(type), "must be a label type"); + return setPropertyFlag(PropertyFlag.OUTPUT_LICENSES, "output_license"); + } + /** * Defines the configuration transition for this attribute. */ @@ -1864,6 +1877,13 @@ public boolean isOrderIndependent() { return getPropertyFlag(PropertyFlag.ORDER_INDEPENDENT); } + /** + * Returns true if output_licenses should be used for checking licensing. + */ + public boolean useOutputLicenses() { + return getPropertyFlag(PropertyFlag.OUTPUT_LICENSES); + } + /** * Returns the configuration transition for this attribute for label or label * list attributes. For other attributes it will always return {@code NONE}. diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java index 5ff24aa753955b..494e74ecf1cc28 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java @@ -237,7 +237,10 @@ public ConfiguredTarget create(RuleContext ruleContext) // but it is sort-of-kind-of a tool, but various parts of it are linked into the output... // ...so we trust the judgment of the author of the cc_toolchain rule to figure out what // licenses should be propagated to C++ targets. - License outputLicense = ruleContext.getRule().getToolOutputLicense(ruleContext.attributes()); + // TODO(elenairina): Remove this and use Attribute.Builder.useOutputLicenses() on the + // :cc_toolchain attribute instead. + final License outputLicense = + ruleContext.getRule().getToolOutputLicense(ruleContext.attributes()); if (outputLicense != null && outputLicense != License.NO_LICENSE) { final NestedSet license = NestedSetBuilder.create(Order.STABLE_ORDER, new TargetLicense(ruleContext.getLabel(), outputLicense)); @@ -246,6 +249,17 @@ public ConfiguredTarget create(RuleContext ruleContext) public NestedSet getTransitiveLicenses() { return license; } + + @Override + public TargetLicense getOutputLicenses() { + return new TargetLicense(label, outputLicense); + } + + @Override + public boolean hasOutputLicenses() { + return true; + } + }; builder.add(LicensesProvider.class, licensesProvider); diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java index 9175a25e2b0e4c..e40d8f793658fc 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java @@ -471,7 +471,7 @@ private void collectDefaultRunfiles(Runfiles.Builder builder, RuleContext ruleCo builder.addArtifacts((Iterable) common.getRuntimeClasspath()); // Add the JDK files if it comes from the source repository (see java_stub_template.txt). - TransitiveInfoCollection javabaseTarget = ruleContext.getPrerequisite(":jvm", Mode.HOST); + TransitiveInfoCollection javabaseTarget = ruleContext.getPrerequisite(":jvm", Mode.TARGET); if (javabaseTarget != null) { builder.addArtifacts( (Iterable) javabaseTarget.getProvider(FileProvider.class).getFilesToBuild());