diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/BUILD b/src/main/java/com/google/devtools/build/lib/rules/python/BUILD
index 13cbe739b10f52..c211b41d9ab117 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/python/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/rules/python/BUILD
@@ -19,6 +19,8 @@ java_library(
"//src/main/java/com/google/devtools/build/lib/actions",
"//src/main/java/com/google/devtools/build/lib/actions:artifacts",
"//src/main/java/com/google/devtools/build/lib/actions:execution_requirements",
+ "//src/main/java/com/google/devtools/build/lib/analysis:actions/abstract_file_write_action",
+ "//src/main/java/com/google/devtools/build/lib/analysis:actions/deterministic_writer",
"//src/main/java/com/google/devtools/build/lib/analysis:analysis_cluster",
"//src/main/java/com/google/devtools/build/lib/analysis:config/build_configuration",
"//src/main/java/com/google/devtools/build/lib/analysis:config/build_options",
@@ -48,6 +50,7 @@ java_library(
"//src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec:serialization-constant",
"//src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp",
"//src/main/java/com/google/devtools/build/lib/starlarkbuildapi/python",
+ "//src/main/java/com/google/devtools/build/lib/util",
"//src/main/java/com/google/devtools/build/lib/util:filetype",
"//src/main/java/com/google/devtools/build/lib/util:os",
"//src/main/java/com/google/devtools/build/lib/vfs",
diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PyBuiltins.java b/src/main/java/com/google/devtools/build/lib/rules/python/PyBuiltins.java
index ca87b89ab706d1..7e7105209af7da 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/python/PyBuiltins.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/python/PyBuiltins.java
@@ -13,10 +13,44 @@
// limitations under the License.
package com.google.devtools.build.lib.rules.python;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.actions.ActionExecutionContext;
+import com.google.devtools.build.lib.actions.ActionExecutionMetadata;
+import com.google.devtools.build.lib.actions.ActionKeyContext;
+import com.google.devtools.build.lib.actions.ActionOwner;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
+import com.google.devtools.build.lib.analysis.AliasProvider;
+import com.google.devtools.build.lib.analysis.FileProvider;
+import com.google.devtools.build.lib.analysis.FilesToRunProvider;
+import com.google.devtools.build.lib.analysis.Runfiles;
+import com.google.devtools.build.lib.analysis.RunfilesSupport;
+import com.google.devtools.build.lib.analysis.SingleRunfilesSupplier;
+import com.google.devtools.build.lib.analysis.SourceManifestAction;
+import com.google.devtools.build.lib.analysis.SourceManifestAction.ManifestType;
+import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
+import com.google.devtools.build.lib.analysis.actions.AbstractFileWriteAction;
+import com.google.devtools.build.lib.analysis.actions.DeterministicWriter;
+import com.google.devtools.build.lib.analysis.starlark.StarlarkRuleContext;
+import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.Depset;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.collect.nestedset.Order;
+import com.google.devtools.build.lib.rules.cpp.CcInfo;
+import com.google.devtools.build.lib.util.Fingerprint;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
import net.starlark.java.annot.Param;
import net.starlark.java.annot.StarlarkBuiltin;
import net.starlark.java.annot.StarlarkMethod;
+import net.starlark.java.eval.Dict;
+import net.starlark.java.eval.EvalException;
+import net.starlark.java.eval.Sequence;
+import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkValue;
/** Bridge to allow builtins bzl code to call Java code. */
@@ -38,4 +72,363 @@ public abstract class PyBuiltins implements StarlarkValue {
public boolean isSingletonDepset(Depset depset) {
return depset.getSet().isSingleton();
}
+
+ @StarlarkMethod(
+ name = "regex_match",
+ doc = "Return true if subject matches pattern; pattern is implicitly anchored with ^ and $",
+ parameters = {
+ @Param(name = "subject", positional = true, named = false, defaultValue = "unbound"),
+ @Param(name = "pattern", positional = true, named = false, defaultValue = "unbound"),
+ })
+ public boolean regexMatch(String subject, String pattern) {
+ return subject.matches(pattern);
+ }
+
+ @StarlarkMethod(
+ name = "new_py_cc_link_params_provider",
+ doc = "Creates a PyCcLinkParamsProvder
.",
+ parameters = {
+ @Param(
+ name = "cc_info",
+ positional = false,
+ named = true,
+ defaultValue = "unbound",
+ doc = "The CcInfo whose linking context to propagate; other information is discarded"),
+ },
+ useStarlarkThread = false)
+ public PyCcLinkParamsProvider newPyCcLinkParamsProvider(CcInfo ccInfo) {
+ return new PyCcLinkParamsProvider(ccInfo);
+ }
+
+ // TODO(b/69113360): Remove once par-generation is moved out of the py_binary rule itself.
+ @StarlarkMethod(
+ name = "new_runfiles_supplier",
+ doc = "Create a RunfilesSupplier, which can be passed to ctx.actions.run.input_manifests.",
+ parameters = {
+ @Param(name = "ctx", positional = false, named = true, defaultValue = "unbound"),
+ @Param(name = "runfiles_dir", positional = false, named = true, defaultValue = "unbound"),
+ @Param(name = "runfiles", positional = false, named = true, defaultValue = "unbound"),
+ })
+ public Object addEnv(StarlarkRuleContext ruleContext, String runfilesStr, Runfiles runfiles)
+ throws EvalException {
+ return new SingleRunfilesSupplier(
+ PathFragment.create(runfilesStr),
+ runfiles,
+ /*manifest=*/ null,
+ /*repoMappingManifest=*/ null,
+ ruleContext.getConfiguration().buildRunfileLinks(),
+ ruleContext.getConfiguration().runfilesEnabled());
+ }
+
+ // TODO(rlevasseur): Remove once Starlark exposes this directly, see
+ // https://github.com/bazelbuild/bazel/issues/15164
+ @StarlarkMethod(
+ name = "get_action_input_manifest_mappings",
+ doc =
+ "Get the set of runfiles passed to the action. These are the runfiles from "
+ + "the `input_manifests`, `tools`, and `executable` args of ctx.actions.run."
+ + "The return value is "
+ + "dict[str runfiles_dir, dict[str runfiles_relative_path, optional File]], "
+ + "which is a dict that maps the runfile directories to a dict of the path->File "
+ + "entries within each runfiles directory. A File value will be None when the "
+ + "path came from runfiles.empty_filesnames. If the passed in action doesn't "
+ + "support fetching its runfiles mapping, None is returned.",
+ parameters = {
+ @Param(name = "action", positional = true, named = true, defaultValue = "unbound"),
+ })
+ public Object getActionRunfilesArtifacts(Object actionUnchecked) {
+ if (!(actionUnchecked instanceof ActionExecutionMetadata)) {
+ // There's many action implementations, and the Starlark caller can't check if they're
+ // passing a valid one ahead of time. So return None instead of failing and crashing.
+ return Starlark.NONE;
+ }
+ ActionExecutionMetadata action = (ActionExecutionMetadata) actionUnchecked;
+
+ Dict.Builder> inputManifest = Dict.builder();
+ for (var outerEntry : action.getRunfilesSupplier().getMappings().entrySet()) {
+ Dict.Builder runfilesMap = Dict.builder();
+ for (var innerEntry : outerEntry.getValue().entrySet()) {
+ Artifact value = innerEntry.getValue();
+ // NOTE: value may be null. This happens for Runfiles.empty_filenames entries.
+ runfilesMap.put(innerEntry.getKey().getPathString(), value == null ? Starlark.NONE : value);
+ }
+ inputManifest.put(outerEntry.getKey().getPathString(), runfilesMap.buildImmutable());
+ }
+ return inputManifest.buildImmutable();
+ }
+
+ // TODO(bazel-team): Remove this once rules are switched to using execpath semanatics for the
+ // $(location) function. See https://github.com/bazelbuild/bazel/issues/15294
+ @StarlarkMethod(
+ name = "expand_location_and_make_variables",
+ doc =
+ "Expands $(location) and makevar references. Note that $(location) performs "
+ + "rootpath (runfiles-relative) expansion, not execpath expansion.",
+ parameters = {
+ @Param(
+ name = "ctx",
+ positional = false,
+ named = true,
+ defaultValue = "unbound",
+ doc = "Rule context"),
+ @Param(
+ name = "attribute_name",
+ positional = false,
+ named = true,
+ defaultValue = "unbound",
+ doc = "Name of attribute being expanded; only used for error reporting."),
+ @Param(
+ name = "expression",
+ positional = false,
+ named = true,
+ defaultValue = "unbound",
+ doc = "The expression to expand."),
+ @Param(
+ name = "targets",
+ positional = false,
+ named = true,
+ defaultValue = "unbound",
+ doc = "List of additional targets to allow in expansions"),
+ })
+ public Object expandLocationAndMakeVariables(
+ StarlarkRuleContext ruleContext, String attributeName, String expression, Sequence> targets)
+ throws EvalException {
+ ImmutableMap.Builder