8000 internal(pystar): Copy @bazel_tools//tools/python files to rules_python · bazel-contrib/rules_python@8c35ea7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8c35ea7

Browse files
committed
internal(pystar): Copy @bazel_tools//tools/python files to rules_python
This copies the useful pieces from @bazel_tools//tools/python into rules_python. They're copied in relatively as-is, and not yet used. These pieces are: * Bootstrap template * The py_runtime_pair rule * Autodetecting toolchain setup Work towards #1069
1 parent 4a0ba3b commit 8c35ea7

File tree

3 files changed

+822
-0
lines changed

3 files changed

+822
-0
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# Copyright 2019 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Definitions related to the Python toolchain."""
16+
17+
load(":utils.bzl", "expand_pyversion_template")
18+
19+
def define_autodetecting_toolchain(
20+
name,
21+
pywrapper_template,
22+
windows_config_setting):
23+
"""Defines the autodetecting Python toolchain.
24+
25+
This includes both strict and non-strict variants.
26+
27+
For use only by @bazel_tools//tools/python:BUILD; see the documentation
28+
comment there.
29+
30+
Args:
31+
name: The name of the toolchain to introduce. Must have value
32+
"autodetecting_toolchain". This param is present only to make the
33+
BUILD file more readable.
34+
pywrapper_template: The label of the pywrapper_template.txt file.
35+
windows_config_setting: The label of a config_setting that matches when
36+
the platform is windows, in which case the toolchain is configured
37+
in a way that triggers a workaround for #7844.
38+
"""
39+
if native.package_name() != "tools/python":
40+
8000 fail("define_autodetecting_toolchain() is private to " +
41+
"@bazel_tools//tools/python")
42+
if name != "autodetecting_toolchain":
43+
fail("Python autodetecting toolchain must be named " +
44+
"'autodetecting_toolchain'")
45+
46+
expand_pyversion_template(
47+
name = "_generate_wrappers",
48+
template = pywrapper_template,
49+
out2 = ":py2wrapper.sh",
50+
out3 = ":py3wrapper.sh",
51+
out2_nonstrict = ":py2wrapper_nonstrict.sh",
52+
out3_nonstrict = ":py3wrapper_nonstrict.sh",
53+
visibility = ["//visibility:private"],
54+
)
55+
56+
# Note that the pywrapper script is a .sh file, not a sh_binary target. If
57+
# we needed to make it a proper shell target, e.g. because it needed to
58+
# access runfiles and needed to depend on the runfiles library, then we'd
59+
# have to use a workaround to allow it to be depended on by py_runtime. See
60+
# https://github.com/bazelbuild/bazel/issues/4286#issuecomment-475661317.
61+
62+
py_runtime(
63+
name = "_autodetecting_py3_runtime",
64+
interpreter = ":py3wrapper.sh",
65+
python_version = "PY3",
66+
stub_shebang = "#!/usr/bin/env python3",
67+
visibility = ["//visibility:private"],
68+
)
69+
70+
py_runtime(
71+
name = "_autodetecting_py3_runtime_nonstrict",
72+
interpreter = ":py3wrapper_nonstrict.sh",
73+
python_version = "PY3",
74+
stub_shebang = "#!/usr/bin/env python3",
75+
visibility = ["//visibility:private"],
76+
)
77+
78+
# This is a dummy runtime whose interpreter_path triggers the native rule
79+
# logic to use the legacy behavior on Windows.
80+
# TODO(#7844): Remove this target.
81+
py_runtime(
82+
name = "_magic_sentinel_runtime",
83+
interpreter_path = "/_magic_pyruntime_sentinel_do_not_use",
84+
python_version = "PY3",
85+
visibility = ["//visibility:private"],
86+
)
87+
88+
py_runtime_pair(
89+
name = "_autodetecting_py_runtime_pair",
90+
py3_runtime = select({
91+
# If we're on windows, inject the sentinel to tell native rule logic
92+
# that we attempted to use the autodetecting toolchain and need to
93+
# switch back to legacy behavior.
94+
# TODO(#7844): Remove this hack.
95+
windows_config_setting: ":_magic_sentinel_runtime",
96+
"//conditions:default": ":_autodetecting_py3_runtime",
97+
}),
98+
visibility = ["//visibility:public"],
99+
)
100+
101+
py_runtime_pair(
102+
name = "_autodetecting_py_runtime_pair_nonstrict",
103+
py3_runtime = select({
104+
# Same hack as above.
105+
# TODO(#7844): Remove this hack.
106+
windows_config_setting: ":_magic_sentinel_runtime",
107+
"//conditions:default": ":_autodetecting_py3_runtime_nonstrict",
108+
}),
109+
visibility = ["//visibility:public"],
110+
)
111+
112+
native.toolchain(
113+
name = name,
114+
toolchain = ":_autodetecting_py_runtime_pair",
115+
toolchain_type = ":toolchain_type",
116+
visibility = ["//visibility:public"],
117+
)
118+
119+
native.toolchain(
120+
name = name + "_nonstrict",
121+
toolchain = ":_autodetecting_py_runtime_pair_nonstrict",
122+
toolchain_type = ":toolchain_type",
123+
visibility = ["//visibility:public"],
124+
)

