Ignore package-level licenses on config_setting. config_setting reflects build artifacts which we typically don't consider as part of licensing for third-party packages, and doesn't directly impact the output binary. As a result, it's more likely that a package-level setting interferes with determining licensing of a binary. RELNOTES: Ignore package-level licenses on config_setting. PiperOrigin-RevId: 231298026
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Rule.java b/src/main/java/com/google/devtools/build/lib/packages/Rule.java index 0c805da..ae01bd2 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/Rule.java +++ b/src/main/java/com/google/devtools/build/lib/packages/Rule.java
@@ -648,6 +648,8 @@ if (isAttrDefined("licenses", BuildType.LICENSE) && isAttributeValueExplicitlySpecified("licenses")) { return NonconfigurableAttributeMapper.of(this).get("licenses", BuildType.LICENSE); + } else if (getRuleClassObject().ignorePackageLicenses()) { + return License.NO_LICENSE; } else { return getPackage().getDefaultLicense(); }
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java index 1af192c..c5152ed 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java +++ b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
@@ -647,6 +647,7 @@ private boolean isAnalysisTest = false; private boolean isConfigMatcher = false; private boolean hasFunctionTransitionWhitelist = false; + private boolean ignorePackageLicenses = false; private ImplicitOutputsFunction implicitOutputsFunction = ImplicitOutputsFunction.NONE; private RuleTransitionFactory transitionFactory; private ConfiguredTargetFactory<?, ?, ?> configuredTargetFactory = null; @@ -808,6 +809,7 @@ isExecutableSkylark, isAnalysisTest, hasFunctionTransitionWhitelist, + ignorePackageLicenses, implicitOutputsFunction, isConfigMatcher, transitionFactory, @@ -1201,6 +1203,16 @@ return this; } + /** This rule class ignores package-level licenses. */ + public Builder setIgnorePackageLicenses() { + this.ignorePackageLicenses = true; + return this; + } + + public boolean ignorePackageLicenses() { + return this.ignorePackageLicenses; + } + public RuleClassType getType() { return this.type; } @@ -1380,6 +1392,7 @@ private final boolean isAnalysisTest; private final boolean isConfigMatcher; private final boolean hasFunctionTransitionWhitelist; + private final boolean ignorePackageLicenses; /** * A (unordered) mapping from attribute names to small integers indexing into @@ -1507,6 +1520,7 @@ boolean isExecutableSkylark, boolean isAnalysisTest, boolean hasFunctionTransitionWhitelist, + boolean ignorePackageLicenses, ImplicitOutputsFunction implicitOutputsFunction, boolean isConfigMatcher, RuleTransitionFactory transitionFactory, @@ -1556,6 +1570,7 @@ this.isExecutableSkylark = isExecutableSkylark; this.isAnalysisTest = isAnalysisTest; this.hasFunctionTransitionWhitelist = hasFunctionTransitionWhitelist; + this.ignorePackageLicenses = ignorePackageLicenses; this.configurationFragmentPolicy = configurationFragmentPolicy; this.supportsConstraintChecking = supportsConstraintChecking; this.requiredToolchains = ImmutableSet.copyOf(requiredToolchains); @@ -2072,6 +2087,10 @@ */ private static void checkThirdPartyRuleHasLicense(Rule rule, Package.Builder pkgBuilder, EventHandler eventHandler) { + if (rule.getRuleClassObject().ignorePackageLicenses()) { + // A package license is sufficient; ignore rules that don't include it. + return; + } if (isThirdPartyPackage(rule.getLabel().getPackageIdentifier())) { License license = rule.getLicense(); if (license == null) { @@ -2408,6 +2427,11 @@ return hasFunctionTransitionWhitelist; } + /** Returns true if this rule class should ignore package-level licenses. */ + public boolean ignorePackageLicenses() { + return ignorePackageLicenses; + } + public ImmutableSet<Label> getRequiredToolchains() { return requiredToolchains; }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigRuleClasses.java index bf5e9db..fdb00ec 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigRuleClasses.java
@@ -139,6 +139,7 @@ @Override public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) { return builder + .setIgnorePackageLicenses() .requiresConfigurationFragments(PlatformConfiguration.class) .add( attr(TOOLS_REPOSITORY_ATTRIBUTE, STRING)
diff --git a/src/test/java/com/google/devtools/build/lib/packages/RuleClassTest.java b/src/test/java/com/google/devtools/build/lib/packages/RuleClassTest.java index 85ba7fc..c43ff8a 100644 --- a/src/test/java/com/google/devtools/build/lib/packages/RuleClassTest.java +++ b/src/test/java/com/google/devtools/build/lib/packages/RuleClassTest.java
@@ -888,6 +888,7 @@ outputsDefaultExecutable, isAnalysisTest, /* hasFunctionTransitionWhitelist=*/ false, + /* ignorePackageLicenses=*/ false, implicitOutputsFunction, /*isConfigMatcher=*/ false, transitionFactory,
diff --git a/src/test/java/com/google/devtools/build/lib/rules/config/ConfigSettingTest.java b/src/test/java/com/google/devtools/build/lib/rules/config/ConfigSettingTest.java index ffe0bc6..1a11fa0 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/config/ConfigSettingTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/config/ConfigSettingTest.java
@@ -26,6 +26,7 @@ import com.google.devtools.build.lib.analysis.util.BuildViewTestCase; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.cmdline.RepositoryName; +import com.google.devtools.build.lib.packages.License.LicenseType; import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; import com.google.devtools.build.lib.testutil.TestConstants; @@ -37,6 +38,7 @@ import com.google.devtools.common.options.OptionMetadataTag; import com.google.devtools.common.options.OptionsParser; import java.util.Map; +import java.util.Set; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -1426,5 +1428,70 @@ " ],", ");"); } -} + private Set<LicenseType> getLicenses(String label) throws Exception { + return getTarget(label).getLicense().getLicenseTypes(); + } + + /** Tests that default license behavior is unaffected. */ + @Test + public void licensesDefault() throws Exception { + scratch.file( + "test/BUILD", + "config_setting(", + " name = 'match',", + " values = {", + " 'copt': '-Dfoo',", + " })"); + + useConfiguration("--copt", "-Dfoo"); + assertThat(getLicenses("//test:match")).containsExactly(LicenseType.NONE); + } + + /** Tests that third-party doesn't require a license from config_setting. */ + @Test + public void thirdPartyLicenseRequirement() throws Exception { + scratch.file( + "third_party/test/BUILD", + "config_setting(", + " name = 'match',", + " values = {", + " 'copt': '-Dfoo',", + " })"); + + useConfiguration("--copt", "-Dfoo"); + assertThat(getLicenses("//third_party/test:match")).containsExactly(LicenseType.NONE); + } + + /** Tests that package-wide licenses are ignored by config_setting. */ + @Test + public void packageLicensesIgnored() throws Exception { + scratch.file( + "test/BUILD", + "licenses(['restricted'])", + "config_setting(", + " name = 'match',", + " values = {", + " 'copt': '-Dfoo',", + " })"); + + useConfiguration("--copt", "-Dfoo"); + assertThat(getLicenses("//test:match")).containsExactly(LicenseType.NONE); + } + + /** Tests that rule-specific licenses are still used by config_setting. */ + @Test + public void ruleLicensesUsed() throws Exception { + scratch.file( + "test/BUILD", + "config_setting(", + " name = 'match',", + " licenses = ['restricted'],", + " values = {", + " 'copt': '-Dfoo',", + " })"); + + useConfiguration("--copt", "-Dfoo"); + assertThat(getLicenses("//test:match")).containsExactly(LicenseType.RESTRICTED); + } +}