blob: bacf3d749f4cada131a59511ff62cc404f6bc86a [file] [log] [blame]
// 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.devtools.build.lib.packages.License.DistributionType;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.List;
import java.util.Set;
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 DEFAULT =
PackageArgs.builder()
.setDefaultVisibility(RuleVisibility.PRIVATE)
.setDefaultTestOnly(false)
.setFeatures(FeatureSet.EMPTY)
.setLicense(License.NO_LICENSE)
.setDistribs(License.DEFAULT_DISTRIB)
.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 distributions value for the package. */
@Nullable
public abstract ImmutableSet<DistributionType> distribs();
/** 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);
public abstract Builder setDistribs(Set<DistributionType> 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)));
break;
case "default_testonly":
builder.setDefaultTestOnly(Type.BOOLEAN.convert(rawValue, what, labelConverter));
break;
case "default_deprecation":
builder.setDefaultDeprecation(Type.STRING.convert(rawValue, what, labelConverter));
break;
case "features":
builder.mergeFeatures(
FeatureSet.parse(Type.STRING_LIST.convert(rawValue, what, labelConverter)));
break;
case "licenses":
builder.setLicense(BuildType.LICENSE.convert(rawValue, what, labelConverter));
break;
case "distribs":
builder.setDistribs(BuildType.DISTRIBUTIONS.convert(rawValue, what, labelConverter));
break;
case "default_compatible_with":
builder.setDefaultCompatibleWith(
throwIfHasDupes(BuildType.LABEL_LIST.convert(rawValue, what, labelConverter), name));
break;
case "default_restricted_to":
builder.setDefaultRestrictedTo(
throwIfHasDupes(BuildType.LABEL_LIST.convert(rawValue, what, labelConverter), name));
break;
case "default_applicable_licenses":
case "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));
break;
case "default_hdrs_check":
builder.setDefaultHdrsCheck(Type.STRING.convert(rawValue, what, labelConverter));
break;
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.distribs() != null) {
builder.setDistribs(other.distribs());
}
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();
}
}