Brian Silverman | cc09f18 | 2022-03-09 15:40:20 -0800 | [diff] [blame^] | 1 | """Utility macros for use in rules_rust repository rules""" |
| 2 | |
| 3 | load("//rust:known_shas.bzl", "FILE_KEY_TO_SHA") |
| 4 | load( |
| 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", |
| 10 | "triple_to_constraint_set", |
| 11 | "triple_to_system", |
| 12 | ) |
| 13 | |
| 14 | DEFAULT_TOOLCHAIN_NAME_PREFIX = "toolchain_for" |
| 15 | DEFAULT_STATIC_RUST_URL_TEMPLATES = ["https://static.rust-lang.org/dist/{}.tar.gz"] |
| 16 | |
| 17 | _build_file_for_compiler_template = """\ |
| 18 | load("@rules_rust//rust:toolchain.bzl", "rust_toolchain") |
| 19 | |
| 20 | filegroup( |
| 21 | name = "rustc", |
| 22 | srcs = ["bin/rustc{binary_ext}"], |
| 23 | visibility = ["//visibility:public"], |
| 24 | ) |
| 25 | |
| 26 | filegroup( |
| 27 | name = "rustc_lib", |
| 28 | srcs = glob( |
| 29 | [ |
| 30 | "bin/*{dylib_ext}", |
| 31 | "lib/*{dylib_ext}", |
| 32 | "lib/rustlib/{target_triple}/codegen-backends/*{dylib_ext}", |
| 33 | "lib/rustlib/{target_triple}/bin/rust-lld{binary_ext}", |
| 34 | "lib/rustlib/{target_triple}/lib/*{dylib_ext}", |
| 35 | ], |
| 36 | allow_empty = True, |
| 37 | ), |
| 38 | visibility = ["//visibility:public"], |
| 39 | ) |
| 40 | |
| 41 | filegroup( |
| 42 | name = "rustdoc", |
| 43 | srcs = ["bin/rustdoc{binary_ext}"], |
| 44 | visibility = ["//visibility:public"], |
| 45 | ) |
| 46 | """ |
| 47 | |
| 48 | def BUILD_for_compiler(target_triple): |
| 49 | """Emits a BUILD file the compiler `.tar.gz`. |
| 50 | |
| 51 | Args: |
| 52 | target_triple (str): The triple of the target platform |
| 53 | |
| 54 | Returns: |
| 55 | str: The contents of a BUILD file |
| 56 | """ |
| 57 | system = triple_to_system(target_triple) |
| 58 | return _build_file_for_compiler_template.format( |
| 59 | binary_ext = system_to_binary_ext(system), |
| 60 | staticlib_ext = system_to_staticlib_ext(system), |
| 61 | dylib_ext = system_to_dylib_ext(system), |
| 62 | target_triple = target_triple, |
| 63 | ) |
| 64 | |
| 65 | _build_file_for_cargo_template = """\ |
| 66 | load("@rules_rust//rust:toolchain.bzl", "rust_toolchain") |
| 67 | |
| 68 | filegroup( |
| 69 | name = "cargo", |
| 70 | srcs = ["bin/cargo{binary_ext}"], |
| 71 | visibility = ["//visibility:public"], |
| 72 | )""" |
| 73 | |
| 74 | def BUILD_for_cargo(target_triple): |
| 75 | """Emits a BUILD file the cargo `.tar.gz`. |
| 76 | |
| 77 | Args: |
| 78 | target_triple (str): The triple of the target platform |
| 79 | |
| 80 | Returns: |
| 81 | str: The contents of a BUILD file |
| 82 | """ |
| 83 | system = triple_to_system(target_triple) |
| 84 | return _build_file_for_cargo_template.format( |
| 85 | binary_ext = system_to_binary_ext(system), |
| 86 | ) |
| 87 | |
| 88 | _build_file_for_rustfmt_template = """\ |
| 89 | load("@rules_rust//rust:toolchain.bzl", "rust_toolchain") |
| 90 | |
| 91 | filegroup( |
| 92 | name = "rustfmt_bin", |
| 93 | srcs = ["bin/rustfmt{binary_ext}"], |
| 94 | visibility = ["//visibility:public"], |
| 95 | ) |
| 96 | |
| 97 | sh_binary( |
| 98 | name = "rustfmt", |
| 99 | srcs = [":rustfmt_bin"], |
| 100 | visibility = ["//visibility:public"], |
| 101 | ) |
| 102 | """ |
| 103 | |
| 104 | def BUILD_for_rustfmt(target_triple): |
| 105 | """Emits a BUILD file the rustfmt `.tar.gz`. |
| 106 | |
| 107 | Args: |
| 108 | target_triple (str): The triple of the target platform |
| 109 | |
| 110 | Returns: |
| 111 | str: The contents of a BUILD file |
| 112 | """ |
| 113 | system = triple_to_system(target_triple) |
| 114 | return _build_file_for_rustfmt_template.format( |
| 115 | binary_ext = system_to_binary_ext(system), |
| 116 | ) |
| 117 | |
| 118 | _build_file_for_clippy_template = """\ |
| 119 | load("@rules_rust//rust:toolchain.bzl", "rust_toolchain") |
| 120 | |
| 121 | filegroup( |
| 122 | name = "clippy_driver_bin", |
| 123 | srcs = ["bin/clippy-driver{binary_ext}"], |
| 124 | visibility = ["//visibility:public"], |
| 125 | ) |
| 126 | """ |
| 127 | |
| 128 | def BUILD_for_clippy(target_triple): |
| 129 | """Emits a BUILD file the clippy `.tar.gz`. |
| 130 | |
| 131 | Args: |
| 132 | target_triple (str): The triple of the target platform |
| 133 | |
| 134 | Returns: |
| 135 | str: The contents of a BUILD file |
| 136 | """ |
| 137 | system = triple_to_system(target_triple) |
| 138 | return _build_file_for_clippy_template.format(binary_ext = system_to_binary_ext(system)) |
| 139 | |
| 140 | _build_file_for_stdlib_template = """\ |
| 141 | load("@rules_rust//rust:toolchain.bzl", "rust_stdlib_filegroup") |
| 142 | |
| 143 | rust_stdlib_filegroup( |
| 144 | name = "rust_std-{target_triple}", |
| 145 | srcs = glob( |
| 146 | [ |
| 147 | "lib/rustlib/{target_triple}/lib/*.rlib", |
| 148 | "lib/rustlib/{target_triple}/lib/*{dylib_ext}", |
| 149 | "lib/rustlib/{target_triple}/lib/*{staticlib_ext}", |
| 150 | "lib/rustlib/{target_triple}/lib/self-contained/**", |
| 151 | ], |
| 152 | # Some patterns (e.g. `lib/*.a`) don't match anything, see https://github.com/bazelbuild/rules_rust/pull/245 |
| 153 | allow_empty = True, |
| 154 | ), |
| 155 | visibility = ["//visibility:public"], |
| 156 | ) |
| 157 | |
| 158 | # For legacy support |
| 159 | alias( |
| 160 | name = "rust_lib-{target_triple}", |
| 161 | actual = "rust_std-{target_triple}", |
| 162 | visibility = ["//visibility:public"], |
| 163 | ) |
| 164 | """ |
| 165 | |
| 166 | def BUILD_for_stdlib(target_triple): |
| 167 | """Emits a BUILD file the stdlib `.tar.gz`. |
| 168 | |
| 169 | Args: |
| 170 | target_triple (str): The triple of the target platform |
| 171 | |
| 172 | Returns: |
| 173 | str: The contents of a BUILD file |
| 174 | """ |
| 175 | system = triple_to_system(target_triple) |
| 176 | return _build_file_for_stdlib_template.format( |
| 177 | binary_ext = system_to_binary_ext(system), |
| 178 | staticlib_ext = system_to_staticlib_ext(system), |
| 179 | dylib_ext = system_to_dylib_ext(system), |
| 180 | target_triple = target_triple, |
| 181 | ) |
| 182 | |
| 183 | _build_file_for_rust_toolchain_template = """\ |
| 184 | rust_toolchain( |
| 185 | name = "{toolchain_name}_impl", |
| 186 | rust_doc = "@{workspace_name}//:rustdoc", |
| 187 | rust_std = "@{workspace_name}//:rust_std-{target_triple}", |
| 188 | rustc = "@{workspace_name}//:rustc", |
| 189 | rustfmt = {rustfmt_label}, |
| 190 | cargo = "@{workspace_name}//:cargo", |
| 191 | clippy_driver = "@{workspace_name}//:clippy_driver_bin", |
| 192 | rustc_lib = "@{workspace_name}//:rustc_lib", |
| 193 | rustc_srcs = {rustc_srcs}, |
| 194 | binary_ext = "{binary_ext}", |
| 195 | staticlib_ext = "{staticlib_ext}", |
| 196 | dylib_ext = "{dylib_ext}", |
| 197 | stdlib_linkflags = [{stdlib_linkflags}], |
| 198 | os = "{system}", |
| 199 | default_edition = "{default_edition}", |
| 200 | exec_triple = "{exec_triple}", |
| 201 | target_triple = "{target_triple}", |
| 202 | visibility = ["//visibility:public"], |
| 203 | ) |
| 204 | """ |
| 205 | |
| 206 | def BUILD_for_rust_toolchain( |
| 207 | workspace_name, |
| 208 | name, |
| 209 | exec_triple, |
| 210 | target_triple, |
| 211 | include_rustc_srcs, |
| 212 | default_edition, |
| 213 | include_rustfmt, |
| 214 | stdlib_linkflags = None): |
| 215 | """Emits a toolchain declaration to match an existing compiler and stdlib. |
| 216 | |
| 217 | Args: |
| 218 | workspace_name (str): The name of the workspace that this toolchain resides in |
| 219 | name (str): The name of the toolchain declaration |
| 220 | exec_triple (str): The rust-style target that this compiler runs on |
| 221 | target_triple (str): The rust-style target triple of the tool |
| 222 | 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. |
| 223 | default_edition (str): Default Rust edition. |
| 224 | include_rustfmt (bool): Whether rustfmt is present in the toolchain. |
| 225 | stdlib_linkflags (list, optional): Overriden flags needed for linking to rust |
| 226 | stdlib, akin to BAZEL_LINKLIBS. Defaults to |
| 227 | None. |
| 228 | |
| 229 | |
| 230 | Returns: |
| 231 | str: A rendered template of a `rust_toolchain` declaration |
| 232 | """ |
| 233 | system = triple_to_system(target_triple) |
| 234 | if stdlib_linkflags == None: |
| 235 | stdlib_linkflags = ", ".join(['"%s"' % x for x in system_to_stdlib_linkflags(system)]) |
| 236 | |
| 237 | rustc_srcs = "None" |
| 238 | if include_rustc_srcs: |
| 239 | rustc_srcs = "\"@{workspace_name}//lib/rustlib/src:rustc_srcs\"".format(workspace_name = workspace_name) |
| 240 | rustfmt_label = "None" |
| 241 | if include_rustfmt: |
| 242 | rustfmt_label = "\"@{workspace_name}//:rustfmt_bin\"".format(workspace_name = workspace_name) |
| 243 | |
| 244 | return _build_file_for_rust_toolchain_template.format( |
| 245 | toolchain_name = name, |
| 246 | workspace_name = workspace_name, |
| 247 | binary_ext = system_to_binary_ext(system), |
| 248 | staticlib_ext = system_to_staticlib_ext(system), |
| 249 | dylib_ext = system_to_dylib_ext(system), |
| 250 | rustc_srcs = rustc_srcs, |
| 251 | stdlib_linkflags = stdlib_linkflags, |
| 252 | system = system, |
| 253 | default_edition = default_edition, |
| 254 | exec_triple = exec_triple, |
| 255 | target_triple = target_triple, |
| 256 | rustfmt_label = rustfmt_label, |
| 257 | ) |
| 258 | |
| 259 | _build_file_for_toolchain_template = """\ |
| 260 | toolchain( |
| 261 | name = "{name}", |
| 262 | exec_compatible_with = {exec_constraint_sets_serialized}, |
| 263 | target_compatible_with = {target_constraint_sets_serialized}, |
| 264 | toolchain = "@{parent_workspace_name}//:{name}_impl", |
| 265 | toolchain_type = "@rules_rust//rust:toolchain", |
| 266 | ) |
| 267 | """ |
| 268 | |
| 269 | def BUILD_for_toolchain(name, parent_workspace_name, exec_triple, target_triple): |
| 270 | return _build_file_for_toolchain_template.format( |
| 271 | name = name, |
| 272 | exec_constraint_sets_serialized = serialized_constraint_set_from_triple(exec_triple), |
| 273 | target_constraint_sets_serialized = serialized_constraint_set_from_triple(target_triple), |
| 274 | parent_workspace_name = parent_workspace_name, |
| 275 | ) |
| 276 | |
| 277 | def load_rustfmt(ctx): |
| 278 | """Loads a rustfmt binary and yields corresponding BUILD for it |
| 279 | |
| 280 | Args: |
| 281 | ctx (repository_ctx): The repository rule's context object |
| 282 | |
| 283 | Returns: |
| 284 | str: The BUILD file contents for this rustfmt binary |
| 285 | """ |
| 286 | target_triple = ctx.attr.exec_triple |
| 287 | |
| 288 | load_arbitrary_tool( |
| 289 | ctx, |
| 290 | iso_date = ctx.attr.iso_date, |
| 291 | target_triple = target_triple, |
| 292 | tool_name = "rustfmt", |
| 293 | tool_subdirectories = ["rustfmt-preview"], |
| 294 | version = ctx.attr.rustfmt_version, |
| 295 | ) |
| 296 | |
| 297 | return BUILD_for_rustfmt(target_triple) |
| 298 | |
| 299 | def load_rust_compiler(ctx): |
| 300 | """Loads a rust compiler and yields corresponding BUILD for it |
| 301 | |
| 302 | Args: |
| 303 | ctx (repository_ctx): A repository_ctx. |
| 304 | |
| 305 | Returns: |
| 306 | str: The BUILD file contents for this compiler and compiler library |
| 307 | """ |
| 308 | |
| 309 | target_triple = ctx.attr.exec_triple |
| 310 | load_arbitrary_tool( |
| 311 | ctx, |
| 312 | iso_date = ctx.attr.iso_date, |
| 313 | target_triple = target_triple, |
| 314 | tool_name = "rust", |
| 315 | tool_subdirectories = ["rustc", "clippy-preview", "cargo"], |
| 316 | version = ctx.attr.version, |
| 317 | ) |
| 318 | |
| 319 | compiler_build_file = BUILD_for_compiler(target_triple) + BUILD_for_clippy(target_triple) + BUILD_for_cargo(target_triple) |
| 320 | |
| 321 | return compiler_build_file |
| 322 | |
| 323 | def should_include_rustc_srcs(repository_ctx): |
| 324 | """Determing whether or not to include rustc sources in the toolchain. |
| 325 | |
| 326 | Args: |
| 327 | repository_ctx (repository_ctx): The repository rule's context object |
| 328 | |
| 329 | Returns: |
| 330 | bool: Whether or not to include rustc source files in a `rustc_toolchain` |
| 331 | """ |
| 332 | |
| 333 | # The environment variable will always take precedence over the attribute. |
| 334 | include_rustc_srcs_env = repository_ctx.os.environ.get("RULES_RUST_TOOLCHAIN_INCLUDE_RUSTC_SRCS") |
| 335 | if include_rustc_srcs_env != None: |
| 336 | return include_rustc_srcs_env.lower() in ["true", "1"] |
| 337 | |
| 338 | return getattr(repository_ctx.attr, "include_rustc_srcs", False) |
| 339 | |
| 340 | def load_rust_src(ctx): |
| 341 | """Loads the rust source code. Used by the rust-analyzer rust-project.json generator. |
| 342 | |
| 343 | Args: |
| 344 | ctx (ctx): A repository_ctx. |
| 345 | """ |
| 346 | tool_suburl = produce_tool_suburl("rust-src", None, ctx.attr.version, ctx.attr.iso_date) |
| 347 | static_rust = ctx.os.environ.get("STATIC_RUST_URL", "https://static.rust-lang.org") |
| 348 | url = "{}/dist/{}.tar.gz".format(static_rust, tool_suburl) |
| 349 | |
| 350 | tool_path = produce_tool_path("rust-src", None, ctx.attr.version) |
| 351 | archive_path = tool_path + ".tar.gz" |
| 352 | ctx.download( |
| 353 | url, |
| 354 | output = archive_path, |
| 355 | sha256 = ctx.attr.sha256s.get(tool_suburl) or FILE_KEY_TO_SHA.get(tool_suburl) or "", |
| 356 | auth = _make_auth_dict(ctx, [url]), |
| 357 | ) |
| 358 | ctx.extract( |
| 359 | archive_path, |
| 360 | output = "lib/rustlib/src", |
| 361 | stripPrefix = "{}/rust-src/lib/rustlib/src/rust".format(tool_path), |
| 362 | ) |
| 363 | ctx.file( |
| 364 | "lib/rustlib/src/BUILD.bazel", |
| 365 | """\ |
| 366 | filegroup( |
| 367 | name = "rustc_srcs", |
| 368 | srcs = glob(["**/*"]), |
| 369 | visibility = ["//visibility:public"], |
| 370 | )""", |
| 371 | ) |
| 372 | |
| 373 | def load_rust_stdlib(ctx, target_triple): |
| 374 | """Loads a rust standard library and yields corresponding BUILD for it |
| 375 | |
| 376 | Args: |
| 377 | ctx (repository_ctx): A repository_ctx. |
| 378 | target_triple (str): The rust-style target triple of the tool |
| 379 | |
| 380 | Returns: |
| 381 | str: The BUILD file contents for this stdlib, and a toolchain decl to match |
| 382 | """ |
| 383 | |
| 384 | load_arbitrary_tool( |
| 385 | ctx, |
| 386 | iso_date = ctx.attr.iso_date, |
| 387 | target_triple = target_triple, |
| 388 | tool_name = "rust-std", |
| 389 | tool_subdirectories = ["rust-std-{}".format(target_triple)], |
| 390 | version = ctx.attr.version, |
| 391 | ) |
| 392 | |
| 393 | toolchain_prefix = ctx.attr.toolchain_name_prefix or DEFAULT_TOOLCHAIN_NAME_PREFIX |
| 394 | stdlib_build_file = BUILD_for_stdlib(target_triple) |
| 395 | |
| 396 | stdlib_linkflags = None |
| 397 | if "BAZEL_RUST_STDLIB_LINKFLAGS" in ctx.os.environ: |
| 398 | stdlib_linkflags = ctx.os.environ["BAZEL_RUST_STDLIB_LINKFLAGS"].split(":") |
| 399 | |
| 400 | toolchain_build_file = BUILD_for_rust_toolchain( |
| 401 | name = "{toolchain_prefix}_{target_triple}".format( |
| 402 | toolchain_prefix = toolchain_prefix, |
| 403 | target_triple = target_triple, |
| 404 | ), |
| 405 | exec_triple = ctx.attr.exec_triple, |
| 406 | include_rustc_srcs = should_include_rustc_srcs(ctx), |
| 407 | target_triple = target_triple, |
| 408 | stdlib_linkflags = stdlib_linkflags, |
| 409 | workspace_name = ctx.attr.name, |
| 410 | default_edition = ctx.attr.edition, |
| 411 | include_rustfmt = not (not ctx.attr.rustfmt_version), |
| 412 | ) |
| 413 | |
| 414 | return stdlib_build_file + toolchain_build_file |
| 415 | |
| 416 | def load_rustc_dev_nightly(ctx, target_triple): |
| 417 | """Loads the nightly rustc dev component |
| 418 | |
| 419 | Args: |
| 420 | ctx: A repository_ctx. |
| 421 | target_triple: The rust-style target triple of the tool |
| 422 | """ |
| 423 | |
| 424 | subdir_name = "rustc-dev" |
| 425 | if ctx.attr.iso_date < "2020-12-24": |
| 426 | subdir_name = "rustc-dev-{}".format(target_triple) |
| 427 | |
| 428 | load_arbitrary_tool( |
| 429 | ctx, |
| 430 | iso_date = ctx.attr.iso_date, |
| 431 | target_triple = target_triple, |
| 432 | tool_name = "rustc-dev", |
| 433 | tool_subdirectories = [subdir_name], |
| 434 | version = ctx.attr.version, |
| 435 | ) |
| 436 | |
| 437 | def load_llvm_tools(ctx, target_triple): |
| 438 | """Loads the llvm tools |
| 439 | |
| 440 | Args: |
| 441 | ctx: A repository_ctx. |
| 442 | target_triple: The rust-style target triple of the tool |
| 443 | """ |
| 444 | load_arbitrary_tool( |
| 445 | ctx, |
| 446 | iso_date = ctx.attr.iso_date, |
| 447 | target_triple = target_triple, |
| 448 | tool_name = "llvm-tools", |
| 449 | tool_subdirectories = ["llvm-tools-preview"], |
| 450 | version = ctx.attr.version, |
| 451 | ) |
| 452 | |
| 453 | def check_version_valid(version, iso_date, param_prefix = ""): |
| 454 | """Verifies that the provided rust version and iso_date make sense. |
| 455 | |
| 456 | Args: |
| 457 | version (str): The rustc version |
| 458 | iso_date (str): The rustc nightly version's iso date |
| 459 | param_prefix (str, optional): The name of the tool who's version is being checked. |
| 460 | """ |
| 461 | |
| 462 | if not version and iso_date: |
| 463 | fail("{param_prefix}iso_date must be paired with a {param_prefix}version".format(param_prefix = param_prefix)) |
| 464 | |
| 465 | if version in ("beta", "nightly") and not iso_date: |
| 466 | fail("{param_prefix}iso_date must be specified if version is 'beta' or 'nightly'".format(param_prefix = param_prefix)) |
| 467 | |
| 468 | def serialized_constraint_set_from_triple(target_triple): |
| 469 | """Returns a string representing a set of constraints |
| 470 | |
| 471 | Args: |
| 472 | target_triple (str): The target triple of the constraint set |
| 473 | |
| 474 | Returns: |
| 475 | str: Formatted string representing the serialized constraint |
| 476 | """ |
| 477 | constraint_set = triple_to_constraint_set(target_triple) |
| 478 | constraint_set_strs = [] |
| 479 | for constraint in constraint_set: |
| 480 | constraint_set_strs.append("\"{}\"".format(constraint)) |
| 481 | return "[{}]".format(", ".join(constraint_set_strs)) |
| 482 | |
| 483 | def produce_tool_suburl(tool_name, target_triple, version, iso_date = None): |
| 484 | """Produces a fully qualified Rust tool name for URL |
| 485 | |
| 486 | Args: |
| 487 | tool_name: The name of the tool per static.rust-lang.org |
| 488 | target_triple: The rust-style target triple of the tool |
| 489 | version: The version of the tool among "nightly", "beta', or an exact version. |
| 490 | iso_date: The date of the tool (or None, if the version is a specific version). |
| 491 | |
| 492 | Returns: |
| 493 | str: The fully qualified url path for the specified tool. |
| 494 | """ |
| 495 | path = produce_tool_path(tool_name, target_triple, version) |
| 496 | return iso_date + "/" + path if (iso_date and version in ("beta", "nightly")) else path |
| 497 | |
| 498 | def produce_tool_path(tool_name, target_triple, version): |
| 499 | """Produces a qualified Rust tool name |
| 500 | |
| 501 | Args: |
| 502 | tool_name: The name of the tool per static.rust-lang.org |
| 503 | target_triple: The rust-style target triple of the tool |
| 504 | version: The version of the tool among "nightly", "beta', or an exact version. |
| 505 | |
| 506 | Returns: |
| 507 | str: The qualified path for the specified tool. |
| 508 | """ |
| 509 | if not tool_name: |
| 510 | fail("No tool name was provided") |
| 511 | if not version: |
| 512 | fail("No tool version was provided") |
| 513 | return "-".join([e for e in [tool_name, version, target_triple] if e]) |
| 514 | |
| 515 | def load_arbitrary_tool(ctx, tool_name, tool_subdirectories, version, iso_date, target_triple, sha256 = ""): |
| 516 | """Loads a Rust tool, downloads, and extracts into the common workspace. |
| 517 | |
| 518 | This function sources the tool from the Rust-lang static file server. The index is available at: |
| 519 | - https://static.rust-lang.org/dist/channel-rust-stable.toml |
| 520 | - https://static.rust-lang.org/dist/channel-rust-beta.toml |
| 521 | - https://static.rust-lang.org/dist/channel-rust-nightly.toml |
| 522 | |
| 523 | The environment variable `STATIC_RUST_URL` can be used to replace the schema and hostname of |
| 524 | the URLs used for fetching assets. `https://static.rust-lang.org/dist/channel-rust-stable.toml` |
| 525 | becomes `${STATIC_RUST_URL}/dist/channel-rust-stable.toml` |
| 526 | |
| 527 | Args: |
| 528 | ctx (repository_ctx): A repository_ctx (no attrs required). |
| 529 | tool_name (str): The name of the given tool per the archive naming. |
| 530 | tool_subdirectories (str): The subdirectories of the tool files (at a level below the root directory of |
| 531 | the archive). The root directory of the archive is expected to match |
| 532 | $TOOL_NAME-$VERSION-$TARGET_TRIPLE. |
| 533 | Example: |
| 534 | tool_name |
| 535 | | version |
| 536 | | | target_triple |
| 537 | v v v |
| 538 | rust-1.39.0-x86_64-unknown-linux-gnu/clippy-preview |
| 539 | .../rustc |
| 540 | .../etc |
| 541 | tool_subdirectories = ["clippy-preview", "rustc"] |
| 542 | version (str): The version of the tool among "nightly", "beta', or an exact version. |
| 543 | iso_date (str): The date of the tool (ignored if the version is a specific version). |
| 544 | target_triple (str): The rust-style target triple of the tool |
| 545 | sha256 (str, optional): The expected hash of hash of the Rust tool. Defaults to "". |
| 546 | """ |
| 547 | check_version_valid(version, iso_date, param_prefix = tool_name + "_") |
| 548 | |
| 549 | # View the indices mentioned in the docstring to find the tool_suburl for a given |
| 550 | # tool. |
| 551 | tool_suburl = produce_tool_suburl(tool_name, target_triple, version, iso_date) |
| 552 | urls = [] |
| 553 | |
| 554 | static_rust_url_from_env = ctx.os.environ.get("STATIC_RUST_URL") |
| 555 | if static_rust_url_from_env: |
| 556 | urls.append("{}/dist/{}.tar.gz".format(static_rust_url_from_env, tool_suburl)) |
| 557 | |
| 558 | for url in getattr(ctx.attr, "urls", DEFAULT_STATIC_RUST_URL_TEMPLATES): |
| 559 | new_url = url.format(tool_suburl) |
| 560 | if new_url not in urls: |
| 561 | urls.append(new_url) |
| 562 | |
| 563 | tool_path = produce_tool_path(tool_name, target_triple, version) |
| 564 | archive_path = "{}.tar.gz".format(tool_path) |
| 565 | ctx.download( |
| 566 | urls, |
| 567 | output = archive_path, |
| 568 | sha256 = getattr(ctx.attr, "sha256s", dict()).get(tool_suburl) or |
| 569 | FILE_KEY_TO_SHA.get(tool_suburl) or |
| 570 | sha256, |
| 571 | auth = _make_auth_dict(ctx, urls), |
| 572 | ) |
| 573 | for subdirectory in tool_subdirectories: |
| 574 | ctx.extract( |
| 575 | archive_path, |
| 576 | output = "", |
| 577 | stripPrefix = "{}/{}".format(tool_path, subdirectory), |
| 578 | ) |
| 579 | |
| 580 | def _make_auth_dict(ctx, urls): |
| 581 | auth = getattr(ctx.attr, "auth", {}) |
| 582 | if not auth: |
| 583 | return {} |
| 584 | ret = {} |
| 585 | for url in urls: |
| 586 | ret[url] = auth |
| 587 | return ret |