-
-
Notifications
You must be signed in to change notification settings - Fork 220
/
common.bzl
249 lines (210 loc) · 7.04 KB
/
common.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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# Copyright 2021 The Bazel Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
SUPPORTED_TARGETS = [
("linux", "x86_64"),
("linux", "aarch64"),
("darwin", "x86_64"),
("darwin", "aarch64"),
("none", "wasm32"),
("none", "wasm64"),
]
# Map of tool name to its symlinked name in the tools directory.
# See tool_paths in toolchain/cc_toolchain_config.bzl.
_toolchain_tools = {
name: name
for name in [
"clang-cpp",
"ld.lld",
"llvm-ar",
"llvm-dwp",
"llvm-profdata",
"llvm-cov",
"llvm-nm",
"llvm-objcopy",
"llvm-objdump",
"llvm-strip",
]
}
# Extra tools for Darwin.
_toolchain_tools_darwin = {
# rules_foreign_cc relies on the filename of the linker to set flags.
# Also see archive_flags in cc_toolchain_config.bzl.
# https://github.com/bazelbuild/rules_foreign_cc/blob/5547abc63b12c521113208eea0c5d7f66ba494d4/foreign_cc/built_tools/make_build.bzl#L71
# https://github.com/bazelbuild/rules_foreign_cc/blob/5547abc63b12c521113208eea0c5d7f66ba494d4/foreign_cc/private/cmake_script.bzl#L319
"llvm-libtool-darwin": "libtool",
}
def exec_os_key(rctx):
(os, version, arch) = os_version_arch(rctx)
if version == "":
return "%s-%s" % (os, arch)
else:
return "%s-%s-%s" % (os, version, arch)
_known_distros = [
"freebsd",
"suse",
"ubuntu",
"arch",
"manjaro",
"debian",
"fedora",
"centos",
"amzn",
"raspbian",
"pop",
"rhel",
"ol",
"almalinux",
]
def _linux_dist(rctx):
info = {}
for line in rctx.read("/etc/os-release").splitlines():
parts = line.split("=", 1)
if len(parts) == 1:
continue
info[parts[0]] = parts[1]
distname = info["ID"].strip('\"')
if distname not in _known_distros and "ID_LIKE" in info:
for distro in info["ID_LIKE"].strip('\"').split(" "):
if distro in _known_distros:
distname = distro
break
version = ""
if "VERSION_ID" in info:
version = info["VERSION_ID"].strip('"')
elif "VERSION_CODENAME" in info:
version = info["VERSION_CODENAME"].strip('"')
return distname, version
def os_version_arch(rctx):
_os = os(rctx)
_arch = arch(rctx)
if _os == "linux" and not rctx.attr.exec_os:
(distname, version) = _linux_dist(rctx)
return distname, version, _arch
return _os, "", _arch
def os(rctx):
# Less granular host OS name, e.g. linux.
name = rctx.attr.exec_os
if name:
if name in ("linux", "darwin"):
return name
else:
fail("Unsupported value for exec_os: %s" % name)
return os_from_rctx(rctx)
def os_from_rctx(rctx):
name = rctx.os.name
if name == "linux":
return "linux"
elif name == "mac os x":
return "darwin"
elif name.startswith("windows"):
return "windows"
fail("Unsupported OS: " + name)
def os_bzl(os):
# Return the OS string as used in bazel platform constraints.
return {"darwin": "osx", "linux": "linux", "none": "none"}[os]
def arch(rctx):
arch = rctx.attr.exec_arch
if arch:
if arch in ("arm64", "aarch64"):
return "aarch64"
elif arch in ("amd64", "x86_64"):
return "x86_64"
else:
fail("Unsupported value for exec_arch: %s" % arch)
return arch_from_rctx(rctx)
def arch_from_rctx(rctx):
arch = rctx.os.arch
if arch == "arm64":
return "aarch64"
if arch == "amd64":
return "x86_64"
return arch
def is_standalone_arch(os, arch):
return os == "none" and arch in ["wasm32", "wasm64"]
def os_arch_pair(os, arch):
if is_standalone_arch(os, arch):
return arch
return "{}-{}".format(os, arch)
_supported_os_arch = [os_arch_pair(os, arch) for (os, arch) in SUPPORTED_TARGETS]
def supported_os_arch_keys():
return _supported_os_arch
def check_os_arch_keys(keys):
for k in keys:
if k and k not in _supported_os_arch:
fail("Unsupported {{os}}-{{arch}} key: {key}; valid keys are: {keys}".format(
key = k,
keys = ", ".join(_supported_os_arch),
))
def exec_os_arch_dict_value(rctx, attr_name, debug = False):
# Gets a value from a dictionary keyed by host OS and arch.
# Checks for the more specific key, then the less specific,
# and finally the empty key as fallback.
# Returns a tuple of the matching key and value.
d = getattr(rctx.attr, attr_name)
key1 = exec_os_key(rctx)
if key1 in d:
return (key1, d.get(key1))
key2 = os_arch_pair(os(rctx), arch(rctx))
if debug:
print("`%s` attribute missing for key '%s' in repository '%s'; checking with key '%s'" % (attr_name, key1, rctx.name, key2)) # buildifier: disable=print
if key2 in d:
return (key2, d.get(key2))
if debug:
print("`%s` attribute missing for key '%s' in repository '%s'; checking with key ''" % (attr_name, key2, rctx.name)) # buildifier: disable=print
return ("", d.get("")) # Fallback to empty key.
def canonical_dir_path(path):
if not path.endswith("/"):
return path + "/"
return path
def is_absolute_path(val):
return val and val[0] == "/" and (len(val) == 1 or val[1] != "/")
def pkg_name_from_label(label):
if label.workspace_name:
return "@" + label.workspace_name + "//" + label.package
else:
return label.package
def pkg_path_from_label(label):
if label.workspace_root:
return label.workspace_root + "/" + label.package
else:
return label.package
def list_to_string(ls):
if ls == None:
return "None"
return "[{}]".format(", ".join(["\"{}\"".format(d) for d in ls]))
def attr_dict(attr):
# Returns a mutable dict of attr values from the struct. This is useful to
# return updated attribute values as return values of repository_rule
# implementations.
tuples = []
for key in dir(attr):
if not hasattr(attr, key):
fail("key %s not found in attributes" % key)
val = getattr(attr, key)
# Make mutable copies of frozen types.
typ = type(val)
if typ == "dict":
val = dict(val)
elif typ == "list":
val = list(val)
elif typ == "builtin_function_or_method":
# Functions can not be compared.
continue
tuples.append((key, val))
return dict(tuples)
def toolchain_tools(os):
tools = dict(_toolchain_tools)
if os == "darwin":
tools.update(_toolchain_tools_darwin)
return tools