blob: 3f8db53ca1fdd82f954f7d9cb4dfaf7fb24bd9f1 [file] [log] [blame]
michajlocab889d2020-02-20 17:48:36 -08001// Copyright 2020 The Bazel Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package com.google.devtools.build.lib.packages;
16
michajlocab889d2020-02-20 17:48:36 -080017import com.google.devtools.build.lib.cmdline.Label;
michajlocab889d2020-02-20 17:48:36 -080018import com.google.devtools.build.lib.packages.License.DistributionType;
Googlerace99b52022-11-02 15:06:30 -070019import com.google.devtools.build.lib.server.FailureDetails.PackageLoading.Code;
michajlocab889d2020-02-20 17:48:36 -080020import java.util.List;
Googler31c51b92023-05-12 09:38:54 -070021import java.util.Map;
michajlocab889d2020-02-20 17:48:36 -080022import java.util.Set;
Googler0511bb42023-05-17 14:34:51 -070023import net.starlark.java.annot.Param;
24import net.starlark.java.annot.StarlarkMethod;
adonovan450c7ad2020-09-14 13:00:21 -070025import net.starlark.java.eval.EvalException;
Googler31c51b92023-05-12 09:38:54 -070026import net.starlark.java.eval.Starlark;
Googler31c51b92023-05-12 09:38:54 -070027import net.starlark.java.eval.StarlarkThread;
adonovan450c7ad2020-09-14 13:00:21 -070028import net.starlark.java.syntax.Location;
michajlocab889d2020-02-20 17:48:36 -080029
Googler31c51b92023-05-12 09:38:54 -070030/**
Googler0511bb42023-05-17 14:34:51 -070031 * Utility class encapsulating the standard definition of the {@code package()} function of BUILD
32 * files.
Googler31c51b92023-05-12 09:38:54 -070033 */
34public class PackageCallable {
michajlocab889d2020-02-20 17:48:36 -080035
Googler0511bb42023-05-17 14:34:51 -070036 protected PackageCallable() {}
37
38 public static final PackageCallable INSTANCE = new PackageCallable();
39
40 @StarlarkMethod(
41 name = "package",
42 documented = false, // documented in docgen/templates/be/functions.vm
43 extraKeywords = @Param(name = "kwargs", defaultValue = "{}"),
44 useStarlarkThread = true)
45 public Object packageCallable(Map<String, Object> kwargs, StarlarkThread thread)
46 throws EvalException {
47 Package.Builder pkgBuilder = PackageFactory.getContext(thread).pkgBuilder;
48 if (pkgBuilder.isPackageFunctionUsed()) {
49 throw new EvalException("'package' can only be used once per BUILD file");
50 }
51 pkgBuilder.setPackageFunctionUsed();
52
53 if (kwargs.isEmpty()) {
54 throw new EvalException("at least one argument must be given to the 'package' function");
55 }
56
57 Location loc = thread.getCallerLocation();
58 for (Map.Entry<String, Object> kwarg : kwargs.entrySet()) {
59 String name = kwarg.getKey();
60 Object rawValue = kwarg.getValue();
61 processParam(name, rawValue, pkgBuilder, loc);
62 }
63 return Starlark.NONE;
64 }
michajlocab889d2020-02-20 17:48:36 -080065
Googler31c51b92023-05-12 09:38:54 -070066 /**
Googler0511bb42023-05-17 14:34:51 -070067 * Handles one parameter. Subclasses can add new parameters by overriding this method and falling
68 * back on the super method when the parameter does not match.
Googler31c51b92023-05-12 09:38:54 -070069 */
Googler0511bb42023-05-17 14:34:51 -070070 protected void processParam(
71 String name, Object rawValue, Package.Builder pkgBuilder, Location loc) throws EvalException {
72 if (name.equals("default_visibility")) {
73 List<Label> value = convert(BuildType.LABEL_LIST, rawValue, pkgBuilder);
Googler91978392023-03-16 12:41:23 -070074 pkgBuilder.setDefaultVisibility(RuleVisibility.parse(value));
michajlocab889d2020-02-20 17:48:36 -080075
Googler0511bb42023-05-17 14:34:51 -070076 } else if (name.equals("default_testonly")) {
77 Boolean value = convert(Type.BOOLEAN, rawValue, pkgBuilder);
michajlocab889d2020-02-20 17:48:36 -080078 pkgBuilder.setDefaultTestonly(value);
michajlocab889d2020-02-20 17:48:36 -080079
Googler0511bb42023-05-17 14:34:51 -070080 } else if (name.equals("default_deprecation")) {
81 String value = convert(Type.STRING, rawValue, pkgBuilder);
michajlocab889d2020-02-20 17:48:36 -080082 pkgBuilder.setDefaultDeprecation(value);
michajlocab889d2020-02-20 17:48:36 -080083
Googler0511bb42023-05-17 14:34:51 -070084 } else if (name.equals("features")) {
85 List<String> value = convert(Type.STRING_LIST, rawValue, pkgBuilder);
michajlocab889d2020-02-20 17:48:36 -080086 pkgBuilder.addFeatures(value);
michajlocab889d2020-02-20 17:48:36 -080087
Googler0511bb42023-05-17 14:34:51 -070088 } else if (name.equals("licenses")) {
89 License value = convert(BuildType.LICENSE, rawValue, pkgBuilder);
michajlocab889d2020-02-20 17:48:36 -080090 pkgBuilder.setDefaultLicense(value);
michajlocab889d2020-02-20 17:48:36 -080091
Googler0511bb42023-05-17 14:34:51 -070092 } else if (name.equals("distribs")) {
93 Set<DistributionType> value = convert(BuildType.DISTRIBUTIONS, rawValue, pkgBuilder);
michajlocab889d2020-02-20 17:48:36 -080094 pkgBuilder.setDefaultDistribs(value);
Googler0511bb42023-05-17 14:34:51 -070095
96 } else if (name.equals("default_compatible_with")) {
97 List<Label> value = convert(BuildType.LABEL_LIST, rawValue, pkgBuilder);
98 pkgBuilder.setDefaultCompatibleWith(value, name, loc);
99
100 } else if (name.equals("default_restricted_to")) {
101 List<Label> value = convert(BuildType.LABEL_LIST, rawValue, pkgBuilder);
102 pkgBuilder.setDefaultRestrictedTo(value, name, loc);
103
104 } else if (name.equals("default_applicable_licenses")) {
105 List<Label> value = convert(BuildType.LABEL_LIST, rawValue, pkgBuilder);
106 if (!pkgBuilder.getDefaultPackageMetadata().isEmpty()) {
107 pkgBuilder.addEvent(
108 Package.error(
109 loc,
110 "Can not set both default_package_metadata and default_applicable_licenses."
111 + " Move all declarations to default_package_metadata.",
112 Code.INVALID_PACKAGE_SPECIFICATION));
113 }
114 pkgBuilder.setDefaultPackageMetadata(value, name, loc);
115
116 } else if (name.equals("default_package_metadata")) {
117 List<Label> value = convert(BuildType.LABEL_LIST, rawValue, pkgBuilder);
118 if (!pkgBuilder.getDefaultPackageMetadata().isEmpty()) {
119 pkgBuilder.addEvent(
120 Package.error(
121 loc,
122 "Can not set both default_package_metadata and default_applicable_licenses."
123 + " Move all declarations to default_package_metadata.",
124 Code.INVALID_PACKAGE_SPECIFICATION));
125 }
126 pkgBuilder.setDefaultPackageMetadata(value, name, loc);
127
128 } else {
129 throw Starlark.errorf("unexpected keyword argument: %s", name);
michajlocab889d2020-02-20 17:48:36 -0800130 }
131 }
132
Googler0511bb42023-05-17 14:34:51 -0700133 protected static <T> T convert(Type<T> type, Object value, Package.Builder pkgBuilder)
134 throws EvalException {
135 return type.convert(value, "'package' argument", pkgBuilder.getLabelConverter());
michajlocab889d2020-02-20 17:48:36 -0800136 }
137}