Add new global attribute: applicable_licenses - Package level default with default_applicable_licenses - guarded by --incompatible_applicable_licenses (default true for Blaze, false for Bazel) Import features: - applicable_licenses is not configurable. Software does not get a different license in different environments. The license it is provided under dictates what type of environments you may use it in. - applicable_licenses is exempt from compatible_with checks. For the same reason. Since there is currently no actual behavior within Bazel, the test cases are located with @rules_license. In the future, we will add provider checking to applicable_licenses. (b/148601291), at which point there must be positive and negative tests alongside the Bazel code. RELNOTES: Add new global attribute: applicable_licenses - Package level default with default_applicable_licenses - guarded by --incompatible_applicable_licenses (default true for Blaze, false for Bazel) - In support of https://docs.google.com/document/d/1uwBuhAoBNrw8tmFs-NxlssI6VRolidGYdYqagLqHWt8/edit# PiperOrigin-RevId: 296042678
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BaseRuleClasses.java b/src/main/java/com/google/devtools/build/lib/analysis/BaseRuleClasses.java index 18daf4d..53ce39a 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/BaseRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/BaseRuleClasses.java
@@ -331,7 +331,14 @@ "special logic for constraints and select: see ConstraintSemantics")) .add( attr(RuleClass.CONFIG_SETTING_DEPS_ATTRIBUTE, LABEL_LIST) - .nonconfigurable("stores configurability keys")); + .nonconfigurable("stores configurability keys")) + .add( + attr(RuleClass.APPLICABLE_LICENSES_ATTR, LABEL_LIST) + .cfg(HostTransition.createFactory()) + .allowedFileTypes(FileTypeSet.NO_FILE) + // TODO(b/148601291): Require provider to be "LicenseInfo". + .dontCheckConstraints() + .nonconfigurable("applicable_licenses is not configurable")); } public static RuleClass.Builder nameAttribute(RuleClass.Builder builder) {
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java b/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java index 61daebd..9433b26 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java
@@ -482,6 +482,14 @@ if (toolchainContext != null) { outgoingLabels.putAll(TOOLCHAIN_DEPENDENCY, toolchainContext.resolvedToolchainLabels()); } + + if (!rule.isAttributeValueExplicitlySpecified(RuleClass.APPLICABLE_LICENSES_ATTR)) { + addExplicitDeps( + outgoingLabels, + rule, + RuleClass.APPLICABLE_LICENSES_ATTR, + rule.getPackage().getDefaultApplicableLicenses()); + } } private void resolveAttributes(
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Package.java b/src/main/java/com/google/devtools/build/lib/packages/Package.java index 45db928..5ae743e 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/Package.java +++ b/src/main/java/com/google/devtools/build/lib/packages/Package.java
@@ -167,6 +167,9 @@ */ private ImmutableList<Label> skylarkFileDependencies; + /** The package's default "applicable_licenses" attribute. */ + private Set<Label> defaultApplicableLicenses = ImmutableSet.of(); + /** * The package's default "licenses" and "distribs" attributes, as specified * in calls to licenses() and distribs() in the BUILD file. @@ -296,6 +299,14 @@ } /** + * Sets the default 'applicable_licenses" value for this package attribute when not explicitly + * specified by the rule. + */ + private void setDefaultApplicableLicenses(Set<Label> licenses) { + defaultApplicableLicenses = licenses; + } + + /** * Sets the default value to use for a rule's {@link RuleClass#COMPATIBLE_ENVIRONMENT_ATTR} * attribute when not explicitly specified by the rule. */ @@ -659,6 +670,11 @@ return defaultVisibilitySet; } + /** Gets the licenses list for the default applicable_licenses declared by this package. */ + public Set<Label> getDefaultApplicableLicenses() { + return defaultApplicableLicenses; + } + /** * Gets the parsed license object for the default license * declared by this package. @@ -830,6 +846,7 @@ @Nullable private IOException ioException = null; private boolean containsErrors = false; + private ImmutableList<Label> defaultApplicableLicenses = ImmutableList.of(); private License defaultLicense = License.NO_LICENSE; private Set<License.DistributionType> defaultDistributionSet = License.DEFAULT_DISTRIB; @@ -1149,6 +1166,23 @@ } /** + * Sets the default value to use for a rule's {@link RuleClass#APPLICABLE_LICENSES_ATTR} + * attribute when not explicitly specified by the rule. Records a package error if any labels + * are duplicated. + */ + void setDefaultApplicableLicenses(List<Label> licenses, String attrName, Location location) { + if (!checkForDuplicateLabels( + licenses, "package " + pkg.getName(), attrName, location, builderEventHandler)) { + setContainsErrors(); + } + pkg.setDefaultApplicableLicenses(ImmutableSet.copyOf(licenses)); + } + + ImmutableList<Label> getDefaultApplicableLicenses() { + return defaultApplicableLicenses; + } + + /** * Sets the default license for this package. */ void setDefaultLicense(License license) {
diff --git a/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java b/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java index 237f0fa..acda081 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java +++ b/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
@@ -199,6 +199,26 @@ } } + /** + * Declares the package() attribute specifying the default value for {@link + * com.google.devtools.build.lib.packages.RuleClass#APPLICABLE_LICENSES_ATTR} when not explicitly + * specified. + */ + private static class DefaultApplicableLicenses extends PackageArgument<List<Label>> { + private static final String DEFAULT_APPLICABLE_LICENSES_ATTRIBUTE = + "default_applicable_licenses"; + + private DefaultApplicableLicenses() { + super(DEFAULT_APPLICABLE_LICENSES_ATTRIBUTE, BuildType.LABEL_LIST); + } + + @Override + protected void process(Package.Builder pkgBuilder, Location location, List<Label> value) { + pkgBuilder.setDefaultApplicableLicenses( + value, DEFAULT_APPLICABLE_LICENSES_ATTRIBUTE, location); + } + } + private static class DefaultLicenses extends PackageArgument<License> { private DefaultLicenses() { super("licenses", BuildType.LICENSE); @@ -448,6 +468,7 @@ ImmutableList.<PackageArgument<?>>builder() .add(new DefaultDeprecation()) .add(new DefaultDistribs()) + .add(new DefaultApplicableLicenses()) .add(new DefaultLicenses()) .add(new DefaultTestOnly()) .add(new DefaultVisibility())
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 301cc77..4e78bea 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
@@ -135,6 +135,10 @@ public static final PathFragment EXPERIMENTAL_PREFIX = PathFragment.create("experimental"); public static final String EXEC_COMPATIBLE_WITH_ATTR = "exec_compatible_with"; public static final String EXEC_PROPERTIES = "exec_properties"; + /* + * The attribute that declares the set of license labels which apply to this target. + */ + public static final String APPLICABLE_LICENSES_ATTR = "applicable_licenses"; /** * A constraint for the package name of the Rule instances. @@ -2183,6 +2187,11 @@ */ private static Object getAttributeNoncomputedDefaultValue(Attribute attr, Package.Builder pkgBuilder) { + // TODO(b/149505729): Determine the right semantics for someone trying to define their own + // attribute named applicable_licenses. + if (attr.getName().equals("applicable_licenses")) { + return pkgBuilder.getDefaultApplicableLicenses(); + } // Starlark rules may define their own "licenses" attributes with different types - // we shouldn't trigger the special "licenses" on those cases. if (attr.getName().equals("licenses") && attr.getType() == BuildType.LICENSE) {