Provide current_py_toolchain (#731)
This commit introduces the current_py_toolchain rule, exposing the
PYTHON2 and PYTHON3 "make" variables in bazel rules, analagous to
@bazel_tools//tools/cpp:current_cc_toolchain.
See
https://docs.bazel.build/versions/main/be/make-variables.html#custom_variables
Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com>
diff --git a/README.md b/README.md
index d880b0a..b553e09 100644
--- a/README.md
+++ b/README.md
@@ -83,6 +83,11 @@
is still used to 'bootstrap' Python targets (see https://github.com/bazelbuild/rules_python/issues/691).
You may also find some quirks while using this toolchain. Please refer to [python-build-standalone documentation's _Quirks_ section](https://python-build-standalone.readthedocs.io/en/latest/quirks.html) for details.
+### Toolchain usage in other rules
+
+Python toolchains can be utilised in other bazel rules, such as `genrule()`, by adding the `toolchains=["@rules_python//python:current_py_toolchain"]` attribute. The path to the python interpreter can be obtained by using the `$(PYTHON2)` and `$(PYTHON3)` ["Make" Variables](https://bazel.build/reference/be/make-variables). See the [`test_current_py_toolchain`](tests/load_from_macro/BUILD) target for an example.
+
+
### "Hello World"
Once you've imported the rule set into your `WORKSPACE` using any of these
diff --git a/docs/python.md b/docs/python.md
index 2b57d25..bd14b82 100755
--- a/docs/python.md
+++ b/docs/python.md
@@ -1,5 +1,28 @@
<!-- Generated with Stardoc: http://skydoc.bazel.build -->
+<a name="#current_py_toolchain"></a>
+
+## current_py_toolchain
+
+<pre>
+current_py_toolchain(<a href="#current_py_toolchain-name">name</a>)
+</pre>
+
+
+ This rule exists so that the current python toolchain can be used in the `toolchains` attribute of
+ other rules, such as genrule. It allows exposing a python toolchain after toolchain resolution has
+ happened, to a rule which expects a concrete implementation of a toolchain, rather than a
+ toolchain_type which could be resolved to that toolchain.
+
+
+**ATTRIBUTES**
+
+
+| Name | Description | Type | Mandatory | Default |
+| :-------------: | :-------------: | :-------------: | :-------------: | :-------------: |
+| name | A unique name for this target. | <a href="https://bazel.build/docs/build-ref.html#name">Name</a> | required | |
+
+
<a name="#py_import"></a>
## py_import
diff --git a/python/BUILD b/python/BUILD
index 05cc9d1..ce19653 100644
--- a/python/BUILD
+++ b/python/BUILD
@@ -24,6 +24,8 @@
that @rules_python//python is only concerned with the core rules.
"""
+load(":defs.bzl", "current_py_toolchain")
+
package(default_visibility = ["//visibility:public"])
licenses(["notice"]) # Apache 2.0
@@ -138,3 +140,7 @@
"packaging.bzl",
"pip.bzl",
])
+
+current_py_toolchain(
+ name = "current_py_toolchain",
+)
diff --git a/python/defs.bzl b/python/defs.bzl
index 39c26eb..f3a74eb 100644
--- a/python/defs.bzl
+++ b/python/defs.bzl
@@ -41,6 +41,49 @@
attrs["tags"] = [_MIGRATION_TAG]
return attrs
+def _current_py_toolchain_impl(ctx):
+ toolchain = ctx.toolchains[ctx.attr._toolchain]
+
+ direct = []
+ transitive = []
+ vars = {}
+
+ if toolchain.py3_runtime and toolchain.py3_runtime.interpreter:
+ direct.append(toolchain.py3_runtime.interpreter)
+ transitive.append(toolchain.py3_runtime.files)
+ vars["PYTHON3"] = toolchain.py3_runtime.interpreter.path
+
+ if toolchain.py2_runtime and toolchain.py2_runtime.interpreter:
+ direct.append(toolchain.py2_runtime.interpreter)
+ transitive.append(toolchain.py2_runtime.files)
+ vars["PYTHON2"] = toolchain.py2_runtime.interpreter.path
+
+ files = depset(direct, transitive = transitive)
+ return [
+ toolchain,
+ platform_common.TemplateVariableInfo(vars),
+ DefaultInfo(
+ runfiles = ctx.runfiles(transitive_files = files),
+ files = files,
+ ),
+ ]
+
+current_py_toolchain = rule(
+ doc = """
+ This rule exists so that the current python toolchain can be used in the `toolchains` attribute of
+ other rules, such as genrule. It allows exposing a python toolchain after toolchain resolution has
+ happened, to a rule which expects a concrete implementation of a toolchain, rather than a
+ toolchain_type which could be resolved to that toolchain.
+ """,
+ implementation = _current_py_toolchain_impl,
+ attrs = {
+ "_toolchain": attr.string(default = str(Label("@bazel_tools//tools/python:toolchain_type"))),
+ },
+ toolchains = [
+ str(Label("@bazel_tools//tools/python:toolchain_type")),
+ ],
+)
+
def py_library(**attrs):
"""See the Bazel core [py_library](https://docs.bazel.build/versions/master/be/python.html#py_library) documentation.
diff --git a/tests/load_from_macro/BUILD b/tests/load_from_macro/BUILD
index 8b5048a..00d7bf9 100644
--- a/tests/load_from_macro/BUILD
+++ b/tests/load_from_macro/BUILD
@@ -24,3 +24,11 @@
# Allow a test to verify an "outside package" doesn't get included
visibility = ["//examples/wheel:__pkg__"],
)
+
+genrule(
+ name = "test_current_py_toolchain",
+ srcs = [],
+ outs = ["out.txt"],
+ cmd = "$(PYTHON3) --version > $(location out.txt)",
+ toolchains = ["//python:current_py_toolchain"],
+)