diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BUILD b/src/main/java/com/google/devtools/build/lib/analysis/BUILD index e50a4f67150145..34c477e246587a 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/BUILD +++ b/src/main/java/com/google/devtools/build/lib/analysis/BUILD @@ -340,6 +340,7 @@ java_library( ":rule_configured_object_value", ":rule_definition_environment", ":run_environment_info", + ":runfiles_library_info", ":starlark/args", ":starlark/bazel_build_api_globals", ":starlark/function_transition_util", @@ -1030,6 +1031,16 @@ java_library( ], ) +java_library( + name = "runfiles_library_info", + srcs = ["RunfilesLibraryInfo.java"], + deps = [ + "//src/main/java/com/google/devtools/build/lib/concurrent", + "//src/main/java/com/google/devtools/build/lib/packages", + "//src/main/java/com/google/devtools/build/lib/starlarkbuildapi", + ], +) + java_library( name = "rule_definition_environment", srcs = ["RuleDefinitionEnvironment.java"], diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RunfilesLibraryInfo.java b/src/main/java/com/google/devtools/build/lib/analysis/RunfilesLibraryInfo.java new file mode 100644 index 00000000000000..5e3107e2ea4f7e --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/analysis/RunfilesLibraryInfo.java @@ -0,0 +1,56 @@ +// Copyright 2022 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.analysis; + +import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; +import com.google.devtools.build.lib.packages.BuiltinProvider; +import com.google.devtools.build.lib.packages.NativeInfo; +import com.google.devtools.build.lib.starlarkbuildapi.RunfilesLibraryInfoApi; + +/** + * Data-less provider that signals to direct dependents that this target is a runfiles library. + * + *

Rules that find this provider advertised by a dependency may use this as a signal to generate + * code that helps with runfiles discovery, e.g., by providing a constant containing the name of the + * repository that defines the rule. + * + *

Bazel itself uses the presence of this provider on a rule as a sign that it should include the + * repository mapping of the repository containing the rule in the repository mapping manifest of + * executable transitive dependents. + */ +@Immutable +public final class RunfilesLibraryInfo extends NativeInfo implements RunfilesLibraryInfoApi { + + public static final RunfilesLibraryInfoProvider PROVIDER = new RunfilesLibraryInfoProvider(); + + @Override + public RunfilesLibraryInfoProvider getProvider() { + return PROVIDER; + } + + /** Provider for {@link RunfilesLibraryInfo}. */ + public static class RunfilesLibraryInfoProvider extends BuiltinProvider + implements RunfilesLibraryInfoApi.RunfilesLibraryInfoApiProvider { + + private RunfilesLibraryInfoProvider() { + super("RunfilesLibraryInfo", RunfilesLibraryInfo.class); + } + + @Override + public RunfilesLibraryInfoApi constructor() { + return new RunfilesLibraryInfo(); + } + } +} diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkModules.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkModules.java index c44ae4c4a9a2bb..345a6560b2aa1d 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkModules.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkModules.java @@ -19,6 +19,7 @@ import com.google.devtools.build.lib.analysis.DefaultInfo; import com.google.devtools.build.lib.analysis.OutputGroupInfo; import com.google.devtools.build.lib.analysis.RunEnvironmentInfo; +import com.google.devtools.build.lib.analysis.RunfilesLibraryInfo; import com.google.devtools.build.lib.packages.StarlarkLibrary; import com.google.devtools.build.lib.packages.StructProvider; import net.starlark.java.eval.Starlark; @@ -46,5 +47,6 @@ public static void addPredeclared(ImmutableMap.Builder predeclar predeclared.put("Actions", ActionsProvider.INSTANCE); predeclared.put("DefaultInfo", DefaultInfo.PROVIDER); predeclared.put("RunEnvironmentInfo", RunEnvironmentInfo.PROVIDER); + predeclared.put("RunfilesLibraryInfo", RunfilesLibraryInfo.PROVIDER); } } diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/RunfilesLibraryInfoApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/RunfilesLibraryInfoApi.java new file mode 100644 index 00000000000000..191b539f57c63a --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/RunfilesLibraryInfoApi.java @@ -0,0 +1,47 @@ +// Copyright 2022 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.starlarkbuildapi; + +import com.google.devtools.build.docgen.annot.DocCategory; +import com.google.devtools.build.docgen.annot.StarlarkConstructor; +import com.google.devtools.build.lib.starlarkbuildapi.core.ProviderApi; +import com.google.devtools.build.lib.starlarkbuildapi.core.StructApi; +import net.starlark.java.annot.StarlarkBuiltin; +import net.starlark.java.annot.StarlarkMethod; + +/** Interface for runfiles library info. */ +@StarlarkBuiltin( + name = "RunfilesLibraryInfo", + category = DocCategory.PROVIDER, + doc = + "Signals to direct dependents as well as Bazel itself that this target is a runfiles" + + " library. For example, rules for compiled languages may choose to generate and" + + " compile additional code that gives access to the name of the repository defining" + + " the current target if they find this provider advertised by a direct" + + " dependency.

