forked from protocolbuffers/protobuf
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdist.bzl
192 lines (173 loc) · 6.49 KB
/
dist.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
180
181
182
183
184
185
186
187
188
189
190
191
192
"""Rules to create python distribution files and properly name them"""
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load("@system_python//:version.bzl", "SYSTEM_PYTHON_VERSION")
def _get_suffix(limited_api, python_version, cpu):
"""Computes an ABI version tag for an extension module per PEP 3149."""
if "win32" in cpu or "win64" in cpu:
if limited_api:
return ".pyd"
if "win32" in cpu:
abi = "win32"
elif "win64" in cpu:
abi = "win_amd64"
else:
fail("Unsupported CPU: " + cpu)
return ".cp{}-{}.{}".format(python_version, abi, "pyd")
if python_version == "system":
python_version = SYSTEM_PYTHON_VERSION
if int(python_version) < 38:
python_version += "m"
abis = {
"darwin_arm64": "darwin",
"darwin_x86_64": "darwin",
"darwin": "darwin",
"osx-x86_64": "darwin",
"osx-aarch_64": "darwin",
"linux-aarch_64": "aarch64-linux-gnu",
"linux-x86_64": "x86_64-linux-gnu",
"k8": "x86_64-linux-gnu",
}
return ".cpython-{}-{}.{}".format(
python_version,
abis[cpu],
"so" if limited_api else "abi3.so",
)
elif limited_api:
return ".abi3.so"
fail("Unsupported combination of flags")
def _declare_module_file(ctx, module_name, python_version, limited_api):
"""Declares an output file for a Python module with this name, version, and limited api."""
base_filename = module_name.replace(".", "/")
suffix = _get_suffix(
python_version = python_version,
limited_api = limited_api,
cpu = ctx.var["TARGET_CPU"],
)
filename = base_filename + suffix
return ctx.actions.declare_file(filename)
# --------------------------------------------------------------------------------------------------
# py_dist_module()
#
# Creates a Python binary extension module that is ready for distribution.
#
# py_dist_module(
# name = "message_mod",
# extension = "//python:_message_binary",
# module_name = "google._upb._message",
# )
#
# In the simple case, this simply involves copying the input file to the proper filename for
# our current configuration (module_name, cpu, python_version, limited_abi).
#
# For multiarch platforms (osx-universal2), we must combine binaries for multiple architectures
# into a single output binary using the "llvm-lipo" tool. A config transition depends on multiple
# architectures to get us the input files we need.
def _py_multiarch_transition_impl(settings, attr):
if settings["//command_line_option:cpu"] == "osx-universal2":
return [{"//command_line_option:cpu": cpu} for cpu in ["osx-aarch_64", "osx-x86_64"]]
else:
return settings
_py_multiarch_transition = transition(
implementation = _py_multiarch_transition_impl,
inputs = ["//command_line_option:cpu"],
outputs = ["//command_line_option:cpu"],
)
def _py_dist_module_impl(ctx):
output_file = _declare_module_file(
ctx = ctx,
module_name = ctx.attr.module_name,
python_version = ctx.attr._python_version[BuildSettingInfo].value,
limited_api = ctx.attr._limited_api[BuildSettingInfo].value,
)
if len(ctx.attr.extension) == 1:
src = ctx.attr.extension[0][DefaultInfo].files.to_list()[0]
ctx.actions.run(
executable = "cp",
arguments = [src.path, output_file.path],
inputs = [src],
outputs = [output_file],
)
return [
DefaultInfo(files = depset([output_file])),
]
else:
srcs = [mod[DefaultInfo].files.to_list()[0] for mod in ctx.attr.extension]
ctx.actions.run(
executable = "/usr/local/bin/llvm-lipo",
arguments = ["-create", "-output", output_file.path] + [src.path for src in srcs],
inputs = srcs,
outputs = [output_file],
)
return [
DefaultInfo(files = depset([output_file])),
]
py_dist_module = rule(
implementation = _py_dist_module_impl,
attrs = {
"module_name": attr.string(mandatory = True),
"extension": attr.label(
mandatory = True,
cfg = _py_multiarch_transition,
),
"_limited_api": attr.label(default = "//python:limited_api"),
"_python_version": attr.label(default = "//python:python_version"),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
},
)
# --------------------------------------------------------------------------------------------------
# py_dist()
#
# A rule that builds a collection of binary wheels, using transitions to depend on many different
# python versions and cpus.
def _py_dist_transition_impl(settings, attr):
_ignore = (settings) # @unused
transitions = []
for cpu, version in attr.limited_api_wheels.items():
transitions.append({
"//command_line_option:cpu": cpu,
"//python:python_version": version,
"//python:limited_api": True,
})
for version in attr.full_api_versions:
for cpu in attr.full_api_cpus:
transitions.append({
"//command_line_option:cpu": cpu,
"//python:python_version": version,
"//python:limited_api": False,
})
return transitions
_py_dist_transition = transition(
implementation = _py_dist_transition_impl,
inputs = [],
outputs = [
"//command_line_option:cpu",
"//python:python_version",
"//python:limited_api",
],
)
def _py_dist_impl(ctx):
binary_files = [dep[DefaultInfo].files for dep in ctx.attr.binary_wheel]
pure_python_files = [ctx.attr.pure_python_wheel[DefaultInfo].files]
return [
DefaultInfo(files = depset(
transitive = binary_files + pure_python_files,
)),
]
py_dist = rule(
implementation = _py_dist_impl,
attrs = {
"binary_wheel": attr.label(
mandatory = True,
cfg = _py_dist_transition,
),
"pure_python_wheel": attr.label(mandatory = True),
"limited_api_wheels": attr.string_dict(),
"full_api_versions": attr.string_list(),
"full_api_cpus": attr.string_list(),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
},
)