| // Copyright 2023 The Bazel Authors. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| package com.google.devtools.build.lib.packages; |
| |
| import com.google.auto.value.AutoValue; |
| import com.google.common.base.Joiner; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableSet; |
| import com.google.common.collect.ImmutableSortedSet; |
| import com.google.devtools.build.lib.analysis.config.FeatureSet; |
| import com.google.devtools.build.lib.cmdline.Label; |
| import com.google.devtools.build.lib.collect.CollectionUtils; |
| import com.google.errorprone.annotations.CanIgnoreReturnValue; |
| import java.util.List; |
| import javax.annotation.Nullable; |
| import net.starlark.java.eval.EvalException; |
| import net.starlark.java.eval.Starlark; |
| |
| /** |
| * A group of {@link Package} argument values that may be provided by `package()` or `repo()` calls. |
| * |
| * <p>Unless otherwise specified, these are only used when the rule does not provide an explicit |
| * override value in the associated attribute. |
| */ |
| @AutoValue |
| public abstract class PackageArgs { |
| public static final PackageArgs EMPTY = PackageArgs.builder().build(); |
| |
| public static final PackageArgs DEFAULT = |
| PackageArgs.builder() |
| .setDefaultVisibility(RuleVisibility.PRIVATE) |
| .setDefaultTestOnly(false) |
| .setFeatures(FeatureSet.EMPTY) |
| .setLicense(License.NO_LICENSE) |
| .setDefaultCompatibleWith(ImmutableSet.of()) |
| .setDefaultRestrictedTo(ImmutableSet.of()) |
| .setDefaultPackageMetadata(ImmutableList.of()) |
| .build(); |
| |
| /** The default visibility value for the package. */ |
| @Nullable |
| public abstract RuleVisibility defaultVisibility(); |
| |
| /** The default testonly value for the package. */ |
| @Nullable |
| public abstract Boolean defaultTestOnly(); |
| |
| /** The default deprecation value for the package. */ |
| @Nullable |
| public abstract String defaultDeprecation(); |
| |
| /** |
| * The default (generally C/C++) features value for the package. |
| * |
| * <p>Note that this is actually additive with features set by a rule where the rule has priority |
| * for turning specific features on or off. |
| */ |
| public abstract FeatureSet features(); |
| |
| /** The default license value for the package. */ |
| @Nullable |
| public abstract License license(); |
| |
| /** The default {@link RuleClass#COMPATIBLE_ENVIRONMENT_ATTR} value for the package. */ |
| @Nullable |
| public abstract ImmutableSet<Label> defaultCompatibleWith(); |
| |
| /** The default {@link RuleClass#RESTRICTED_ENVIRONMENT_ATTR} value for the package. */ |
| @Nullable |
| public abstract ImmutableSet<Label> defaultRestrictedTo(); |
| |
| /** The default package metadata list value for the package. */ |
| @Nullable |
| public abstract ImmutableList<Label> defaultPackageMetadata(); |
| |
| // TODO(blaze-team): this should just act like other attributes in that |
| // it is public and does not have getters defined |
| /** The default (C/C++) header strictness checking mode for the package. */ |
| @Nullable |
| abstract String defaultHdrsCheck(); |
| |
| /** Gets the default header checking mode. */ |
| public String getDefaultHdrsCheck() { |
| return defaultHdrsCheck() != null ? defaultHdrsCheck() : "strict"; |
| } |
| |
| /** Returns whether the default header checking mode has been set or it is the default value. */ |
| public boolean isDefaultHdrsCheckSet() { |
| return defaultHdrsCheck() != null; |
| } |
| |
| public static Builder builder() { |
| return new AutoValue_PackageArgs.Builder().setFeatures(FeatureSet.EMPTY); |
| } |
| |
| abstract Builder toBuilder(); |
| |
| /** Builder type for {@link PackageArgs}. */ |
| @AutoValue.Builder |
| public abstract static class Builder { |
| public abstract Builder setDefaultVisibility(RuleVisibility x); |
| |
| public abstract Builder setDefaultTestOnly(Boolean x); |
| |
| public abstract Builder setDefaultDeprecation(String x); |
| |
| abstract FeatureSet features(); |
| |
| public abstract Builder setFeatures(FeatureSet x); |
| |
| @CanIgnoreReturnValue |
| public final Builder mergeFeatures(FeatureSet x) { |
| return setFeatures(FeatureSet.merge(features(), x)); |
| } |
| |
| public abstract Builder setLicense(License x); |
| |
| /** Note that we don't check dupes in this method. Check beforehand! */ |
| public abstract Builder setDefaultCompatibleWith(Iterable<Label> x); |
| |
| /** Note that we don't check dupes in this method. Check beforehand! */ |
| public abstract Builder setDefaultRestrictedTo(Iterable<Label> x); |
| |
| @Nullable |
| abstract ImmutableList<Label> defaultPackageMetadata(); |
| |
| /** Note that we don't check dupes in this method. Check beforehand! */ |
| public abstract Builder setDefaultPackageMetadata(List<Label> x); |
| |
| public abstract Builder setDefaultHdrsCheck(String x); |
| |
| public abstract PackageArgs build(); |
| } |
| |
| private static List<Label> throwIfHasDupes(List<Label> labels, String what) throws EvalException { |
| var dupes = ImmutableSortedSet.copyOf(CollectionUtils.duplicatedElementsOf(labels)); |
| if (!dupes.isEmpty()) { |
| throw Starlark.errorf("duplicate label(s) in %s: %s", what, Joiner.on(", ").join(dupes)); |
| } |
| return labels; |
| } |
| |
| /** |
| * Processes the given Starlark parameter to the {@code package()/repo()} call into a field on a |
| * {@link Builder} object. |
| */ |
| public static void processParam( |
| String name, Object rawValue, String what, LabelConverter labelConverter, Builder builder) |
| throws EvalException { |
| switch (name) { |
| case "default_visibility" -> |
| builder.setDefaultVisibility( |
| RuleVisibility.parse(BuildType.LABEL_LIST.convert(rawValue, what, labelConverter))); |
| case "default_testonly" -> |
| builder.setDefaultTestOnly(Type.BOOLEAN.convert(rawValue, what, labelConverter)); |
| case "default_deprecation" -> |
| builder.setDefaultDeprecation(Type.STRING.convert(rawValue, what, labelConverter)); |
| case "features" -> |
| builder.mergeFeatures( |
| FeatureSet.parse(Types.STRING_LIST.convert(rawValue, what, labelConverter))); |
| case "licenses" -> |
| builder.setLicense(BuildType.LICENSE.convert(rawValue, what, labelConverter)); |
| case "default_compatible_with" -> |
| builder.setDefaultCompatibleWith( |
| throwIfHasDupes(BuildType.LABEL_LIST.convert(rawValue, what, labelConverter), name)); |
| case "default_restricted_to" -> |
| builder.setDefaultRestrictedTo( |
| throwIfHasDupes(BuildType.LABEL_LIST.convert(rawValue, what, labelConverter), name)); |
| case "default_applicable_licenses", "default_package_metadata" -> { |
| if (builder.defaultPackageMetadata() != null) { |
| throw Starlark.errorf( |
| "Can not set both default_package_metadata and default_applicable_licenses." |
| + " Move all declarations to default_package_metadata."); |
| } |
| builder.setDefaultPackageMetadata( |
| throwIfHasDupes(BuildType.LABEL_LIST.convert(rawValue, what, labelConverter), name)); |
| } |
| case "default_hdrs_check" -> |
| builder.setDefaultHdrsCheck(Type.STRING.convert(rawValue, what, labelConverter)); |
| default -> throw Starlark.errorf("unexpected keyword argument: %s", name); |
| } |
| } |
| |
| /** |
| * Returns a new {@link PackageArgs} containing the result of merging {@code other} into {@code |
| * this}. {@code other}'s fields take precedence if specified. |
| */ |
| public PackageArgs mergeWith(PackageArgs other) { |
| Builder builder = toBuilder(); |
| if (other.defaultVisibility() != null) { |
| builder.setDefaultVisibility(other.defaultVisibility()); |
| } |
| if (other.defaultTestOnly() != null) { |
| builder.setDefaultTestOnly(other.defaultTestOnly()); |
| } |
| if (other.defaultDeprecation() != null) { |
| builder.setDefaultDeprecation(other.defaultDeprecation()); |
| } |
| if (!other.features().equals(FeatureSet.EMPTY)) { |
| builder.mergeFeatures(other.features()); |
| } |
| if (other.license() != null) { |
| builder.setLicense(other.license()); |
| } |
| if (other.defaultCompatibleWith() != null) { |
| builder.setDefaultCompatibleWith(other.defaultCompatibleWith()); |
| } |
| if (other.defaultRestrictedTo() != null) { |
| builder.setDefaultRestrictedTo(other.defaultRestrictedTo()); |
| } |
| if (other.defaultPackageMetadata() != null) { |
| builder.setDefaultPackageMetadata(other.defaultPackageMetadata()); |
| } |
| if (other.defaultHdrsCheck() != null) { |
| builder.setDefaultHdrsCheck(other.defaultHdrsCheck()); |
| } |
| return builder.build(); |
| } |
| } |