python/private/py_runtime_pair.bzl

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# Copyright 2019 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License&q F438 uot;);
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Implementation of py_runtime_pair."""
16+
17+
# TODO: move py_runtime_pair into rules_python (and the rest of @bazel_tools//python)
18+
# py_runtime should be loaded from rules_python, but this creates a circular dep, because py_runtime_pair is imported there.
19+
py_runtime = native.py_runtime
20+
21+
def _py_runtime_pair_impl(ctx):
22+
if ctx.attr.py2_runtime != None:
23+
py2_runtime = ctx.attr.py2_runtime[PyRuntimeInfo]
24+
if py2_runtime.python_version != "PY2":
25+
fail("The Python runtime in the 'py2_runtime' attribute did not have " +
26+
"version 'PY2'")
27+
else:
28+
py2_runtime = None
29+
30+
if ctx.attr.py3_runtime != None:
31+
py3_runtime = ctx.attr.py3_runtime[PyRuntimeInfo]
32+
if py3_runtime.python_version != "PY3":
33+
fail("The Python runtime in the 'py3_runtime' attribute did not have " +
34+
"version 'PY3'")
35+
else:
36+
py3_runtime = None
37+
38+
# TODO: Uncomment this after --incompatible_python_disable_py2 defaults to true
39+
# if _is_py2_disabled(ctx) and py2_runtime != None:
40+
# fail("Using Python 2 is not supported and disabled; see " +
41+
# "https://github.com/bazelbuild/bazel/issues/15684")
42+
43+
return [platform_common.ToolchainInfo(
44+
py2_runtime = py2_runtime,
45+
py3_runtime = py3_runtime,
46+
)]
47+
48+
def _is_py2_disabled(ctx):
49+
# In Google, this file isn't bundled with Bazel, so we have to conditionally
50+
# check for this flag.
51+
# TODO: Remove this once a build with the flag is released in Google
52+
if not hasattr(ctx.fragments.py, "disable_py"):
53+
return False
54+
return ctx.fragments.py.disable_py2
55+
56+
py_runtime_pair = rule(
57+
implementation = _py_runtime_pair_impl,
58+
attrs = {
59+
# The two runtimes are used by the py_binary at runtime, and so need to
60+
# be built for the target platform.
61+
"py2_runtime": attr.label(
62+
providers = [PyRuntimeInfo],
63+
cfg = "target",
64+
doc = """\
65+
The runtime to use for Python 2 targets. Must have `python_version` set to
66+
`PY2`.
67+
""",
68+
),
69+
"py3_runtime": attr.label(
70+
providers = [PyRuntimeInfo],
71+
cfg = "target",
72+
doc = """\
73+
The runtime to use for Python 3 targets. Must have `python_version` set to
74+
`PY3`.
75+
""",
76+
),
77+
},
78+
fragments = ["py"],
79+
doc = """\
80+
A toolchain rule for Python.
81+
82+
This wraps up to two Python runtimes, one for Python 2 and one for Python 3.
83+
The rule consuming this toolchain will choose which runtime is appropriate.
84+
Either runtime may be omitted, in which case the resulting toolchain will be
85+
unusable for building Python code using that version.
86+
87+
Usually the wrapped runtimes are declared using the `py_runtime` rule, but any
88+
rule returning a `PyRuntimeInfo` provider may be used.
89+
90+
This rule returns a `platform_common.ToolchainInfo` provider with the following
91+
schema:
92+
93+
```python
94+
platform_common.ToolchainInfo(
95+
py2_runtime = <PyRuntimeInfo or None>,
96+
py3_runtime = <PyRuntimeInfo or None>,
97+
)
98+
```
99+
100+
Example usage:
101+
102+
```python
103+
# In your BUILD file...
104+
105+
load("@rules_python//python:defs.bzl", "py_runtime_pair")
106+
107+
py_runtime(
108+
name = "my_py2_runtime",
109+
interpreter_path = "/system/python2",
110+
python_version = "PY2",
111+
)
112+
113+
py_runtime(
114+
name = "my_py3_runtime",
115+
interpreter_path = "/system/python3",
116+
python_version = "PY3",
117+
)
118+
119+
py_runtime_pair(
120+
name = "my_py_runtime_pair",
121+
py2_runtime = ":my_py2_runtime",
122+
py3_runtime = ":my_py3_runtime",
123+
)
124+
125+
toolchain(
126+
name = "my_toolchain",
127+
target_compatible_with = <...>,
128+
toolchain = ":my_py_runtime_pair",
129+
toolchain_type = "@rules_python//python:toolchain_type",
130+
)
131+
```
132+
133+
```python
134+
# In your WORKSPACE...
135+
136+
register_toolchains("//my_pkg:my_toolchain")
137+
```
138+
""",
139+
)

0 commit comments

Comments
 (0)
0