diff --git a/src/main/java/com/google/devtools/build/lib/cmdline/Label.java b/src/main/java/com/google/devtools/build/lib/cmdline/Label.java index 82e3ed16db6dfc..e9a663c49aa824 100644 --- a/src/main/java/com/google/devtools/build/lib/cmdline/Label.java +++ b/src/main/java/com/google/devtools/build/lib/cmdline/Label.java @@ -281,9 +281,10 @@ public RepositoryName getRepository() { name = "package", structField = true, doc = - "The package part of this label. " - + "For instance:
" - + "
Label(\"//pkg/foo:abc\").package == \"pkg/foo\"
") + "The name of the package containing the target referred to by this label, without the" + + " repository name. For instance:
Label(\"@@repo//pkg/foo:abc\").package ==" + + " \"pkg/foo\"") public String getPackageName() { return packageIdentifier.getPackageFragment().getPathString(); } @@ -300,9 +301,9 @@ public String getPackageName() { name = "workspace_root", structField = true, doc = - "Returns the execution root for the workspace of this label, relative to the execroot. " - + "For instance:
" - + "
Label(\"@repo//pkg/foo:abc\").workspace_root =="
+          "Returns the execution root for the repository containing the target referred to by this"
+              + " label, relative to the execroot. For instance:
Label(\"@repo//pkg/foo:abc\").workspace_root ==" + " \"external/repo\"
", useStarlarkSemantics = true) @Deprecated @@ -351,9 +352,8 @@ public PathFragment toPathFragment() { name = "name", structField = true, doc = - "The name of this label within the package. " - + "For instance:
" - + "
Label(\"//pkg/foo:abc\").name == \"abc\"
") + "The name of the target referred to by this label. For instance:
" + + "
Label(\"@@foo//pkg/foo:abc\").name == \"abc\"
") public String getName() { return name; } @@ -433,20 +433,41 @@ public String getShorthandDisplayForm(RepositoryMapping mainRepositoryMapping) { name = "workspace_name", structField = true, doc = - "The repository part of this label. For instance, " - + "
Label(\"@foo//bar:baz\").workspace_name"
-              + " == \"foo\"
") + "Deprecated. The field name \"workspace name\" is a misnomer here; use" + + " the identically-behaving Label.repo_name" + + " instead.

The canonical name of the repository containing the target referred to" + + " by this label, without any leading at-signs (@). For instance, Label(\"@@foo//bar:baz\").workspace_name == \"foo\"", + enableOnlyWithFlag = BuildLanguageOptions.INCOMPATIBLE_ENABLE_DEPRECATED_LABEL_APIS) + @Deprecated public String getWorkspaceName() throws EvalException { checkRepoVisibilityForStarlark("workspace_name"); return packageIdentifier.getRepository().getName(); } + /** Return the name of the repository label refers to without the leading `at` symbol. */ + @StarlarkMethod( + name = "repo_name", + structField = true, + doc = + "The canonical name of the repository containing the target referred to by this label," + + " without any leading at-signs (@). For instance, Label(\"@@foo//bar:baz\").repo_name == \"foo\"") + public String getRepoName() throws EvalException { + checkRepoVisibilityForStarlark("repo_name"); + return packageIdentifier.getRepository().getName(); + } + /** * Returns a label in the same package as this label with the given target name. * * @throws LabelSyntaxException if {@code targetName} is not a valid target name */ - public Label getLocalTargetLabel(String targetName) throws LabelSyntaxException { + @StarlarkMethod( + name = "same_package_label", + doc = "Creates a label in the same package as this label with the given target name.", + parameters = {@Param(name = "target_name", doc = "The target name of the new label.")}) + public Label getSamePackageLabel(String targetName) throws LabelSyntaxException { return create(packageIdentifier, targetName); } @@ -462,34 +483,38 @@ public Label getLocalTargetLabel(String targetName) throws LabelSyntaxException @StarlarkMethod( name = "relative", doc = - // TODO(#14503): Fix the documentation. - "Resolves a label that is either absolute (starts with //) or relative to " - + "the current package. If this label is in a remote repository, the argument will " - + "be resolved relative to that repository. If the argument contains a repository " - + "name, the current label is ignored and the argument is returned as-is, except " - + "that the repository name is rewritten if it is in the current repository mapping. " - + "Reserved labels will also be returned as-is.
" - + "For example:
" - + "

\n"
+          "Deprecated. This method behaves surprisingly when used with an argument"
+              + " containing an apparent repo name. Prefer Label.same_package_label(), native.package_relative_label(),"
+              + " or Label() instead.

Resolves a label that" + + " is either absolute (starts with //) or relative to the current" + + " package. If this label is in a remote repository, the argument will be resolved" + + " relative to that repository. If the argument contains a repository name, the" + + " current label is ignored and the argument is returned as-is, except that the" + + " repository name is rewritten if it is in the current repository mapping. Reserved" + + " labels will also be returned as-is.
For example:
\n" + "Label(\"//foo/bar:baz\").relative(\":quux\") == Label(\"//foo/bar:quux\")\n" + "Label(\"//foo/bar:baz\").relative(\"//wiz:quux\") == Label(\"//wiz:quux\")\n" - + "Label(\"@repo//foo/bar:baz\").relative(\"//wiz:quux\") == " - + "Label(\"@repo//wiz:quux\")\n" - + "Label(\"@repo//foo/bar:baz\").relative(\"//visibility:public\") == " - + "Label(\"//visibility:public\")\n" - + "Label(\"@repo//foo/bar:baz\").relative(\"@other//wiz:quux\") == " - + "Label(\"@other//wiz:quux\")\n" - + "

" - + "

If the repository mapping passed in is {'@other' : '@remapped'}, " - + "then the following remapping will take place:
" - + "

\n"
-              + "Label(\"@repo//foo/bar:baz\").relative(\"@other//wiz:quux\") == "
-              + "Label(\"@remapped//wiz:quux\")\n"
+              + "Label(\"@repo//foo/bar:baz\").relative(\"//wiz:quux\") =="
+              + " Label(\"@repo//wiz:quux\")\n"
+              + "Label(\"@repo//foo/bar:baz\").relative(\"//visibility:public\") =="
+              + " Label(\"//visibility:public\")\n"
+              + "Label(\"@repo//foo/bar:baz\").relative(\"@other//wiz:quux\") =="
+              + " Label(\"@other//wiz:quux\")\n"
+              + "

If the repository mapping passed in is {'@other' :" + + " '@remapped'}, then the following remapping will take place:
\n" + + "Label(\"@repo//foo/bar:baz\").relative(\"@other//wiz:quux\") ==" + + " Label(\"@remapped//wiz:quux\")\n" + "", parameters = { @Param(name = "relName", doc = "The label that will be resolved relative to this one.") }, + enableOnlyWithFlag = BuildLanguageOptions.INCOMPATIBLE_ENABLE_DEPRECATED_LABEL_APIS, useStarlarkThread = true) + @Deprecated public Label getRelative(String relName, StarlarkThread thread) throws LabelSyntaxException { return parseWithPackageContext( relName, diff --git a/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeModule.java b/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeModule.java index 66fb2fa2173ce6..0cfefe14e27b42 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeModule.java +++ b/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeModule.java @@ -608,18 +608,21 @@ public NoneType exportsFiles( @Override public String packageName(StarlarkThread thread) throws EvalException { BazelStarlarkContext.checkLoadingPhase(thread, "native.package_name"); - PackageIdentifier packageId = - PackageFactory.getContext(thread).getBuilder().getPackageIdentifier(); + PackageIdentifier packageId = getContext(thread).getBuilder().getPackageIdentifier(); return packageId.getPackageFragment().getPathString(); } @Override public String repositoryName(StarlarkThread thread) throws EvalException { BazelStarlarkContext.checkLoadingPhase(thread, "native.repository_name"); - PackageIdentifier packageId = - PackageFactory.getContext(thread).getBuilder().getPackageIdentifier(); // for legacy reasons, this is prefixed with a single '@'. - return '@' + packageId.getRepository().getName(); + return '@' + repoName(thread); + } + + @Override + public String repoName(StarlarkThread thread) throws EvalException { + BazelStarlarkContext.checkLoadingPhase(thread, "native.repo_name"); + return getContext(thread).getBuilder().getPackageIdentifier().getRepository().getName(); } @Override @@ -630,7 +633,7 @@ public Label packageRelativeLabel(Object input, StarlarkThread thread) throws Ev } try { String s = (String) input; - return PackageFactory.getContext(thread).getBuilder().getLabelConverter().convert(s); + return getContext(thread).getBuilder().getLabelConverter().convert(s); } catch (LabelSyntaxException e) { throw Starlark.errorf("invalid label in native.package_relative_label: %s", e.getMessage()); } @@ -640,14 +643,14 @@ public Label packageRelativeLabel(Object input, StarlarkThread thread) throws Ev @Nullable public String moduleName(StarlarkThread thread) throws EvalException { BazelStarlarkContext.checkLoadingPhase(thread, "native.module_name"); - return PackageFactory.getContext(thread).getBuilder().getAssociatedModuleName().orElse(null); + return getContext(thread).getBuilder().getAssociatedModuleName().orElse(null); } @Override @Nullable public String moduleVersion(StarlarkThread thread) throws EvalException { BazelStarlarkContext.checkLoadingPhase(thread, "native.module_version"); - return PackageFactory.getContext(thread).getBuilder().getAssociatedModuleVersion().orElse(null); + return getContext(thread).getBuilder().getAssociatedModuleVersion().orElse(null); } private static Dict getRuleDict(Rule rule, Mutability mu) throws EvalException { diff --git a/src/main/java/com/google/devtools/build/lib/packages/semantics/BuildLanguageOptions.java b/src/main/java/com/google/devtools/build/lib/packages/semantics/BuildLanguageOptions.java index 71d543e45a4faa..9575a929c7ad92 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/semantics/BuildLanguageOptions.java +++ b/src/main/java/com/google/devtools/build/lib/packages/semantics/BuildLanguageOptions.java @@ -722,6 +722,16 @@ public final class BuildLanguageOptions extends OptionsBase { help = "Enable experimental rule extension API and subrule APIs") public boolean experimentalRuleExtensionApi; + @Option( + name = "incompatible_enable_deprecated_label_apis", + defaultValue = "true", + documentationCategory = OptionDocumentationCategory.STARLARK_SEMANTICS, + effectTags = {OptionEffectTag.LOADING_AND_ANALYSIS}, + help = + "If enabled, certain deprecated APIs (native.repository_name, Label.workspace_name," + + " Label.relative) can be used.") + public boolean enableDeprecatedLabelApis; + /** * An interner to reduce the number of StarlarkSemantics instances. A single Blaze instance should * never accumulate a large number of these and being able to shortcut on object identity makes a @@ -829,6 +839,7 @@ public StarlarkSemantics toStarlarkSemantics() { INCOMPATIBLE_DISABLE_NON_EXECUTABLE_JAVA_BINARY, incompatibleDisableNonExecutableJavaBinary) .setBool(EXPERIMENTAL_RULE_EXTENSION_API, experimentalRuleExtensionApi) + .setBool(INCOMPATIBLE_ENABLE_DEPRECATED_LABEL_APIS, enableDeprecatedLabelApis) .build(); return INTERNER.intern(semantics); } @@ -925,6 +936,8 @@ public StarlarkSemantics toStarlarkSemantics() { public static final String INCOMPATIBLE_DISABLE_NON_EXECUTABLE_JAVA_BINARY = "-incompatible_disable_non_executable_java_binary"; public static final String EXPERIMENTAL_RULE_EXTENSION_API = "-experimental_rule_extension_api"; + public static final String INCOMPATIBLE_ENABLE_DEPRECATED_LABEL_APIS = + "+incompatible_enable_deprecated_label_apis"; // non-booleans public static final StarlarkSemantics.Key EXPERIMENTAL_BUILTINS_BZL_PATH = diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/StarlarkNativeModuleApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/StarlarkNativeModuleApi.java index a7527847f6cb82..8244b4bf063187 100644 --- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/StarlarkNativeModuleApi.java +++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/StarlarkNativeModuleApi.java @@ -18,6 +18,7 @@ import com.google.devtools.build.docgen.annot.GlobalMethods; import com.google.devtools.build.docgen.annot.GlobalMethods.Environment; import com.google.devtools.build.lib.cmdline.Label; +import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions; import javax.annotation.Nullable; import net.starlark.java.annot.Param; import net.starlark.java.annot.ParamType; @@ -226,27 +227,38 @@ NoneType exportsFiles(Sequence srcs, Object visibility, Object licenses, Star @StarlarkMethod( name = "package_name", doc = - "The name of the package being evaluated. " + "The name of the package being evaluated, without the repository name. " + "For example, in the BUILD file some/package/BUILD, its value " + "will be some/package. " + "If the BUILD file calls a function defined in a .bzl file, " - + "package_name() will match the caller BUILD file package. " - + "This function is equivalent to the deprecated variable PACKAGE_NAME.", + + "package_name() will match the caller BUILD file package.", useStarlarkThread = true) String packageName(StarlarkThread thread) throws EvalException; @StarlarkMethod( name = "repository_name", doc = - "The name of the repository the rule or build extension is called from. " - + "For example, in packages that are called into existence by the WORKSPACE stanza " - + "local_repository(name='local', path=...) it will be set to " - + "@local. In packages in the main repository, it will be set to " - + "@. This function is equivalent to the deprecated variable " - + "REPOSITORY_NAME.", + "Deprecated. Prefer to use repo_name instead, which doesn't contain the" + + " spurious leading at-sign, but behaves identically otherwise.

The canonical name" + + " of the repository containing the package currently being evaluated, with a single" + + " at-sign (@) prefixed. For example, in packages that are called into" + + " existence by the WORKSPACE stanza local_repository(name='local'," + + " path=...) it will be set to @local. In packages in the main" + + " repository, it will be set to @.", + enableOnlyWithFlag = BuildLanguageOptions.INCOMPATIBLE_ENABLE_DEPRECATED_LABEL_APIS, useStarlarkThread = true) + @Deprecated String repositoryName(StarlarkThread thread) throws EvalException; + @StarlarkMethod( + name = "repo_name", + doc = + "The canonical name of the repository containing the package currently being evaluated," + + " with no leading at-signs.", + useStarlarkThread = true) + String repoName(StarlarkThread thread) throws EvalException; + @StarlarkMethod( name = "package_relative_label", doc = diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/StarlarkRuleContextApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/StarlarkRuleContextApi.java index a715af1f3c544f..b1834dedb02ba9 100644 --- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/StarlarkRuleContextApi.java +++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/StarlarkRuleContextApi.java @@ -183,7 +183,11 @@ public interface StarlarkRuleContextApi--enable_bzlmod is on, this is the" + + " fixed string _main. Otherwise, this is the workspace name as defined" + + " in the WORKSPACE file.") String getWorkspaceName() throws EvalException; @StarlarkMethod( diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeStarlarkNativeModuleApi.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeStarlarkNativeModuleApi.java index 44d58039cc1dfb..0c415ca6e421af 100644 --- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeStarlarkNativeModuleApi.java +++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeStarlarkNativeModuleApi.java @@ -78,6 +78,11 @@ public String repositoryName(StarlarkThread thread) { return ""; } + @Override + public String repoName(StarlarkThread thread) { + return ""; + } + @Override public Label packageRelativeLabel(Object input, StarlarkThread thread) throws EvalException { return Label.parseCanonicalUnchecked("//:fake_label"); diff --git a/src/test/java/com/google/devtools/build/lib/packages/semantics/ConsistencyTest.java b/src/test/java/com/google/devtools/build/lib/packages/semantics/ConsistencyTest.java index ac6319abb9f1a4..d5b4943a3cd31b 100644 --- a/src/test/java/com/google/devtools/build/lib/packages/semantics/ConsistencyTest.java +++ b/src/test/java/com/google/devtools/build/lib/packages/semantics/ConsistencyTest.java @@ -142,6 +142,7 @@ private static BuildLanguageOptions buildRandomOptions(Random rand) throws Excep "--incompatible_disallow_empty_glob=" + rand.nextBoolean(), "--incompatible_disallow_struct_provider_syntax=" + rand.nextBoolean(), "--incompatible_do_not_split_linking_cmdline=" + rand.nextBoolean(), + "--incompatible_enable_deprecated_label_apis=" + rand.nextBoolean(), "--incompatible_java_common_parameters=" + rand.nextBoolean(), "--incompatible_merge_fixed_and_default_shell_env=" + rand.nextBoolean(), "--incompatible_new_actions_api=" + rand.nextBoolean(), @@ -193,6 +194,7 @@ private static StarlarkSemantics buildRandomSemantics(Random rand) { .setBool( BuildLanguageOptions.INCOMPATIBLE_DISALLOW_STRUCT_PROVIDER_SYNTAX, rand.nextBoolean()) .setBool(BuildLanguageOptions.INCOMPATIBLE_DO_NOT_SPLIT_LINKING_CMDLINE, rand.nextBoolean()) + .setBool(BuildLanguageOptions.INCOMPATIBLE_ENABLE_DEPRECATED_LABEL_APIS, rand.nextBoolean()) .setBool(BuildLanguageOptions.INCOMPATIBLE_JAVA_COMMON_PARAMETERS, rand.nextBoolean()) .setBool( BuildLanguageOptions.INCOMPATIBLE_MERGE_FIXED_AND_DEFAULT_SHELL_ENV, rand.nextBoolean()) diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/MockPlatformSupport.java b/src/test/java/com/google/devtools/build/lib/packages/util/MockPlatformSupport.java index 778e6458f1a436..5a3f3e239692a1 100644 --- a/src/test/java/com/google/devtools/build/lib/packages/util/MockPlatformSupport.java +++ b/src/test/java/com/google/devtools/build/lib/packages/util/MockPlatformSupport.java @@ -200,7 +200,7 @@ public static void addMockK8Platform(MockToolsConfig mockToolsConfig, Label cros "toolchain(", " name = 'toolchain_cc-compiler-k8',", " toolchain_type = '" + TestConstants.TOOLS_REPOSITORY + "//tools/cpp:toolchain_type',", - " toolchain = '" + crosstoolLabel.getLocalTargetLabel("cc-compiler-k8-compiler") + "',", + " toolchain = '" + crosstoolLabel.getSamePackageLabel("cc-compiler-k8-compiler") + "',", " target_compatible_with = [':mock_value'],", ")"); } @@ -220,7 +220,7 @@ public static void addMockPPCPlatform(MockToolsConfig mockToolsConfig, Label cro "toolchain(", " name = 'toolchain_cc-compiler-ppc',", " toolchain_type = '" + TestConstants.TOOLS_REPOSITORY + "//tools/cpp:toolchain_type',", - " toolchain = '" + crosstoolLabel.getLocalTargetLabel("cc-compiler-ppc-compiler") + "',", + " toolchain = '" + crosstoolLabel.getSamePackageLabel("cc-compiler-ppc-compiler") + "',", " target_compatible_with = [':mock_value'],", ")"); }