Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import com.google.devtools.build.lib.analysis.test.InstrumentedFilesCollector;
import com.google.devtools.build.lib.analysis.test.InstrumentedFilesInfo;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.collect.nestedset.Depset;
import com.google.devtools.build.lib.collect.nestedset.Depset.TypeException;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
Expand Down Expand Up @@ -1154,7 +1155,7 @@ public Tuple resolveCommand(
String attribute = Type.STRING.convertOptional(attributeUnchecked, "attribute");
if (expandLocations) {
command =
helper.resolveCommandAndExpandLabels(command, attribute, /*allowDataInLabel=*/ false);
helper.resolveCommandAndExpandLabels(command, attribute, /* allowDataInLabel= */ false);
}
if (!Starlark.isNullOrNone(makeVariablesUnchecked)) {
Map<String, String> makeVariables =
Expand Down Expand Up @@ -1212,6 +1213,23 @@ private void checkResolveToolsAllowed() throws EvalException {
}
}

@Override
public Label packageRelativeLabel(Object input) throws EvalException {
checkMutable("package_relative_label");
if (input instanceof Label inputLabel) {
return inputLabel;
}
try {
return Label.parseWithPackageContext(
(String) input,
Label.PackageContext.of(
ruleContext.getLabel().getPackageIdentifier(),
ruleContext.getRule().getPackageMetadata().repositoryMapping()));
} catch (LabelSyntaxException e) {
throw Starlark.errorf("invalid label in ctx.package_relative_label: %s", e.getMessage());
}
}

@Override
public StarlarkSemantics getStarlarkSemantics() {
return ruleContext.getAnalysisEnvironment().getStarlarkSemantics();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,7 @@ public Label getSamePackageLabel(String targetName) throws LabelSyntaxException
+ " containing an apparent repo name. Prefer <a"
+ " href=\"#same_package_label\"><code>Label.same_package_label()</code></a>, <a"
+ " href=\"../toplevel/native.html#package_relative_label\"><code>native.package_relative_label()</code></a>,"
+ " <a href=\"ctx.html#package_relative_label\"><code>ctx.package_relative_label()</code></a>,"
+ " or <a href=\"#Label\"><code>Label()</code></a> instead.<p>Resolves a label that"
+ " is either absolute (starts with <code>//</code>) or relative to the current"
+ " package. If this label is in a remote repository, the argument will be resolved"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,10 @@ NoneType exportsFiles(Sequence<?> srcs, Object visibility, Object licenses, Star
+ " supplied by the BUILD file to a <code>Label</code> object. (There is no way to"
+ " convert a string to a <code>Label</code> in the context of a package other than"
+ " the BUILD file or the calling .bzl file. For that reason, outer macros should"
+ " always prefer to pass Label objects to inner macros rather than label strings.)",
+ " always prefer to pass Label objects to inner macros rather than label strings.)"
+ "<a href='ctx.html#package_relative_label'><code>ctx.package_relative_label()"
+ "</code></a> provides the same functionality within a rule or aspect implementation"
+ " function.",
parameters = {
@Param(
name = "input",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,11 +330,7 @@ public interface StarlarkRuleContextApi<ConstraintValueT extends ConstraintValue
// TODO(cparsons): Look into flipping this to true.
documented = false,
parameters = {
@Param(
name = "option",
positional = true,
named = false,
doc = "The string to split."),
@Param(name = "option", positional = true, named = false, doc = "The string to split."),
})
Sequence<String> tokenize(String optionString) throws EvalException;

Expand Down Expand Up @@ -664,4 +660,32 @@ Tuple resolveCommand(
doc = "List of tools (list of targets)."),
})
Tuple resolveTools(Sequence<?> tools) throws EvalException;

@StarlarkMethod(
name = "package_relative_label",
doc =
"""
Converts the input string into a <a href='../builtins/Label.html'>Label</a> object, in \
the context of the package of the target currently being analyzed. If the input is \
already a <code>Label</code>, it is returned unchanged.<p>The result of this function is \
the same <code>Label</code> value as would be produced by passing the given string to a \
label-valued attribute of the rule and accessing the corresponding \
<a href='../builtins/Target.html#label><code>label</code></a> field.
<p><i>Usage note:</i> The difference between this function and \
<a href='../builtins/Label.html#Label'>Label()</a></code> is \
that <code>Label()</code> uses the context of the package of the <code>.bzl</code> file \
that called it, not the package of the target currently being analyzed. This function \
has the same behavior as <a href='../toplevel/native.html#package_relative_label'>
<code>native.package_relative_label()</code></a>, which cannot be used in a rule or
aspect implementation function.
""",
parameters = {
@Param(
name = "input",
allowedTypes = {@ParamType(type = String.class), @ParamType(type = Label.class)},
doc =
"The input label string or Label object. If a Label object is passed, it's"
+ " returned as is.")
})
Label packageRelativeLabel(Object input) throws EvalException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -1036,8 +1036,11 @@ StarlarkAspectApi aspect(
+ " function, <code><a"
+ " href='../toplevel/native.html#package_relative_label'>native.package_relative_label()</a></code>,"
+ " converts the input into a <code>Label</code> in the context of the package"
+ " currently being constructed. Use that function to mimic the string-to-label"
+ " conversion that is automatically done by label-valued rule attributes.",
+ " currently being constructed. For rule and aspect implementation functions, <a"
+ " href='ctx.html#package_relative_label'><code>ctx.package_relative_label()</code></a>"
+ " can be used for the same purpose. Use these functions to mimic the"
+ " string-to-label conversion that is automatically done by label-valued rule"
+ " attributes.",
parameters = {
@Param(
name = "input",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
import com.google.devtools.build.lib.analysis.util.MockRule;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.cmdline.RepositoryMapping;
import com.google.devtools.build.lib.collect.nestedset.Depset;
import com.google.devtools.build.lib.packages.Provider;
Expand Down Expand Up @@ -2792,8 +2793,7 @@ public void testNoAccessToDependencyActionsWithoutStarlarkTest() throws Exceptio

@Test
public void testAbstractActionInterface() throws Exception {
setBuildLanguageOptions(
"--incompatible_no_rule_outputs_param=false");
setBuildLanguageOptions("--incompatible_no_rule_outputs_param=false");
scratch.file(
"test/rules.bzl",
"load('//test:providers.bzl', 'AInfo')",
Expand Down Expand Up @@ -2838,8 +2838,7 @@ public void testAbstractActionInterface() throws Exception {

@Test
public void testCreatedActions() throws Exception {
setBuildLanguageOptions(
"--incompatible_no_rule_outputs_param=false");
setBuildLanguageOptions("--incompatible_no_rule_outputs_param=false");
// createRuleContext() gives us the context for a rule upon entry into its analysis function.
// But we need to inspect the result of calling created_actions() after the rule context has
// been modified by creating actions. So we'll call created_actions() from within the analysis
Expand Down Expand Up @@ -2927,8 +2926,7 @@ public void testSpawnActionInterface() throws Exception {

@Test
public void testRunShellUsesHelperScriptForLongCommand() throws Exception {
setBuildLanguageOptions(
"--incompatible_no_rule_outputs_param=false");
setBuildLanguageOptions("--incompatible_no_rule_outputs_param=false");
// createRuleContext() gives us the context for a rule upon entry into its analysis function.
// But we need to inspect the result of calling created_actions() after the rule context has
// been modified by creating actions. So we'll call created_actions() from within the analysis
Expand Down Expand Up @@ -4935,4 +4933,39 @@ def _impl(ctx):
assertThat(buildSettingProvider.getDefaultValue()).isEqualTo(ImmutableSet.copyOf(defaultValue));
assertThat(buildSettingProvider.getType()).isEqualTo(Types.STRING_SET);
}

@Test
public void testPackageRelativeLabel() throws Exception {
scratch.file("rules/BUILD");
scratch.file(
"rules/rules.bzl",
"""
MyProvider = provider()

def _impl(ctx):
return MyProvider(result = ctx.package_relative_label(":some_target"))

my_rule = rule(
implementation = _impl,
)
""");

scratch.file(
"test/BUILD",
"""
load("//rules:rules.bzl", "my_rule")

my_rule(
name = "my_target",
)
""");

ConfiguredTarget myTarget = getConfiguredTarget("//test:my_target");
Provider.Key myProviderKey =
new StarlarkProvider.Key(
keyForBuild(Label.create(PackageIdentifier.createInMainRepo("rules"), "rules.bzl")),
"MyProvider");
var result = (Label) ((StarlarkInfo) myTarget.get(myProviderKey)).getValue("result");
assertThat(result).isEqualTo(Label.parseCanonicalUnchecked("//test:some_target"));
}
}
52 changes: 52 additions & 0 deletions src/test/py/bazel/bzlmod/bazel_module_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,58 @@ def testNativePackageRelativeLabel(self):
self.assertIn('5th: @@bleb//bleb:bleb', stderr)
self.assertIn('6th: @@//bleb:bleb', stderr)

def testCtxPackageRelativeLabel(self):
self.ScratchFile(
'MODULE.bazel',
[
'module(name="foo")',
'bazel_dep(name="bar")',
'local_path_override(module_name="bar",path="bar")',
],
)
self.ScratchFile('BUILD')
self.ScratchFile(
'defs.bzl',
[
'def _my_rule_impl(ctx):',
' print("1st: " + str(ctx.package_relative_label(":bleb")))',
' print("2nd: " + str(ctx.package_relative_label('
+ '"//bleb:bleb")))',
' print("3rd: " + str(ctx.package_relative_label('
+ '"@bleb//bleb:bleb")))',
' print("4th: " + str(ctx.package_relative_label("//bleb")))',
' print("5th: " + str(ctx.package_relative_label('
+ '"@@bleb//bleb:bleb")))',
' print("6th: " + str(ctx.package_relative_label(Label('
+ '"//bleb"))))',
'my_rule = rule(_my_rule_impl)',
],
)

self.ScratchFile(
'bar/MODULE.bazel',
[
'module(name="bar")',
'bazel_dep(name="foo", repo_name="bleb")',
],
)
self.ScratchFile(
'bar/quux/BUILD',
[
'load("@bleb//:defs.bzl", "my_rule")',
'my_rule(name="book")',
],
)

_, _, stderr = self.RunBazel(['build', '@bar//quux:book'])
stderr = '\n'.join(stderr)
self.assertIn('1st: @@bar+//quux:bleb', stderr)
self.assertIn('2nd: @@bar+//bleb:bleb', stderr)
self.assertIn('3rd: @@//bleb:bleb', stderr)
self.assertIn('4th: @@bar+//bleb:bleb', stderr)
self.assertIn('5th: @@bleb//bleb:bleb', stderr)
self.assertIn('6th: @@//bleb:bleb', stderr)

def testArchiveWithArchiveType(self):
# make the archive without the .zip extension
self.main_registry.createShModule(
Expand Down
Loading