-
Notifications
You must be signed in to change notification settings - Fork 80
/
python.bzl
179 lines (165 loc) · 6.29 KB
/
python.bzl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
"""<!-- Edit the docstring in `toolchains/python/python.bzl` and run `bazel run //docs:update-README.md` to change this repository's `README.md`. -->
Rules for importing a Python toolchain from Nixpkgs.
# Rules
* [nixpkgs_python_configure](#nixpkgs_python_configure)
"""
load("@bazel_skylib//lib:versions.bzl", "versions")
load(
"@rules_nixpkgs_core//:nixpkgs.bzl",
"nixpkgs_package",
)
load(
"@rules_nixpkgs_core//:util.bzl",
"ensure_constraints",
"label_string",
)
def _nixpkgs_python_toolchain_impl(repository_ctx):
exec_constraints, target_constraints = ensure_constraints(repository_ctx)
repository_ctx.file("BUILD.bazel", executable = False, content = """
load("@bazel_tools//tools/python:toolchain.bzl", "py_runtime_pair")
py_runtime_pair(
name = "py_runtime_pair",
py2_runtime = {python2_runtime},
py3_runtime = {python3_runtime},
)
toolchain(
name = "toolchain",
toolchain = ":py_runtime_pair",
toolchain_type = "@bazel_tools//tools/python:toolchain_type",
exec_compatible_with = {exec_constraints},
target_compatible_with = {target_constraints},
)
""".format(
python2_runtime = label_string(repository_ctx.attr.python2_runtime),
python3_runtime = label_string(repository_ctx.attr.python3_runtime),
exec_constraints = exec_constraints,
target_constraints = target_constraints,
))
_nixpkgs_python_toolchain = repository_rule(
_nixpkgs_python_toolchain_impl,
attrs = {
# Using attr.string instead of attr.label, so that the repository rule
# does not explicitly depend on the nixpkgs_package instances. This is
# necessary, so that builds don't fail on platforms without nixpkgs.
"python2_runtime": attr.string(),
"python3_runtime": attr.string(),
"exec_constraints": attr.string_list(),
"target_constraints": attr.string_list(),
},
)
def _python_nix_file_content(attribute_path, bin_path, version):
add_shebang = versions.is_at_least("4.2.0", versions.get())
return """
with import <nixpkgs> {{ config = {{}}; overlays = []; }};
let
addShebang = {add_shebang};
interpreterPath = "${{{attribute_path}}}/{bin_path}";
shebangLine = interpreter: writers.makeScriptWriter {{ inherit interpreter; }} "shebang" "";
in
runCommand "bazel-nixpkgs-python-toolchain"
{{ executable = false;
# Pointless to do this on a remote machine.
preferLocalBuild = true;
allowSubstitutes = false;
}}
''
n=$out/BUILD.bazel
mkdir -p "$(dirname "$n")"
cat >>$n <<EOF
py_runtime(
name = "runtime",
interpreter_path = "${{interpreterPath}}",
python_version = "{version}",
${{lib.optionalString addShebang ''
stub_shebang = "$(cat ${{shebangLine interpreterPath}})",
''}}
visibility = ["//visibility:public"],
)
EOF
''
""".format(
add_shebang = "true" if add_shebang else "false",
attribute_path = attribute_path,
bin_path = bin_path,
version = version,
)
def nixpkgs_python_configure(
name = "nixpkgs_python_toolchain",
python2_attribute_path = None,
python2_bin_path = "bin/python",
python3_attribute_path = "python3",
python3_bin_path = "bin/python",
repository = None,
repositories = {},
nix_file_deps = None,
nixopts = [],
fail_not_supported = True,
quiet = False,
exec_constraints = None,
target_constraints = None):
"""Define and register a Python toolchain provided by nixpkgs.
Creates `nixpkgs_package`s for Python 2 or 3 `py_runtime` instances and a
corresponding `py_runtime_pair` and `toolchain`. The toolchain is
automatically registered and uses the constraint:
```
"@io_tweag_rules_nixpkgs//nixpkgs/constraints:support_nix"
```
Args:
name: The name-prefix for the created external repositories.
python2_attribute_path: The nixpkgs attribute path for python2.
python2_bin_path: The path to the interpreter within the package.
python3_attribute_path: The nixpkgs attribute path for python3.
python3_bin_path: The path to the interpreter within the package.
repository: See [`nixpkgs_package`](#nixpkgs_package-repository).
repositories: See [`nixpkgs_package`](#nixpkgs_package-repositories).
nix_file_deps: See [`nixpkgs_package`](#nixpkgs_package-nix_file_deps).
nixopts: See [`nixpkgs_package`](#nixpkgs_package-nixopts).
fail_not_supported: See [`nixpkgs_package`](#nixpkgs_package-fail_not_supported).
quiet: See [`nixpkgs_package`](#nixpkgs_package-quiet).
exec_constraints: Constraints for the execution platform.
target_constraints: Constraints for the target platform.
"""
python2_specified = python2_attribute_path and python2_bin_path
python3_specified = python3_attribute_path and python3_bin_path
if not python2_specified and not python3_specified:
fail("At least one of python2 or python3 has to be specified.")
kwargs = dict(
repository = repository,
repositories = repositories,
nix_file_deps = nix_file_deps,
nixopts = nixopts,
fail_not_supported = fail_not_supported,
quiet = quiet,
)
python2_runtime = None
if python2_attribute_path:
python2_runtime = "@%s_python2//:runtime" % name
nixpkgs_package(
name = name + "_python2",
nix_file_content = _python_nix_file_content(
attribute_path = python2_attribute_path,
bin_path = python2_bin_path,
version = "PY2",
),
**kwargs
)
python3_runtime = None
if python3_attribute_path:
python3_runtime = "@%s_python3//:runtime" % name
nixpkgs_package(
name = name + "_python3",
nix_file_content = _python_nix_file_content(
attribute_path = python3_attribute_path,
bin_path = python3_bin_path,
version = "PY3",
),
**kwargs
)
_nixpkgs_python_toolchain(
name = name,
python2_runtime = python2_runtime,
python3_runtime = python3_runtime,
exec_constraints = exec_constraints,
target_constraints = target_constraints,
)
native.register_toolchains("@%s//:toolchain" % name)