This provider carries no data.") +public interface RunfilesLibraryInfoApi extends StructApi { + + /** Interface for runfiles library info provider. */ + @StarlarkBuiltin(name = "Provider", category = DocCategory.PROVIDER, documented = false) + interface RunfilesLibraryInfoApiProvider extends ProviderApi { + + @StarlarkMethod( + name = "RunfilesLibraryInfo", + doc = "The RunfilesLibraryInfo constructor.", + selfCall = true) + @StarlarkConstructor + RunfilesLibraryInfoApi constructor(); + } +} diff --git a/src/test/java/com/google/devtools/build/lib/starlark/BUILD b/src/test/java/com/google/devtools/build/lib/starlark/BUILD index 0ab20ce6319a18..c0e25bae180ae3 100644 --- a/src/test/java/com/google/devtools/build/lib/starlark/BUILD +++ b/src/test/java/com/google/devtools/build/lib/starlark/BUILD @@ -46,6 +46,7 @@ java_test( "//src/main/java/com/google/devtools/build/lib/analysis:file_provider", "//src/main/java/com/google/devtools/build/lib/analysis:resolved_toolchain_context", "//src/main/java/com/google/devtools/build/lib/analysis:run_environment_info", + "//src/main/java/com/google/devtools/build/lib/analysis:runfiles_library_info", "//src/main/java/com/google/devtools/build/lib/analysis:starlark/args", "//src/main/java/com/google/devtools/build/lib/analysis:starlark/starlark_exec_group_collection", "//src/main/java/com/google/devtools/build/lib/analysis:test/analysis_test_result_info", diff --git a/src/test/java/com/google/devtools/build/lib/starlark/StarlarkIntegrationTest.java b/src/test/java/com/google/devtools/build/lib/starlark/StarlarkIntegrationTest.java index 0c12eea2af2315..a4a0e53c459bda 100644 --- a/src/test/java/com/google/devtools/build/lib/starlark/StarlarkIntegrationTest.java +++ b/src/test/java/com/google/devtools/build/lib/starlark/StarlarkIntegrationTest.java @@ -30,6 +30,7 @@ import com.google.devtools.build.lib.analysis.FilesToRunProvider; import com.google.devtools.build.lib.analysis.OutputGroupInfo; import com.google.devtools.build.lib.analysis.RunEnvironmentInfo; +import com.google.devtools.build.lib.analysis.RunfilesLibraryInfo; import com.google.devtools.build.lib.analysis.RunfilesProvider; import com.google.devtools.build.lib.analysis.config.StarlarkDefinedConfigTransition; import com.google.devtools.build.lib.analysis.configuredtargets.FileConfiguredTarget; @@ -3652,4 +3653,34 @@ public void nonExecutableStarlarkRuleReturningTestEnvironmentProducesAWarning() + " non-test target has no effect", ImmutableSet.of(EventKind.WARNING)); } + + @Test + public void runfilesLibraryInfoCanBeReturnedAndQueried() throws Exception { + scratch.file( + "examples/rules.bzl", + "def my_runfiles_library_impl(ctx):", + " return [RunfilesLibraryInfo()]", + "my_runfiles_library = rule(implementation = my_runfiles_library_impl)", + "def language_rule_impl(ctx):", + " if RunfilesLibraryInfo not in ctx.attr.dep:", + " fail('dep does not advertise RunfilesLibraryInfo')", + "language_rule = rule(", + " implementation = language_rule_impl,", + " attrs = {'dep': attr.label()},", + ")"); + scratch.file( + "examples/BUILD", + "load(':rules.bzl', 'language_rule', 'my_runfiles_library')", + "my_runfiles_library(name = 'runfiles_library')", + "language_rule(", + " name = 'target',", + " dep = ':runfiles_library',", + ")"); + + ConfiguredTarget runfilesLibrary = getConfiguredTarget("//examples:runfiles_library"); + assertThat(runfilesLibrary.get(RunfilesLibraryInfo.PROVIDER)).isNotNull(); + + // Succeeds only if targets can be queried for the presence of RunfilesLibraryInfo in Starlark. + getConfiguredTarget("//examples:target"); + } }