| // 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(); | |
| /** The transitive visibility settings this package says it belongs to. */ | |
| @Nullable | |
| public abstract Label transitiveVisibility(); | |
| // 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 setTransitiveVisibility(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)); | |
| case "transitive_visibility" -> { | |
| Label transitiveVisibility = BuildType.LABEL.convert(rawValue, what, labelConverter); | |
| builder.setTransitiveVisibility(transitiveVisibility); | |
| } | |
| 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.transitiveVisibility() != null) { | |
| builder.setTransitiveVisibility(other.transitiveVisibility()); | |
| } | |
| if (other.defaultHdrsCheck() != null) { | |
| builder.setDefaultHdrsCheck(other.defaultHdrsCheck()); | |
| } | |
| return builder.build(); | |
| } | |
| } |