blob: 1f5a01aa23a265d088a09d83eaa3d91c469d3038 [file] [log] [blame]
Brian Silvermancc09f182022-03-09 15:40:20 -08001"""Utility macros for use in rules_rust repository rules"""
2
3load("//rust:known_shas.bzl", "FILE_KEY_TO_SHA")
4load(
5 "//rust/platform:triple_mappings.bzl",
6 "system_to_binary_ext",
7 "system_to_dylib_ext",
8 "system_to_staticlib_ext",
9 "system_to_stdlib_linkflags",
Brian Silvermancc09f182022-03-09 15:40:20 -080010)
Adam Snaider1c095c92023-07-08 02:09:58 -040011load("//rust/private:common.bzl", "DEFAULT_NIGHTLY_ISO_DATE")
Brian Silvermancc09f182022-03-09 15:40:20 -080012
13DEFAULT_TOOLCHAIN_NAME_PREFIX = "toolchain_for"
14DEFAULT_STATIC_RUST_URL_TEMPLATES = ["https://static.rust-lang.org/dist/{}.tar.gz"]
Adam Snaider1c095c92023-07-08 02:09:58 -040015DEFAULT_NIGHTLY_VERSION = "nightly/{}".format(DEFAULT_NIGHTLY_ISO_DATE)
16DEFAULT_EXTRA_TARGET_TRIPLES = ["wasm32-unknown-unknown", "wasm32-wasi"]
17
18TINYJSON_KWARGS = dict(
19 name = "rules_rust_tinyjson",
20 sha256 = "9ab95735ea2c8fd51154d01e39cf13912a78071c2d89abc49a7ef102a7dd725a",
21 url = "https://crates.io/api/v1/crates/tinyjson/2.5.1/download",
22 strip_prefix = "tinyjson-2.5.1",
23 type = "tar.gz",
24 build_file = "@rules_rust//util/process_wrapper:BUILD.tinyjson.bazel",
25)
Brian Silvermancc09f182022-03-09 15:40:20 -080026
27_build_file_for_compiler_template = """\
Brian Silvermancc09f182022-03-09 15:40:20 -080028filegroup(
29 name = "rustc",
30 srcs = ["bin/rustc{binary_ext}"],
31 visibility = ["//visibility:public"],
32)
33
34filegroup(
35 name = "rustc_lib",
36 srcs = glob(
37 [
38 "bin/*{dylib_ext}",
39 "lib/*{dylib_ext}",
40 "lib/rustlib/{target_triple}/codegen-backends/*{dylib_ext}",
41 "lib/rustlib/{target_triple}/bin/rust-lld{binary_ext}",
42 "lib/rustlib/{target_triple}/lib/*{dylib_ext}",
43 ],
44 allow_empty = True,
45 ),
46 visibility = ["//visibility:public"],
47)
48
49filegroup(
50 name = "rustdoc",
51 srcs = ["bin/rustdoc{binary_ext}"],
52 visibility = ["//visibility:public"],
53)
54"""
55
56def BUILD_for_compiler(target_triple):
Brian Silverman5f6f2762022-08-13 19:30:05 -070057 """Emits a BUILD file the compiler archive.
Brian Silvermancc09f182022-03-09 15:40:20 -080058
59 Args:
60 target_triple (str): The triple of the target platform
61
62 Returns:
63 str: The contents of a BUILD file
64 """
Brian Silvermancc09f182022-03-09 15:40:20 -080065 return _build_file_for_compiler_template.format(
Adam Snaider1c095c92023-07-08 02:09:58 -040066 binary_ext = system_to_binary_ext(target_triple.system),
67 staticlib_ext = system_to_staticlib_ext(target_triple.system),
68 dylib_ext = system_to_dylib_ext(target_triple.system),
69 target_triple = target_triple.str,
Brian Silvermancc09f182022-03-09 15:40:20 -080070 )
71
72_build_file_for_cargo_template = """\
Brian Silvermancc09f182022-03-09 15:40:20 -080073filegroup(
74 name = "cargo",
75 srcs = ["bin/cargo{binary_ext}"],
76 visibility = ["//visibility:public"],
77)"""
78
79def BUILD_for_cargo(target_triple):
Brian Silverman5f6f2762022-08-13 19:30:05 -070080 """Emits a BUILD file the cargo archive.
Brian Silvermancc09f182022-03-09 15:40:20 -080081
82 Args:
83 target_triple (str): The triple of the target platform
84
85 Returns:
86 str: The contents of a BUILD file
87 """
Brian Silvermancc09f182022-03-09 15:40:20 -080088 return _build_file_for_cargo_template.format(
Adam Snaider1c095c92023-07-08 02:09:58 -040089 binary_ext = system_to_binary_ext(target_triple.system),
Brian Silvermancc09f182022-03-09 15:40:20 -080090 )
91
92_build_file_for_rustfmt_template = """\
Brian Silvermancc09f182022-03-09 15:40:20 -080093filegroup(
94 name = "rustfmt_bin",
95 srcs = ["bin/rustfmt{binary_ext}"],
96 visibility = ["//visibility:public"],
97)
98
99sh_binary(
100 name = "rustfmt",
101 srcs = [":rustfmt_bin"],
102 visibility = ["//visibility:public"],
103)
104"""
105
106def BUILD_for_rustfmt(target_triple):
Brian Silverman5f6f2762022-08-13 19:30:05 -0700107 """Emits a BUILD file the rustfmt archive.
Brian Silvermancc09f182022-03-09 15:40:20 -0800108
109 Args:
110 target_triple (str): The triple of the target platform
111
112 Returns:
113 str: The contents of a BUILD file
114 """
Brian Silvermancc09f182022-03-09 15:40:20 -0800115 return _build_file_for_rustfmt_template.format(
Adam Snaider1c095c92023-07-08 02:09:58 -0400116 binary_ext = system_to_binary_ext(target_triple.system),
Brian Silvermancc09f182022-03-09 15:40:20 -0800117 )
118
119_build_file_for_clippy_template = """\
Brian Silvermancc09f182022-03-09 15:40:20 -0800120filegroup(
121 name = "clippy_driver_bin",
122 srcs = ["bin/clippy-driver{binary_ext}"],
123 visibility = ["//visibility:public"],
124)
125"""
126
Adam Snaider1c095c92023-07-08 02:09:58 -0400127_build_file_for_rust_analyzer_proc_macro_srv = """\
128filegroup(
129 name = "rust_analyzer_proc_macro_srv",
130 srcs = ["libexec/rust-analyzer-proc-macro-srv{binary_ext}"],
131 visibility = ["//visibility:public"],
132)
133"""
134
135def BUILD_for_rust_analyzer_proc_macro_srv(exec_triple):
136 """Emits a BUILD file the rust_analyzer_proc_macro_srv archive.
137
138 Args:
139 exec_triple (str): The triple of the exec platform
140 Returns:
141 str: The contents of a BUILD file
142 """
143 return _build_file_for_rust_analyzer_proc_macro_srv.format(
144 binary_ext = system_to_binary_ext(exec_triple.system),
145 )
146
Brian Silvermancc09f182022-03-09 15:40:20 -0800147def BUILD_for_clippy(target_triple):
Brian Silverman5f6f2762022-08-13 19:30:05 -0700148 """Emits a BUILD file the clippy archive.
Brian Silvermancc09f182022-03-09 15:40:20 -0800149
150 Args:
151 target_triple (str): The triple of the target platform
152
153 Returns:
154 str: The contents of a BUILD file
155 """
Adam Snaider1c095c92023-07-08 02:09:58 -0400156 return _build_file_for_clippy_template.format(
157 binary_ext = system_to_binary_ext(target_triple.system),
158 )
Brian Silvermancc09f182022-03-09 15:40:20 -0800159
Brian Silverman5f6f2762022-08-13 19:30:05 -0700160_build_file_for_llvm_tools = """\
161filegroup(
162 name = "llvm_cov_bin",
163 srcs = ["lib/rustlib/{target_triple}/bin/llvm-cov{binary_ext}"],
164 visibility = ["//visibility:public"],
165)
166
167filegroup(
168 name = "llvm_profdata_bin",
169 srcs = ["lib/rustlib/{target_triple}/bin/llvm-profdata{binary_ext}"],
170 visibility = ["//visibility:public"],
171)
172"""
173
174def BUILD_for_llvm_tools(target_triple):
175 """Emits a BUILD file the llvm-tools binaries.
176
177 Args:
Adam Snaider1c095c92023-07-08 02:09:58 -0400178 target_triple (struct): The triple of the target platform
Brian Silverman5f6f2762022-08-13 19:30:05 -0700179
180 Returns:
181 str: The contents of a BUILD file
182 """
Brian Silverman5f6f2762022-08-13 19:30:05 -0700183 return _build_file_for_llvm_tools.format(
Adam Snaider1c095c92023-07-08 02:09:58 -0400184 binary_ext = system_to_binary_ext(target_triple.system),
185 target_triple = target_triple.str,
Brian Silverman5f6f2762022-08-13 19:30:05 -0700186 )
187
Brian Silvermancc09f182022-03-09 15:40:20 -0800188_build_file_for_stdlib_template = """\
189load("@rules_rust//rust:toolchain.bzl", "rust_stdlib_filegroup")
190
191rust_stdlib_filegroup(
192 name = "rust_std-{target_triple}",
193 srcs = glob(
194 [
195 "lib/rustlib/{target_triple}/lib/*.rlib",
196 "lib/rustlib/{target_triple}/lib/*{dylib_ext}",
197 "lib/rustlib/{target_triple}/lib/*{staticlib_ext}",
198 "lib/rustlib/{target_triple}/lib/self-contained/**",
199 ],
200 # Some patterns (e.g. `lib/*.a`) don't match anything, see https://github.com/bazelbuild/rules_rust/pull/245
201 allow_empty = True,
202 ),
203 visibility = ["//visibility:public"],
204)
205
206# For legacy support
207alias(
208 name = "rust_lib-{target_triple}",
209 actual = "rust_std-{target_triple}",
210 visibility = ["//visibility:public"],
211)
212"""
213
214def BUILD_for_stdlib(target_triple):
Brian Silverman5f6f2762022-08-13 19:30:05 -0700215 """Emits a BUILD file the stdlib archive.
Brian Silvermancc09f182022-03-09 15:40:20 -0800216
217 Args:
Adam Snaider1c095c92023-07-08 02:09:58 -0400218 target_triple (triple): The triple of the target platform
Brian Silvermancc09f182022-03-09 15:40:20 -0800219
220 Returns:
221 str: The contents of a BUILD file
222 """
Brian Silvermancc09f182022-03-09 15:40:20 -0800223 return _build_file_for_stdlib_template.format(
Adam Snaider1c095c92023-07-08 02:09:58 -0400224 binary_ext = system_to_binary_ext(target_triple.system),
225 staticlib_ext = system_to_staticlib_ext(target_triple.system),
226 dylib_ext = system_to_dylib_ext(target_triple.system),
227 target_triple = target_triple.str,
Brian Silvermancc09f182022-03-09 15:40:20 -0800228 )
229
230_build_file_for_rust_toolchain_template = """\
Brian Silverman5f6f2762022-08-13 19:30:05 -0700231load("@rules_rust//rust:toolchain.bzl", "rust_toolchain")
232
Brian Silvermancc09f182022-03-09 15:40:20 -0800233rust_toolchain(
Brian Silverman5f6f2762022-08-13 19:30:05 -0700234 name = "{toolchain_name}",
Adam Snaider1c095c92023-07-08 02:09:58 -0400235 rust_doc = "//:rustdoc",
236 rust_std = "//:rust_std-{target_triple}",
237 rustc = "//:rustc",
Brian Silvermancc09f182022-03-09 15:40:20 -0800238 rustfmt = {rustfmt_label},
Adam Snaider1c095c92023-07-08 02:09:58 -0400239 cargo = "//:cargo",
240 clippy_driver = "//:clippy_driver_bin",
Brian Silverman5f6f2762022-08-13 19:30:05 -0700241 llvm_cov = {llvm_cov_label},
242 llvm_profdata = {llvm_profdata_label},
Adam Snaider1c095c92023-07-08 02:09:58 -0400243 rustc_lib = "//:rustc_lib",
Brian Silverman5f6f2762022-08-13 19:30:05 -0700244 allocator_library = {allocator_library},
Adam Snaider1c095c92023-07-08 02:09:58 -0400245 global_allocator_library = {global_allocator_library},
Brian Silvermancc09f182022-03-09 15:40:20 -0800246 binary_ext = "{binary_ext}",
247 staticlib_ext = "{staticlib_ext}",
248 dylib_ext = "{dylib_ext}",
249 stdlib_linkflags = [{stdlib_linkflags}],
Brian Silvermancc09f182022-03-09 15:40:20 -0800250 default_edition = "{default_edition}",
251 exec_triple = "{exec_triple}",
252 target_triple = "{target_triple}",
253 visibility = ["//visibility:public"],
Adam Snaider1c095c92023-07-08 02:09:58 -0400254 extra_rustc_flags = {extra_rustc_flags},
255 extra_exec_rustc_flags = {extra_exec_rustc_flags},
Brian Silvermancc09f182022-03-09 15:40:20 -0800256)
257"""
258
259def BUILD_for_rust_toolchain(
Brian Silvermancc09f182022-03-09 15:40:20 -0800260 name,
261 exec_triple,
262 target_triple,
Brian Silverman5f6f2762022-08-13 19:30:05 -0700263 allocator_library,
Adam Snaider1c095c92023-07-08 02:09:58 -0400264 global_allocator_library,
Brian Silvermancc09f182022-03-09 15:40:20 -0800265 default_edition,
266 include_rustfmt,
Brian Silverman5f6f2762022-08-13 19:30:05 -0700267 include_llvm_tools,
Adam Snaider1c095c92023-07-08 02:09:58 -0400268 stdlib_linkflags = None,
269 extra_rustc_flags = None,
270 extra_exec_rustc_flags = None):
Brian Silvermancc09f182022-03-09 15:40:20 -0800271 """Emits a toolchain declaration to match an existing compiler and stdlib.
272
273 Args:
Brian Silvermancc09f182022-03-09 15:40:20 -0800274 name (str): The name of the toolchain declaration
Adam Snaider1c095c92023-07-08 02:09:58 -0400275 exec_triple (triple): The rust-style target that this compiler runs on
276 target_triple (triple): The rust-style target triple of the tool
Brian Silverman5f6f2762022-08-13 19:30:05 -0700277 allocator_library (str, optional): Target that provides allocator functions when rust_library targets are embedded in a cc_binary.
Adam Snaider1c095c92023-07-08 02:09:58 -0400278 global_allocator_library (str, optional): Target that provides allocator functions when a global allocator is used with cc_common_link.
279 This target is only used in the target configuration; exec builds still use the symbols provided
280 by the `allocator_library` target.
Brian Silvermancc09f182022-03-09 15:40:20 -0800281 default_edition (str): Default Rust edition.
282 include_rustfmt (bool): Whether rustfmt is present in the toolchain.
Brian Silverman5f6f2762022-08-13 19:30:05 -0700283 include_llvm_tools (bool): Whether llvm-tools are present in the toolchain.
Brian Silvermancc09f182022-03-09 15:40:20 -0800284 stdlib_linkflags (list, optional): Overriden flags needed for linking to rust
285 stdlib, akin to BAZEL_LINKLIBS. Defaults to
286 None.
Adam Snaider1c095c92023-07-08 02:09:58 -0400287 extra_rustc_flags (list, optional): Extra flags to pass to rustc in non-exec configuration.
288 extra_exec_rustc_flags (list, optional): Extra flags to pass to rustc in exec configuration.
Brian Silvermancc09f182022-03-09 15:40:20 -0800289
290 Returns:
291 str: A rendered template of a `rust_toolchain` declaration
292 """
Brian Silvermancc09f182022-03-09 15:40:20 -0800293 if stdlib_linkflags == None:
Adam Snaider1c095c92023-07-08 02:09:58 -0400294 stdlib_linkflags = ", ".join(['"%s"' % x for x in system_to_stdlib_linkflags(target_triple.system)])
Brian Silvermancc09f182022-03-09 15:40:20 -0800295
Brian Silvermancc09f182022-03-09 15:40:20 -0800296 rustfmt_label = "None"
297 if include_rustfmt:
Adam Snaider1c095c92023-07-08 02:09:58 -0400298 rustfmt_label = "\"//:rustfmt_bin\""
Brian Silverman5f6f2762022-08-13 19:30:05 -0700299 llvm_cov_label = "None"
300 llvm_profdata_label = "None"
301 if include_llvm_tools:
Adam Snaider1c095c92023-07-08 02:09:58 -0400302 llvm_cov_label = "\"//:llvm_cov_bin\""
303 llvm_profdata_label = "\"//:llvm_profdata_bin\""
Brian Silverman5f6f2762022-08-13 19:30:05 -0700304 allocator_library_label = "None"
305 if allocator_library:
306 allocator_library_label = "\"{allocator_library}\"".format(allocator_library = allocator_library)
Adam Snaider1c095c92023-07-08 02:09:58 -0400307 global_allocator_library_label = "None"
308 if global_allocator_library:
309 global_allocator_library_label = "\"{global_allocator_library}\"".format(global_allocator_library = global_allocator_library)
Brian Silvermancc09f182022-03-09 15:40:20 -0800310
311 return _build_file_for_rust_toolchain_template.format(
312 toolchain_name = name,
Adam Snaider1c095c92023-07-08 02:09:58 -0400313 binary_ext = system_to_binary_ext(target_triple.system),
314 staticlib_ext = system_to_staticlib_ext(target_triple.system),
315 dylib_ext = system_to_dylib_ext(target_triple.system),
Brian Silverman5f6f2762022-08-13 19:30:05 -0700316 allocator_library = allocator_library_label,
Adam Snaider1c095c92023-07-08 02:09:58 -0400317 global_allocator_library = global_allocator_library_label,
Brian Silvermancc09f182022-03-09 15:40:20 -0800318 stdlib_linkflags = stdlib_linkflags,
Brian Silvermancc09f182022-03-09 15:40:20 -0800319 default_edition = default_edition,
Adam Snaider1c095c92023-07-08 02:09:58 -0400320 exec_triple = exec_triple.str,
321 target_triple = target_triple.str,
Brian Silvermancc09f182022-03-09 15:40:20 -0800322 rustfmt_label = rustfmt_label,
Brian Silverman5f6f2762022-08-13 19:30:05 -0700323 llvm_cov_label = llvm_cov_label,
324 llvm_profdata_label = llvm_profdata_label,
Adam Snaider1c095c92023-07-08 02:09:58 -0400325 extra_rustc_flags = extra_rustc_flags,
326 extra_exec_rustc_flags = extra_exec_rustc_flags,
Brian Silvermancc09f182022-03-09 15:40:20 -0800327 )
328
329_build_file_for_toolchain_template = """\
330toolchain(
331 name = "{name}",
332 exec_compatible_with = {exec_constraint_sets_serialized},
333 target_compatible_with = {target_constraint_sets_serialized},
Brian Silverman5f6f2762022-08-13 19:30:05 -0700334 toolchain = "{toolchain}",
335 toolchain_type = "{toolchain_type}",
Adam Snaider1c095c92023-07-08 02:09:58 -0400336 {target_settings}
Brian Silvermancc09f182022-03-09 15:40:20 -0800337)
338"""
339
Brian Silverman5f6f2762022-08-13 19:30:05 -0700340def BUILD_for_toolchain(
341 name,
342 toolchain,
343 toolchain_type,
Adam Snaider1c095c92023-07-08 02:09:58 -0400344 target_settings,
Brian Silverman5f6f2762022-08-13 19:30:05 -0700345 target_compatible_with,
346 exec_compatible_with):
Adam Snaider1c095c92023-07-08 02:09:58 -0400347 target_settings_value = "target_settings = {},".format(json.encode(target_settings)) if target_settings else "# target_settings = []"
348
Brian Silvermancc09f182022-03-09 15:40:20 -0800349 return _build_file_for_toolchain_template.format(
350 name = name,
Adam Snaider1c095c92023-07-08 02:09:58 -0400351 exec_constraint_sets_serialized = json.encode(exec_compatible_with),
352 target_constraint_sets_serialized = json.encode(target_compatible_with),
Brian Silverman5f6f2762022-08-13 19:30:05 -0700353 toolchain = toolchain,
354 toolchain_type = toolchain_type,
Adam Snaider1c095c92023-07-08 02:09:58 -0400355 target_settings = target_settings_value,
Brian Silvermancc09f182022-03-09 15:40:20 -0800356 )
357
Adam Snaider1c095c92023-07-08 02:09:58 -0400358def load_rustfmt(ctx, target_triple, version, iso_date):
Brian Silvermancc09f182022-03-09 15:40:20 -0800359 """Loads a rustfmt binary and yields corresponding BUILD for it
360
361 Args:
Adam Snaider1c095c92023-07-08 02:09:58 -0400362 ctx (repository_ctx): The repository rule's context object.
363 target_triple (struct): The platform triple to download rustfmt for.
364 version (str): The version or channel of rustfmt.
365 iso_date (str): The date of the tool (or None, if the version is a specific version).
Brian Silvermancc09f182022-03-09 15:40:20 -0800366
367 Returns:
368 str: The BUILD file contents for this rustfmt binary
369 """
Brian Silvermancc09f182022-03-09 15:40:20 -0800370
371 load_arbitrary_tool(
372 ctx,
Adam Snaider1c095c92023-07-08 02:09:58 -0400373 iso_date = iso_date,
Brian Silvermancc09f182022-03-09 15:40:20 -0800374 target_triple = target_triple,
375 tool_name = "rustfmt",
376 tool_subdirectories = ["rustfmt-preview"],
Adam Snaider1c095c92023-07-08 02:09:58 -0400377 version = version,
Brian Silvermancc09f182022-03-09 15:40:20 -0800378 )
379
380 return BUILD_for_rustfmt(target_triple)
381
Adam Snaider1c095c92023-07-08 02:09:58 -0400382def load_rust_compiler(ctx, iso_date, target_triple, version):
Brian Silvermancc09f182022-03-09 15:40:20 -0800383 """Loads a rust compiler and yields corresponding BUILD for it
384
385 Args:
386 ctx (repository_ctx): A repository_ctx.
Adam Snaider1c095c92023-07-08 02:09:58 -0400387 iso_date (str): The date of the tool (or None, if the version is a specific version).
388 target_triple (struct): The Rust-style target that this compiler runs on.
389 version (str): The version of the tool among \"nightly\", \"beta\", or an exact version.
Brian Silvermancc09f182022-03-09 15:40:20 -0800390
391 Returns:
392 str: The BUILD file contents for this compiler and compiler library
393 """
394
Brian Silvermancc09f182022-03-09 15:40:20 -0800395 load_arbitrary_tool(
396 ctx,
Adam Snaider1c095c92023-07-08 02:09:58 -0400397 iso_date = iso_date,
Brian Silvermancc09f182022-03-09 15:40:20 -0800398 target_triple = target_triple,
Brian Silverman5f6f2762022-08-13 19:30:05 -0700399 tool_name = "rustc",
400 tool_subdirectories = ["rustc"],
Adam Snaider1c095c92023-07-08 02:09:58 -0400401 version = version,
Brian Silvermancc09f182022-03-09 15:40:20 -0800402 )
403
Brian Silverman5f6f2762022-08-13 19:30:05 -0700404 return BUILD_for_compiler(target_triple)
Brian Silvermancc09f182022-03-09 15:40:20 -0800405
Adam Snaider1c095c92023-07-08 02:09:58 -0400406def load_clippy(ctx, iso_date, target_triple, version):
Brian Silverman5f6f2762022-08-13 19:30:05 -0700407 """Loads Clippy and yields corresponding BUILD for it
408
409 Args:
410 ctx (repository_ctx): A repository_ctx.
Adam Snaider1c095c92023-07-08 02:09:58 -0400411 iso_date (str): The date of the tool (or None, if the version is a specific version).
412 target_triple (struct): The Rust-style target that this compiler runs on.
413 version (str): The version of the tool among \"nightly\", \"beta\", or an exact version.
Brian Silverman5f6f2762022-08-13 19:30:05 -0700414
415 Returns:
416 str: The BUILD file contents for Clippy
417 """
Brian Silverman5f6f2762022-08-13 19:30:05 -0700418 load_arbitrary_tool(
419 ctx,
Adam Snaider1c095c92023-07-08 02:09:58 -0400420 iso_date = iso_date,
Brian Silverman5f6f2762022-08-13 19:30:05 -0700421 target_triple = target_triple,
422 tool_name = "clippy",
423 tool_subdirectories = ["clippy-preview"],
Adam Snaider1c095c92023-07-08 02:09:58 -0400424 version = version,
Brian Silverman5f6f2762022-08-13 19:30:05 -0700425 )
426
427 return BUILD_for_clippy(target_triple)
428
Adam Snaider1c095c92023-07-08 02:09:58 -0400429def load_cargo(ctx, iso_date, target_triple, version):
Brian Silverman5f6f2762022-08-13 19:30:05 -0700430 """Loads Cargo and yields corresponding BUILD for it
431
432 Args:
433 ctx (repository_ctx): A repository_ctx.
Adam Snaider1c095c92023-07-08 02:09:58 -0400434 iso_date (str): The date of the tool (or None, if the version is a specific version).
435 target_triple (struct): The Rust-style target that this compiler runs on.
436 version (str): The version of the tool among \"nightly\", \"beta\", or an exact version.
Brian Silverman5f6f2762022-08-13 19:30:05 -0700437
438 Returns:
439 str: The BUILD file contents for Cargo
440 """
441
Brian Silverman5f6f2762022-08-13 19:30:05 -0700442 load_arbitrary_tool(
443 ctx,
Adam Snaider1c095c92023-07-08 02:09:58 -0400444 iso_date = iso_date,
Brian Silverman5f6f2762022-08-13 19:30:05 -0700445 target_triple = target_triple,
446 tool_name = "cargo",
447 tool_subdirectories = ["cargo"],
Adam Snaider1c095c92023-07-08 02:09:58 -0400448 version = version,
Brian Silverman5f6f2762022-08-13 19:30:05 -0700449 )
450
451 return BUILD_for_cargo(target_triple)
Brian Silvermancc09f182022-03-09 15:40:20 -0800452
Adam Snaider1c095c92023-07-08 02:09:58 -0400453def includes_rust_analyzer_proc_macro_srv(version, iso_date):
454 """Determine whether or not the rust_analyzer_proc_macro_srv binary in available in the given version of Rust.
Brian Silvermancc09f182022-03-09 15:40:20 -0800455
456 Args:
Adam Snaider1c095c92023-07-08 02:09:58 -0400457 version (str): The version of the tool among \"nightly\", \"beta\", or an exact version.
458 iso_date (str): The date of the tool (or None, if the version is a specific version).
Brian Silvermancc09f182022-03-09 15:40:20 -0800459
460 Returns:
Adam Snaider1c095c92023-07-08 02:09:58 -0400461 bool: Whether or not the binary is expected to be included
Brian Silvermancc09f182022-03-09 15:40:20 -0800462 """
463
Adam Snaider1c095c92023-07-08 02:09:58 -0400464 if version == "nightly":
465 return iso_date >= "2022-09-21"
466 elif version == "beta":
467 return False
468 elif version >= "1.64.0":
469 return True
Brian Silvermancc09f182022-03-09 15:40:20 -0800470
Adam Snaider1c095c92023-07-08 02:09:58 -0400471 return False
Brian Silvermancc09f182022-03-09 15:40:20 -0800472
Adam Snaider1c095c92023-07-08 02:09:58 -0400473def load_rust_src(ctx, iso_date, version, sha256 = ""):
Brian Silvermancc09f182022-03-09 15:40:20 -0800474 """Loads the rust source code. Used by the rust-analyzer rust-project.json generator.
475
476 Args:
477 ctx (ctx): A repository_ctx.
Adam Snaider1c095c92023-07-08 02:09:58 -0400478 version (str): The version of the tool among "nightly", "beta', or an exact version.
479 iso_date (str): The date of the tool (or None, if the version is a specific version).
Brian Silverman5f6f2762022-08-13 19:30:05 -0700480 sha256 (str): The sha256 value for the `rust-src` artifact
Brian Silvermancc09f182022-03-09 15:40:20 -0800481 """
Adam Snaider1c095c92023-07-08 02:09:58 -0400482 tool_suburl = produce_tool_suburl("rust-src", None, version, iso_date)
Brian Silverman5f6f2762022-08-13 19:30:05 -0700483 url = ctx.attr.urls[0].format(tool_suburl)
Brian Silvermancc09f182022-03-09 15:40:20 -0800484
Adam Snaider1c095c92023-07-08 02:09:58 -0400485 tool_path = produce_tool_path("rust-src", version, None)
486 archive_path = tool_path + _get_tool_extension(getattr(ctx.attr, "urls", None))
Brian Silverman5f6f2762022-08-13 19:30:05 -0700487 sha256 = sha256 or getattr(ctx.attr, "sha256s", {}).get(archive_path) or FILE_KEY_TO_SHA.get(archive_path) or ""
488 ctx.download_and_extract(
Brian Silvermancc09f182022-03-09 15:40:20 -0800489 url,
Brian Silvermancc09f182022-03-09 15:40:20 -0800490 output = "lib/rustlib/src",
Brian Silverman5f6f2762022-08-13 19:30:05 -0700491 sha256 = sha256,
492 auth = _make_auth_dict(ctx, [url]),
Brian Silvermancc09f182022-03-09 15:40:20 -0800493 stripPrefix = "{}/rust-src/lib/rustlib/src/rust".format(tool_path),
494 )
495 ctx.file(
496 "lib/rustlib/src/BUILD.bazel",
497 """\
498filegroup(
499 name = "rustc_srcs",
500 srcs = glob(["**/*"]),
501 visibility = ["//visibility:public"],
502)""",
503 )
504
Brian Silverman5f6f2762022-08-13 19:30:05 -0700505_build_file_for_rust_analyzer_toolchain_template = """\
506load("@rules_rust//rust:toolchain.bzl", "rust_analyzer_toolchain")
507
508rust_analyzer_toolchain(
509 name = "{name}",
Adam Snaider1c095c92023-07-08 02:09:58 -0400510 proc_macro_srv = {proc_macro_srv},
511 rustc = "{rustc}",
Brian Silverman5f6f2762022-08-13 19:30:05 -0700512 rustc_srcs = "//lib/rustlib/src:rustc_srcs",
513 visibility = ["//visibility:public"],
514)
515"""
516
Adam Snaider1c095c92023-07-08 02:09:58 -0400517def BUILD_for_rust_analyzer_toolchain(name, rustc, proc_macro_srv):
Brian Silverman5f6f2762022-08-13 19:30:05 -0700518 return _build_file_for_rust_analyzer_toolchain_template.format(
519 name = name,
Adam Snaider1c095c92023-07-08 02:09:58 -0400520 rustc = rustc,
521 proc_macro_srv = repr(proc_macro_srv),
522 )
523
524_build_file_for_rustfmt_toolchain_template = """\
525load("@rules_rust//rust:toolchain.bzl", "rustfmt_toolchain")
526
527rustfmt_toolchain(
528 name = "{name}",
529 rustfmt = "{rustfmt}",
530 rustc = "{rustc}",
531 rustc_lib = "{rustc_lib}",
532 visibility = ["//visibility:public"],
533)
534"""
535
536def BUILD_for_rustfmt_toolchain(name, rustfmt, rustc, rustc_lib):
537 return _build_file_for_rustfmt_toolchain_template.format(
538 name = name,
539 rustfmt = rustfmt,
540 rustc = rustc,
541 rustc_lib = rustc_lib,
Brian Silverman5f6f2762022-08-13 19:30:05 -0700542 )
543
Brian Silvermancc09f182022-03-09 15:40:20 -0800544def load_rust_stdlib(ctx, target_triple):
545 """Loads a rust standard library and yields corresponding BUILD for it
546
547 Args:
548 ctx (repository_ctx): A repository_ctx.
Adam Snaider1c095c92023-07-08 02:09:58 -0400549 target_triple (struct): The rust-style target triple of the tool
Brian Silvermancc09f182022-03-09 15:40:20 -0800550
551 Returns:
Brian Silverman5f6f2762022-08-13 19:30:05 -0700552 str: The BUILD file contents for this stdlib
Brian Silvermancc09f182022-03-09 15:40:20 -0800553 """
554
555 load_arbitrary_tool(
556 ctx,
557 iso_date = ctx.attr.iso_date,
558 target_triple = target_triple,
559 tool_name = "rust-std",
Adam Snaider1c095c92023-07-08 02:09:58 -0400560 tool_subdirectories = ["rust-std-{}".format(target_triple.str)],
Brian Silvermancc09f182022-03-09 15:40:20 -0800561 version = ctx.attr.version,
562 )
563
Brian Silverman5f6f2762022-08-13 19:30:05 -0700564 return BUILD_for_stdlib(target_triple)
Brian Silvermancc09f182022-03-09 15:40:20 -0800565
566def load_rustc_dev_nightly(ctx, target_triple):
567 """Loads the nightly rustc dev component
568
569 Args:
570 ctx: A repository_ctx.
571 target_triple: The rust-style target triple of the tool
572 """
573
574 subdir_name = "rustc-dev"
575 if ctx.attr.iso_date < "2020-12-24":
576 subdir_name = "rustc-dev-{}".format(target_triple)
577
578 load_arbitrary_tool(
579 ctx,
580 iso_date = ctx.attr.iso_date,
581 target_triple = target_triple,
582 tool_name = "rustc-dev",
583 tool_subdirectories = [subdir_name],
584 version = ctx.attr.version,
585 )
586
587def load_llvm_tools(ctx, target_triple):
588 """Loads the llvm tools
589
590 Args:
591 ctx: A repository_ctx.
592 target_triple: The rust-style target triple of the tool
593 """
594 load_arbitrary_tool(
595 ctx,
596 iso_date = ctx.attr.iso_date,
597 target_triple = target_triple,
598 tool_name = "llvm-tools",
599 tool_subdirectories = ["llvm-tools-preview"],
600 version = ctx.attr.version,
601 )
602
Brian Silverman5f6f2762022-08-13 19:30:05 -0700603 return BUILD_for_llvm_tools(target_triple)
604
Brian Silvermancc09f182022-03-09 15:40:20 -0800605def check_version_valid(version, iso_date, param_prefix = ""):
606 """Verifies that the provided rust version and iso_date make sense.
607
608 Args:
609 version (str): The rustc version
610 iso_date (str): The rustc nightly version's iso date
611 param_prefix (str, optional): The name of the tool who's version is being checked.
612 """
613
614 if not version and iso_date:
615 fail("{param_prefix}iso_date must be paired with a {param_prefix}version".format(param_prefix = param_prefix))
616
617 if version in ("beta", "nightly") and not iso_date:
618 fail("{param_prefix}iso_date must be specified if version is 'beta' or 'nightly'".format(param_prefix = param_prefix))
619
Brian Silvermancc09f182022-03-09 15:40:20 -0800620def produce_tool_suburl(tool_name, target_triple, version, iso_date = None):
621 """Produces a fully qualified Rust tool name for URL
622
623 Args:
Adam Snaider1c095c92023-07-08 02:09:58 -0400624 tool_name (str): The name of the tool per `static.rust-lang.org`.
625 target_triple (struct): The rust-style target triple of the tool.
626 version (str): The version of the tool among "nightly", "beta', or an exact version.
627 iso_date (str): The date of the tool (or None, if the version is a specific version).
Brian Silvermancc09f182022-03-09 15:40:20 -0800628
629 Returns:
630 str: The fully qualified url path for the specified tool.
631 """
Adam Snaider1c095c92023-07-08 02:09:58 -0400632 path = produce_tool_path(tool_name, version, target_triple)
Brian Silvermancc09f182022-03-09 15:40:20 -0800633 return iso_date + "/" + path if (iso_date and version in ("beta", "nightly")) else path
634
Adam Snaider1c095c92023-07-08 02:09:58 -0400635def produce_tool_path(tool_name, version, target_triple = None):
Brian Silvermancc09f182022-03-09 15:40:20 -0800636 """Produces a qualified Rust tool name
637
638 Args:
Adam Snaider1c095c92023-07-08 02:09:58 -0400639 tool_name (str): The name of the tool per static.rust-lang.org
640 version (str): The version of the tool among "nightly", "beta', or an exact version.
641 target_triple (struct, optional): The rust-style target triple of the tool
Brian Silvermancc09f182022-03-09 15:40:20 -0800642
643 Returns:
644 str: The qualified path for the specified tool.
645 """
646 if not tool_name:
647 fail("No tool name was provided")
648 if not version:
649 fail("No tool version was provided")
Adam Snaider1c095c92023-07-08 02:09:58 -0400650
651 # Not all tools require a triple. E.g. `rustc_src` (Rust source files for rust-analyzer).
652 platform_triple = None
653 if target_triple:
654 platform_triple = target_triple.str
655
656 return "-".join([e for e in [tool_name, version, platform_triple] if e])
657
658def lookup_tool_sha256(ctx, tool_name, target_triple, version, iso_date, sha256):
659 """Looks up the sha256 hash of a specific tool archive.
660
661 The lookup order is:
662
663 1. The sha256s dict in the context attributes;
664 2. The list of sha256 hashes populated in //rust:known_shas.bzl;
665 3. The sha256 argument to the function
666
667 Args:
668 ctx (repository_ctx): A repository_ctx (no attrs required).
669 tool_name (str): The name of the given tool per the archive naming.
670 target_triple (struct): The rust-style target triple of the tool.
671 version (str): The version of the tool among "nightly", "beta', or an exact version.
672 iso_date (str): The date of the tool (ignored if the version is a specific version).
673 sha256 (str): The expected hash of hash of the Rust tool.
674
675 Returns:
676 str: The sha256 of the tool archive, or an empty string if the hash could not be found.
677 """
678 tool_suburl = produce_tool_suburl(tool_name, target_triple, version, iso_date)
679 archive_path = tool_suburl + _get_tool_extension(getattr(ctx.attr, "urls", None))
680 return getattr(ctx.attr, "sha256s", dict()).get(archive_path) or FILE_KEY_TO_SHA.get(archive_path) or sha256
Brian Silvermancc09f182022-03-09 15:40:20 -0800681
682def load_arbitrary_tool(ctx, tool_name, tool_subdirectories, version, iso_date, target_triple, sha256 = ""):
683 """Loads a Rust tool, downloads, and extracts into the common workspace.
684
685 This function sources the tool from the Rust-lang static file server. The index is available at:
686 - https://static.rust-lang.org/dist/channel-rust-stable.toml
687 - https://static.rust-lang.org/dist/channel-rust-beta.toml
688 - https://static.rust-lang.org/dist/channel-rust-nightly.toml
689
Brian Silvermancc09f182022-03-09 15:40:20 -0800690 Args:
691 ctx (repository_ctx): A repository_ctx (no attrs required).
692 tool_name (str): The name of the given tool per the archive naming.
693 tool_subdirectories (str): The subdirectories of the tool files (at a level below the root directory of
694 the archive). The root directory of the archive is expected to match
695 $TOOL_NAME-$VERSION-$TARGET_TRIPLE.
696 Example:
697 tool_name
698 | version
699 | | target_triple
700 v v v
701 rust-1.39.0-x86_64-unknown-linux-gnu/clippy-preview
702 .../rustc
703 .../etc
704 tool_subdirectories = ["clippy-preview", "rustc"]
705 version (str): The version of the tool among "nightly", "beta', or an exact version.
706 iso_date (str): The date of the tool (ignored if the version is a specific version).
Adam Snaider1c095c92023-07-08 02:09:58 -0400707 target_triple (struct): The rust-style target triple of the tool.
Brian Silvermancc09f182022-03-09 15:40:20 -0800708 sha256 (str, optional): The expected hash of hash of the Rust tool. Defaults to "".
709 """
710 check_version_valid(version, iso_date, param_prefix = tool_name + "_")
711
712 # View the indices mentioned in the docstring to find the tool_suburl for a given
713 # tool.
714 tool_suburl = produce_tool_suburl(tool_name, target_triple, version, iso_date)
715 urls = []
716
Brian Silvermancc09f182022-03-09 15:40:20 -0800717 for url in getattr(ctx.attr, "urls", DEFAULT_STATIC_RUST_URL_TEMPLATES):
718 new_url = url.format(tool_suburl)
719 if new_url not in urls:
720 urls.append(new_url)
721
Adam Snaider1c095c92023-07-08 02:09:58 -0400722 tool_path = produce_tool_path(tool_name, version, target_triple)
723
724 sha256 = lookup_tool_sha256(ctx, tool_name, target_triple, version, iso_date, sha256)
Brian Silverman5f6f2762022-08-13 19:30:05 -0700725
Brian Silvermancc09f182022-03-09 15:40:20 -0800726 for subdirectory in tool_subdirectories:
Brian Silverman5f6f2762022-08-13 19:30:05 -0700727 # As long as the sha256 value is consistent accross calls here the
728 # cost of downloading an artifact is negated as by Bazel's caching.
729 result = ctx.download_and_extract(
730 urls,
731 sha256 = sha256,
732 auth = _make_auth_dict(ctx, urls),
Brian Silvermancc09f182022-03-09 15:40:20 -0800733 stripPrefix = "{}/{}".format(tool_path, subdirectory),
734 )
735
Brian Silverman5f6f2762022-08-13 19:30:05 -0700736 # In the event no sha256 was provided, set it to the value of the first
737 # downloaded item so subsequent downloads use a cached artifact.
738 if not sha256:
739 sha256 = result.sha256
740
Brian Silvermancc09f182022-03-09 15:40:20 -0800741def _make_auth_dict(ctx, urls):
742 auth = getattr(ctx.attr, "auth", {})
743 if not auth:
744 return {}
745 ret = {}
746 for url in urls:
747 ret[url] = auth
748 return ret
Brian Silverman5f6f2762022-08-13 19:30:05 -0700749
Adam Snaider1c095c92023-07-08 02:09:58 -0400750def _get_tool_extension(urls = None):
751 if urls == None:
752 urls = DEFAULT_STATIC_RUST_URL_TEMPLATES
Brian Silverman5f6f2762022-08-13 19:30:05 -0700753 if urls[0][-7:] == ".tar.gz":
754 return ".tar.gz"
755 elif urls[0][-7:] == ".tar.xz":
756 return ".tar.xz"
757 else:
758 return ""
Adam Snaider1c095c92023-07-08 02:09:58 -0400759
760def select_rust_version(versions):
761 """Select the highest priorty version for a list of Rust versions
762
763 Priority order: `stable > nightly > beta`
764
765 Note that duplicate channels are unexpected in `versions`.
766
767 Args:
768 versions (list): A list of Rust versions. E.g. [`1.66.0`, `nightly/2022-12-15`]
769
770 Returns:
771 str: The highest ranking value from `versions`
772 """
773 if not versions:
774 fail("No versions were provided")
775
776 current = versions[0]
777
778 for ver in versions:
779 if ver.startswith("beta"):
780 if current[0].isdigit() or current.startswith("nightly"):
781 continue
782 if current.startswith("beta") and ver > current:
783 current = ver
784 continue
785
786 current = ver
787 elif ver.startswith("nightly"):
788 if current[0].isdigit():
789 continue
790 if current.startswith("nightly") and ver > current:
791 current = ver
792 continue
793
794 current = ver
795
796 else:
797 current = ver
798
799 return current
800
801_build_file_for_toolchain_hub_template = """
802toolchain(
803 name = "{name}",
804 exec_compatible_with = {exec_constraint_sets_serialized},
805 target_compatible_with = {target_constraint_sets_serialized},
806 toolchain = "{toolchain}",
807 toolchain_type = "{toolchain_type}",
808 visibility = ["//visibility:public"],
809)
810"""
811
812def BUILD_for_toolchain_hub(
813 toolchain_names,
814 toolchain_labels,
815 toolchain_types,
816 target_compatible_with,
817 exec_compatible_with):
818 return "\n".join([_build_file_for_toolchain_hub_template.format(
819 name = toolchain_name,
820 exec_constraint_sets_serialized = json.encode(exec_compatible_with[toolchain_name]),
821 target_constraint_sets_serialized = json.encode(target_compatible_with[toolchain_name]),
822 toolchain = toolchain_labels[toolchain_name],
823 toolchain_type = toolchain_types[toolchain_name],
824 ) for toolchain_name in toolchain_names])
825
826def _toolchain_repository_hub_impl(repository_ctx):
827 repository_ctx.file("WORKSPACE.bazel", """workspace(name = "{}")""".format(
828 repository_ctx.name,
829 ))
830
831 repository_ctx.file("BUILD.bazel", BUILD_for_toolchain_hub(
832 toolchain_names = repository_ctx.attr.toolchain_names,
833 toolchain_labels = repository_ctx.attr.toolchain_labels,
834 toolchain_types = repository_ctx.attr.toolchain_types,
835 target_compatible_with = repository_ctx.attr.target_compatible_with,
836 exec_compatible_with = repository_ctx.attr.exec_compatible_with,
837 ))
838
839toolchain_repository_hub = repository_rule(
840 doc = (
841 "Generates a toolchain-bearing repository that declares a set of other toolchains from other " +
842 "repositories. This exists to allow registering a set of toolchains in one go with the `:all` target."
843 ),
844 attrs = {
845 "exec_compatible_with": attr.string_list_dict(
846 doc = "A list of constraints for the execution platform for this toolchain, keyed by toolchain name.",
847 mandatory = True,
848 ),
849 "target_compatible_with": attr.string_list_dict(
850 doc = "A list of constraints for the target platform for this toolchain, keyed by toolchain name.",
851 mandatory = True,
852 ),
853 "toolchain_labels": attr.string_dict(
854 doc = "The name of the toolchain implementation target, keyed by toolchain name.",
855 mandatory = True,
856 ),
857 "toolchain_names": attr.string_list(mandatory = True),
858 "toolchain_types": attr.string_dict(
859 doc = "The toolchain type of the toolchain to declare, keyed by toolchain name.",
860 mandatory = True,
861 ),
862 },
863 implementation = _toolchain_repository_hub_impl,
864)