blob: 86d3f78ace0aff20898b7c99a7f5996921bdba94 [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 "triple_to_system",
11)
12
13DEFAULT_TOOLCHAIN_NAME_PREFIX = "toolchain_for"
14DEFAULT_STATIC_RUST_URL_TEMPLATES = ["https://static.rust-lang.org/dist/{}.tar.gz"]
15
16_build_file_for_compiler_template = """\
Brian Silvermancc09f182022-03-09 15:40:20 -080017filegroup(
18 name = "rustc",
19 srcs = ["bin/rustc{binary_ext}"],
20 visibility = ["//visibility:public"],
21)
22
23filegroup(
24 name = "rustc_lib",
25 srcs = glob(
26 [
27 "bin/*{dylib_ext}",
28 "lib/*{dylib_ext}",
29 "lib/rustlib/{target_triple}/codegen-backends/*{dylib_ext}",
30 "lib/rustlib/{target_triple}/bin/rust-lld{binary_ext}",
31 "lib/rustlib/{target_triple}/lib/*{dylib_ext}",
32 ],
33 allow_empty = True,
34 ),
35 visibility = ["//visibility:public"],
36)
37
38filegroup(
39 name = "rustdoc",
40 srcs = ["bin/rustdoc{binary_ext}"],
41 visibility = ["//visibility:public"],
42)
43"""
44
45def BUILD_for_compiler(target_triple):
Brian Silverman5f6f2762022-08-13 19:30:05 -070046 """Emits a BUILD file the compiler archive.
Brian Silvermancc09f182022-03-09 15:40:20 -080047
48 Args:
49 target_triple (str): The triple of the target platform
50
51 Returns:
52 str: The contents of a BUILD file
53 """
54 system = triple_to_system(target_triple)
55 return _build_file_for_compiler_template.format(
56 binary_ext = system_to_binary_ext(system),
57 staticlib_ext = system_to_staticlib_ext(system),
58 dylib_ext = system_to_dylib_ext(system),
59 target_triple = target_triple,
60 )
61
62_build_file_for_cargo_template = """\
Brian Silvermancc09f182022-03-09 15:40:20 -080063filegroup(
64 name = "cargo",
65 srcs = ["bin/cargo{binary_ext}"],
66 visibility = ["//visibility:public"],
67)"""
68
69def BUILD_for_cargo(target_triple):
Brian Silverman5f6f2762022-08-13 19:30:05 -070070 """Emits a BUILD file the cargo archive.
Brian Silvermancc09f182022-03-09 15:40:20 -080071
72 Args:
73 target_triple (str): The triple of the target platform
74
75 Returns:
76 str: The contents of a BUILD file
77 """
78 system = triple_to_system(target_triple)
79 return _build_file_for_cargo_template.format(
80 binary_ext = system_to_binary_ext(system),
81 )
82
83_build_file_for_rustfmt_template = """\
Brian Silvermancc09f182022-03-09 15:40:20 -080084filegroup(
85 name = "rustfmt_bin",
86 srcs = ["bin/rustfmt{binary_ext}"],
87 visibility = ["//visibility:public"],
88)
89
90sh_binary(
91 name = "rustfmt",
92 srcs = [":rustfmt_bin"],
93 visibility = ["//visibility:public"],
94)
95"""
96
97def BUILD_for_rustfmt(target_triple):
Brian Silverman5f6f2762022-08-13 19:30:05 -070098 """Emits a BUILD file the rustfmt archive.
Brian Silvermancc09f182022-03-09 15:40:20 -080099
100 Args:
101 target_triple (str): The triple of the target platform
102
103 Returns:
104 str: The contents of a BUILD file
105 """
106 system = triple_to_system(target_triple)
107 return _build_file_for_rustfmt_template.format(
108 binary_ext = system_to_binary_ext(system),
109 )
110
111_build_file_for_clippy_template = """\
Brian Silvermancc09f182022-03-09 15:40:20 -0800112filegroup(
113 name = "clippy_driver_bin",
114 srcs = ["bin/clippy-driver{binary_ext}"],
115 visibility = ["//visibility:public"],
116)
117"""
118
119def BUILD_for_clippy(target_triple):
Brian Silverman5f6f2762022-08-13 19:30:05 -0700120 """Emits a BUILD file the clippy archive.
Brian Silvermancc09f182022-03-09 15:40:20 -0800121
122 Args:
123 target_triple (str): The triple of the target platform
124
125 Returns:
126 str: The contents of a BUILD file
127 """
128 system = triple_to_system(target_triple)
129 return _build_file_for_clippy_template.format(binary_ext = system_to_binary_ext(system))
130
Brian Silverman5f6f2762022-08-13 19:30:05 -0700131_build_file_for_llvm_tools = """\
132filegroup(
133 name = "llvm_cov_bin",
134 srcs = ["lib/rustlib/{target_triple}/bin/llvm-cov{binary_ext}"],
135 visibility = ["//visibility:public"],
136)
137
138filegroup(
139 name = "llvm_profdata_bin",
140 srcs = ["lib/rustlib/{target_triple}/bin/llvm-profdata{binary_ext}"],
141 visibility = ["//visibility:public"],
142)
143"""
144
145def BUILD_for_llvm_tools(target_triple):
146 """Emits a BUILD file the llvm-tools binaries.
147
148 Args:
149 target_triple (str): The triple of the target platform
150
151 Returns:
152 str: The contents of a BUILD file
153 """
154 system = triple_to_system(target_triple)
155 return _build_file_for_llvm_tools.format(
156 binary_ext = system_to_binary_ext(system),
157 target_triple = target_triple,
158 )
159
Brian Silvermancc09f182022-03-09 15:40:20 -0800160_build_file_for_stdlib_template = """\
161load("@rules_rust//rust:toolchain.bzl", "rust_stdlib_filegroup")
162
163rust_stdlib_filegroup(
164 name = "rust_std-{target_triple}",
165 srcs = glob(
166 [
167 "lib/rustlib/{target_triple}/lib/*.rlib",
168 "lib/rustlib/{target_triple}/lib/*{dylib_ext}",
169 "lib/rustlib/{target_triple}/lib/*{staticlib_ext}",
170 "lib/rustlib/{target_triple}/lib/self-contained/**",
171 ],
172 # Some patterns (e.g. `lib/*.a`) don't match anything, see https://github.com/bazelbuild/rules_rust/pull/245
173 allow_empty = True,
174 ),
175 visibility = ["//visibility:public"],
176)
177
178# For legacy support
179alias(
180 name = "rust_lib-{target_triple}",
181 actual = "rust_std-{target_triple}",
182 visibility = ["//visibility:public"],
183)
184"""
185
186def BUILD_for_stdlib(target_triple):
Brian Silverman5f6f2762022-08-13 19:30:05 -0700187 """Emits a BUILD file the stdlib archive.
Brian Silvermancc09f182022-03-09 15:40:20 -0800188
189 Args:
190 target_triple (str): The triple of the target platform
191
192 Returns:
193 str: The contents of a BUILD file
194 """
195 system = triple_to_system(target_triple)
196 return _build_file_for_stdlib_template.format(
197 binary_ext = system_to_binary_ext(system),
198 staticlib_ext = system_to_staticlib_ext(system),
199 dylib_ext = system_to_dylib_ext(system),
200 target_triple = target_triple,
201 )
202
203_build_file_for_rust_toolchain_template = """\
Brian Silverman5f6f2762022-08-13 19:30:05 -0700204load("@rules_rust//rust:toolchain.bzl", "rust_toolchain")
205
Brian Silvermancc09f182022-03-09 15:40:20 -0800206rust_toolchain(
Brian Silverman5f6f2762022-08-13 19:30:05 -0700207 name = "{toolchain_name}",
Brian Silvermancc09f182022-03-09 15:40:20 -0800208 rust_doc = "@{workspace_name}//:rustdoc",
209 rust_std = "@{workspace_name}//:rust_std-{target_triple}",
210 rustc = "@{workspace_name}//:rustc",
211 rustfmt = {rustfmt_label},
212 cargo = "@{workspace_name}//:cargo",
213 clippy_driver = "@{workspace_name}//:clippy_driver_bin",
Brian Silverman5f6f2762022-08-13 19:30:05 -0700214 llvm_cov = {llvm_cov_label},
215 llvm_profdata = {llvm_profdata_label},
Brian Silvermancc09f182022-03-09 15:40:20 -0800216 rustc_lib = "@{workspace_name}//:rustc_lib",
217 rustc_srcs = {rustc_srcs},
Brian Silverman5f6f2762022-08-13 19:30:05 -0700218 allocator_library = {allocator_library},
Brian Silvermancc09f182022-03-09 15:40:20 -0800219 binary_ext = "{binary_ext}",
220 staticlib_ext = "{staticlib_ext}",
221 dylib_ext = "{dylib_ext}",
222 stdlib_linkflags = [{stdlib_linkflags}],
223 os = "{system}",
224 default_edition = "{default_edition}",
225 exec_triple = "{exec_triple}",
226 target_triple = "{target_triple}",
227 visibility = ["//visibility:public"],
228)
229"""
230
231def BUILD_for_rust_toolchain(
232 workspace_name,
233 name,
234 exec_triple,
235 target_triple,
236 include_rustc_srcs,
Brian Silverman5f6f2762022-08-13 19:30:05 -0700237 allocator_library,
Brian Silvermancc09f182022-03-09 15:40:20 -0800238 default_edition,
239 include_rustfmt,
Brian Silverman5f6f2762022-08-13 19:30:05 -0700240 include_llvm_tools,
Brian Silvermancc09f182022-03-09 15:40:20 -0800241 stdlib_linkflags = None):
242 """Emits a toolchain declaration to match an existing compiler and stdlib.
243
244 Args:
245 workspace_name (str): The name of the workspace that this toolchain resides in
246 name (str): The name of the toolchain declaration
247 exec_triple (str): The rust-style target that this compiler runs on
248 target_triple (str): The rust-style target triple of the tool
249 include_rustc_srcs (bool, optional): Whether to download rustc's src code. This is required in order to use rust-analyzer support. Defaults to False.
Brian Silverman5f6f2762022-08-13 19:30:05 -0700250 allocator_library (str, optional): Target that provides allocator functions when rust_library targets are embedded in a cc_binary.
Brian Silvermancc09f182022-03-09 15:40:20 -0800251 default_edition (str): Default Rust edition.
252 include_rustfmt (bool): Whether rustfmt is present in the toolchain.
Brian Silverman5f6f2762022-08-13 19:30:05 -0700253 include_llvm_tools (bool): Whether llvm-tools are present in the toolchain.
Brian Silvermancc09f182022-03-09 15:40:20 -0800254 stdlib_linkflags (list, optional): Overriden flags needed for linking to rust
255 stdlib, akin to BAZEL_LINKLIBS. Defaults to
256 None.
257
258
259 Returns:
260 str: A rendered template of a `rust_toolchain` declaration
261 """
262 system = triple_to_system(target_triple)
263 if stdlib_linkflags == None:
264 stdlib_linkflags = ", ".join(['"%s"' % x for x in system_to_stdlib_linkflags(system)])
265
266 rustc_srcs = "None"
267 if include_rustc_srcs:
268 rustc_srcs = "\"@{workspace_name}//lib/rustlib/src:rustc_srcs\"".format(workspace_name = workspace_name)
269 rustfmt_label = "None"
270 if include_rustfmt:
271 rustfmt_label = "\"@{workspace_name}//:rustfmt_bin\"".format(workspace_name = workspace_name)
Brian Silverman5f6f2762022-08-13 19:30:05 -0700272 llvm_cov_label = "None"
273 llvm_profdata_label = "None"
274 if include_llvm_tools:
275 llvm_cov_label = "\"@{workspace_name}//:llvm_cov_bin\"".format(workspace_name = workspace_name)
276 llvm_profdata_label = "\"@{workspace_name}//:llvm_profdata_bin\"".format(workspace_name = workspace_name)
277 allocator_library_label = "None"
278 if allocator_library:
279 allocator_library_label = "\"{allocator_library}\"".format(allocator_library = allocator_library)
Brian Silvermancc09f182022-03-09 15:40:20 -0800280
281 return _build_file_for_rust_toolchain_template.format(
282 toolchain_name = name,
283 workspace_name = workspace_name,
284 binary_ext = system_to_binary_ext(system),
285 staticlib_ext = system_to_staticlib_ext(system),
286 dylib_ext = system_to_dylib_ext(system),
287 rustc_srcs = rustc_srcs,
Brian Silverman5f6f2762022-08-13 19:30:05 -0700288 allocator_library = allocator_library_label,
Brian Silvermancc09f182022-03-09 15:40:20 -0800289 stdlib_linkflags = stdlib_linkflags,
290 system = system,
291 default_edition = default_edition,
292 exec_triple = exec_triple,
293 target_triple = target_triple,
294 rustfmt_label = rustfmt_label,
Brian Silverman5f6f2762022-08-13 19:30:05 -0700295 llvm_cov_label = llvm_cov_label,
296 llvm_profdata_label = llvm_profdata_label,
Brian Silvermancc09f182022-03-09 15:40:20 -0800297 )
298
299_build_file_for_toolchain_template = """\
300toolchain(
301 name = "{name}",
302 exec_compatible_with = {exec_constraint_sets_serialized},
303 target_compatible_with = {target_constraint_sets_serialized},
Brian Silverman5f6f2762022-08-13 19:30:05 -0700304 toolchain = "{toolchain}",
305 toolchain_type = "{toolchain_type}",
Brian Silvermancc09f182022-03-09 15:40:20 -0800306)
307"""
308
Brian Silverman5f6f2762022-08-13 19:30:05 -0700309def BUILD_for_toolchain(
310 name,
311 toolchain,
312 toolchain_type,
313 target_compatible_with,
314 exec_compatible_with):
Brian Silvermancc09f182022-03-09 15:40:20 -0800315 return _build_file_for_toolchain_template.format(
316 name = name,
Brian Silverman5f6f2762022-08-13 19:30:05 -0700317 exec_constraint_sets_serialized = exec_compatible_with,
318 target_constraint_sets_serialized = target_compatible_with,
319 toolchain = toolchain,
320 toolchain_type = toolchain_type,
Brian Silvermancc09f182022-03-09 15:40:20 -0800321 )
322
323def load_rustfmt(ctx):
324 """Loads a rustfmt binary and yields corresponding BUILD for it
325
326 Args:
327 ctx (repository_ctx): The repository rule's context object
328
329 Returns:
330 str: The BUILD file contents for this rustfmt binary
331 """
332 target_triple = ctx.attr.exec_triple
333
334 load_arbitrary_tool(
335 ctx,
336 iso_date = ctx.attr.iso_date,
337 target_triple = target_triple,
338 tool_name = "rustfmt",
339 tool_subdirectories = ["rustfmt-preview"],
340 version = ctx.attr.rustfmt_version,
341 )
342
343 return BUILD_for_rustfmt(target_triple)
344
345def load_rust_compiler(ctx):
346 """Loads a rust compiler and yields corresponding BUILD for it
347
348 Args:
349 ctx (repository_ctx): A repository_ctx.
350
351 Returns:
352 str: The BUILD file contents for this compiler and compiler library
353 """
354
355 target_triple = ctx.attr.exec_triple
356 load_arbitrary_tool(
357 ctx,
358 iso_date = ctx.attr.iso_date,
359 target_triple = target_triple,
Brian Silverman5f6f2762022-08-13 19:30:05 -0700360 tool_name = "rustc",
361 tool_subdirectories = ["rustc"],
Brian Silvermancc09f182022-03-09 15:40:20 -0800362 version = ctx.attr.version,
363 )
364
Brian Silverman5f6f2762022-08-13 19:30:05 -0700365 return BUILD_for_compiler(target_triple)
Brian Silvermancc09f182022-03-09 15:40:20 -0800366
Brian Silverman5f6f2762022-08-13 19:30:05 -0700367def load_clippy(ctx):
368 """Loads Clippy and yields corresponding BUILD for it
369
370 Args:
371 ctx (repository_ctx): A repository_ctx.
372
373 Returns:
374 str: The BUILD file contents for Clippy
375 """
376
377 target_triple = ctx.attr.exec_triple
378 load_arbitrary_tool(
379 ctx,
380 iso_date = ctx.attr.iso_date,
381 target_triple = target_triple,
382 tool_name = "clippy",
383 tool_subdirectories = ["clippy-preview"],
384 version = ctx.attr.version,
385 )
386
387 return BUILD_for_clippy(target_triple)
388
389def load_cargo(ctx):
390 """Loads Cargo and yields corresponding BUILD for it
391
392 Args:
393 ctx (repository_ctx): A repository_ctx.
394
395 Returns:
396 str: The BUILD file contents for Cargo
397 """
398
399 target_triple = ctx.attr.exec_triple
400 load_arbitrary_tool(
401 ctx,
402 iso_date = ctx.attr.iso_date,
403 target_triple = target_triple,
404 tool_name = "cargo",
405 tool_subdirectories = ["cargo"],
406 version = ctx.attr.version,
407 )
408
409 return BUILD_for_cargo(target_triple)
Brian Silvermancc09f182022-03-09 15:40:20 -0800410
411def should_include_rustc_srcs(repository_ctx):
412 """Determing whether or not to include rustc sources in the toolchain.
413
414 Args:
415 repository_ctx (repository_ctx): The repository rule's context object
416
417 Returns:
418 bool: Whether or not to include rustc source files in a `rustc_toolchain`
419 """
420
421 # The environment variable will always take precedence over the attribute.
422 include_rustc_srcs_env = repository_ctx.os.environ.get("RULES_RUST_TOOLCHAIN_INCLUDE_RUSTC_SRCS")
423 if include_rustc_srcs_env != None:
424 return include_rustc_srcs_env.lower() in ["true", "1"]
425
426 return getattr(repository_ctx.attr, "include_rustc_srcs", False)
427
Brian Silverman5f6f2762022-08-13 19:30:05 -0700428def load_rust_src(ctx, sha256 = ""):
Brian Silvermancc09f182022-03-09 15:40:20 -0800429 """Loads the rust source code. Used by the rust-analyzer rust-project.json generator.
430
431 Args:
432 ctx (ctx): A repository_ctx.
Brian Silverman5f6f2762022-08-13 19:30:05 -0700433 sha256 (str): The sha256 value for the `rust-src` artifact
Brian Silvermancc09f182022-03-09 15:40:20 -0800434 """
435 tool_suburl = produce_tool_suburl("rust-src", None, ctx.attr.version, ctx.attr.iso_date)
Brian Silverman5f6f2762022-08-13 19:30:05 -0700436 url = ctx.attr.urls[0].format(tool_suburl)
Brian Silvermancc09f182022-03-09 15:40:20 -0800437
438 tool_path = produce_tool_path("rust-src", None, ctx.attr.version)
Brian Silverman5f6f2762022-08-13 19:30:05 -0700439 archive_path = tool_path + _get_tool_extension(ctx)
440 sha256 = sha256 or getattr(ctx.attr, "sha256s", {}).get(archive_path) or FILE_KEY_TO_SHA.get(archive_path) or ""
441 ctx.download_and_extract(
Brian Silvermancc09f182022-03-09 15:40:20 -0800442 url,
Brian Silvermancc09f182022-03-09 15:40:20 -0800443 output = "lib/rustlib/src",
Brian Silverman5f6f2762022-08-13 19:30:05 -0700444 sha256 = sha256,
445 auth = _make_auth_dict(ctx, [url]),
Brian Silvermancc09f182022-03-09 15:40:20 -0800446 stripPrefix = "{}/rust-src/lib/rustlib/src/rust".format(tool_path),
447 )
448 ctx.file(
449 "lib/rustlib/src/BUILD.bazel",
450 """\
451filegroup(
452 name = "rustc_srcs",
453 srcs = glob(["**/*"]),
454 visibility = ["//visibility:public"],
455)""",
456 )
457
Brian Silverman5f6f2762022-08-13 19:30:05 -0700458_build_file_for_rust_analyzer_toolchain_template = """\
459load("@rules_rust//rust:toolchain.bzl", "rust_analyzer_toolchain")
460
461rust_analyzer_toolchain(
462 name = "{name}",
463 rustc_srcs = "//lib/rustlib/src:rustc_srcs",
464 visibility = ["//visibility:public"],
465)
466"""
467
468def BUILD_for_rust_analyzer_toolchain(name):
469 return _build_file_for_rust_analyzer_toolchain_template.format(
470 name = name,
471 )
472
Brian Silvermancc09f182022-03-09 15:40:20 -0800473def load_rust_stdlib(ctx, target_triple):
474 """Loads a rust standard library and yields corresponding BUILD for it
475
476 Args:
477 ctx (repository_ctx): A repository_ctx.
478 target_triple (str): The rust-style target triple of the tool
479
480 Returns:
Brian Silverman5f6f2762022-08-13 19:30:05 -0700481 str: The BUILD file contents for this stdlib
Brian Silvermancc09f182022-03-09 15:40:20 -0800482 """
483
484 load_arbitrary_tool(
485 ctx,
486 iso_date = ctx.attr.iso_date,
487 target_triple = target_triple,
488 tool_name = "rust-std",
489 tool_subdirectories = ["rust-std-{}".format(target_triple)],
490 version = ctx.attr.version,
491 )
492
Brian Silverman5f6f2762022-08-13 19:30:05 -0700493 return BUILD_for_stdlib(target_triple)
Brian Silvermancc09f182022-03-09 15:40:20 -0800494
495def load_rustc_dev_nightly(ctx, target_triple):
496 """Loads the nightly rustc dev component
497
498 Args:
499 ctx: A repository_ctx.
500 target_triple: The rust-style target triple of the tool
501 """
502
503 subdir_name = "rustc-dev"
504 if ctx.attr.iso_date < "2020-12-24":
505 subdir_name = "rustc-dev-{}".format(target_triple)
506
507 load_arbitrary_tool(
508 ctx,
509 iso_date = ctx.attr.iso_date,
510 target_triple = target_triple,
511 tool_name = "rustc-dev",
512 tool_subdirectories = [subdir_name],
513 version = ctx.attr.version,
514 )
515
516def load_llvm_tools(ctx, target_triple):
517 """Loads the llvm tools
518
519 Args:
520 ctx: A repository_ctx.
521 target_triple: The rust-style target triple of the tool
522 """
523 load_arbitrary_tool(
524 ctx,
525 iso_date = ctx.attr.iso_date,
526 target_triple = target_triple,
527 tool_name = "llvm-tools",
528 tool_subdirectories = ["llvm-tools-preview"],
529 version = ctx.attr.version,
530 )
531
Brian Silverman5f6f2762022-08-13 19:30:05 -0700532 return BUILD_for_llvm_tools(target_triple)
533
Brian Silvermancc09f182022-03-09 15:40:20 -0800534def check_version_valid(version, iso_date, param_prefix = ""):
535 """Verifies that the provided rust version and iso_date make sense.
536
537 Args:
538 version (str): The rustc version
539 iso_date (str): The rustc nightly version's iso date
540 param_prefix (str, optional): The name of the tool who's version is being checked.
541 """
542
543 if not version and iso_date:
544 fail("{param_prefix}iso_date must be paired with a {param_prefix}version".format(param_prefix = param_prefix))
545
546 if version in ("beta", "nightly") and not iso_date:
547 fail("{param_prefix}iso_date must be specified if version is 'beta' or 'nightly'".format(param_prefix = param_prefix))
548
Brian Silvermancc09f182022-03-09 15:40:20 -0800549def produce_tool_suburl(tool_name, target_triple, version, iso_date = None):
550 """Produces a fully qualified Rust tool name for URL
551
552 Args:
553 tool_name: The name of the tool per static.rust-lang.org
554 target_triple: The rust-style target triple of the tool
555 version: The version of the tool among "nightly", "beta', or an exact version.
556 iso_date: The date of the tool (or None, if the version is a specific version).
557
558 Returns:
559 str: The fully qualified url path for the specified tool.
560 """
561 path = produce_tool_path(tool_name, target_triple, version)
562 return iso_date + "/" + path if (iso_date and version in ("beta", "nightly")) else path
563
564def produce_tool_path(tool_name, target_triple, version):
565 """Produces a qualified Rust tool name
566
567 Args:
568 tool_name: The name of the tool per static.rust-lang.org
569 target_triple: The rust-style target triple of the tool
570 version: The version of the tool among "nightly", "beta', or an exact version.
571
572 Returns:
573 str: The qualified path for the specified tool.
574 """
575 if not tool_name:
576 fail("No tool name was provided")
577 if not version:
578 fail("No tool version was provided")
579 return "-".join([e for e in [tool_name, version, target_triple] if e])
580
581def load_arbitrary_tool(ctx, tool_name, tool_subdirectories, version, iso_date, target_triple, sha256 = ""):
582 """Loads a Rust tool, downloads, and extracts into the common workspace.
583
584 This function sources the tool from the Rust-lang static file server. The index is available at:
585 - https://static.rust-lang.org/dist/channel-rust-stable.toml
586 - https://static.rust-lang.org/dist/channel-rust-beta.toml
587 - https://static.rust-lang.org/dist/channel-rust-nightly.toml
588
Brian Silvermancc09f182022-03-09 15:40:20 -0800589 Args:
590 ctx (repository_ctx): A repository_ctx (no attrs required).
591 tool_name (str): The name of the given tool per the archive naming.
592 tool_subdirectories (str): The subdirectories of the tool files (at a level below the root directory of
593 the archive). The root directory of the archive is expected to match
594 $TOOL_NAME-$VERSION-$TARGET_TRIPLE.
595 Example:
596 tool_name
597 | version
598 | | target_triple
599 v v v
600 rust-1.39.0-x86_64-unknown-linux-gnu/clippy-preview
601 .../rustc
602 .../etc
603 tool_subdirectories = ["clippy-preview", "rustc"]
604 version (str): The version of the tool among "nightly", "beta', or an exact version.
605 iso_date (str): The date of the tool (ignored if the version is a specific version).
606 target_triple (str): The rust-style target triple of the tool
607 sha256 (str, optional): The expected hash of hash of the Rust tool. Defaults to "".
608 """
609 check_version_valid(version, iso_date, param_prefix = tool_name + "_")
610
611 # View the indices mentioned in the docstring to find the tool_suburl for a given
612 # tool.
613 tool_suburl = produce_tool_suburl(tool_name, target_triple, version, iso_date)
614 urls = []
615
Brian Silvermancc09f182022-03-09 15:40:20 -0800616 for url in getattr(ctx.attr, "urls", DEFAULT_STATIC_RUST_URL_TEMPLATES):
617 new_url = url.format(tool_suburl)
618 if new_url not in urls:
619 urls.append(new_url)
620
621 tool_path = produce_tool_path(tool_name, target_triple, version)
Brian Silverman5f6f2762022-08-13 19:30:05 -0700622 archive_path = tool_path + _get_tool_extension(ctx)
623 sha256 = getattr(ctx.attr, "sha256s", dict()).get(archive_path) or FILE_KEY_TO_SHA.get(archive_path) or sha256
624
Brian Silvermancc09f182022-03-09 15:40:20 -0800625 for subdirectory in tool_subdirectories:
Brian Silverman5f6f2762022-08-13 19:30:05 -0700626 # As long as the sha256 value is consistent accross calls here the
627 # cost of downloading an artifact is negated as by Bazel's caching.
628 result = ctx.download_and_extract(
629 urls,
630 sha256 = sha256,
631 auth = _make_auth_dict(ctx, urls),
Brian Silvermancc09f182022-03-09 15:40:20 -0800632 stripPrefix = "{}/{}".format(tool_path, subdirectory),
633 )
634
Brian Silverman5f6f2762022-08-13 19:30:05 -0700635 # In the event no sha256 was provided, set it to the value of the first
636 # downloaded item so subsequent downloads use a cached artifact.
637 if not sha256:
638 sha256 = result.sha256
639
Brian Silvermancc09f182022-03-09 15:40:20 -0800640def _make_auth_dict(ctx, urls):
641 auth = getattr(ctx.attr, "auth", {})
642 if not auth:
643 return {}
644 ret = {}
645 for url in urls:
646 ret[url] = auth
647 return ret
Brian Silverman5f6f2762022-08-13 19:30:05 -0700648
649def _get_tool_extension(ctx):
650 urls = getattr(ctx.attr, "urls", DEFAULT_STATIC_RUST_URL_TEMPLATES)
651 if urls[0][-7:] == ".tar.gz":
652 return ".tar.gz"
653 elif urls[0][-7:] == ".tar.xz":
654 return ".tar.xz"
655 else:
656 return ""