rust.configure (26042B)
1 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- 2 # vim: set filetype=python: 3 # This Source Code Form is subject to the terms of the Mozilla Public 4 # License, v. 2.0. If a copy of the MPL was not distributed with this 5 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 7 8 # Rust is required by `rust_compiler` below. We allow_missing here 9 # to propagate failures to the better error message there. 10 option(env="RUSTC", nargs=1, help="Path to the rust compiler") 11 option(env="CARGO", nargs=1, help="Path to the Cargo package manager") 12 13 rustc = check_prog( 14 "_RUSTC", 15 ["rustc"], 16 what="rustc", 17 paths=rust_search_path, 18 input="RUSTC", 19 allow_missing=True, 20 ) 21 cargo = check_prog( 22 "_CARGO", 23 ["cargo"], 24 what="cargo", 25 paths=rust_search_path, 26 input="CARGO", 27 allow_missing=True, 28 ) 29 30 31 @template 32 def unwrap_rustup(prog, name): 33 # rustc and cargo can either be rustup wrappers, or they can be the actual, 34 # plain executables. For cargo, on OSX, rustup sets DYLD_LIBRARY_PATH (at 35 # least until https://github.com/rust-lang/rustup.rs/pull/1752 is merged 36 # and shipped) and that can wreak havoc (see bug 1536486). Similarly, for 37 # rustc, rustup silently honors toolchain overrides set by vendored crates 38 # (see bug 1547196). 39 # 40 # In either case, we need to find the plain executables. 41 # 42 # To achieve that, try to run `PROG +stable`. When the rustup wrapper is in 43 # use, it either prints PROG's help and exits with status 0, or prints 44 # an error message (error: toolchain 'stable' is not installed) and exits 45 # with status 1. In the cargo case, when plain cargo is in use, it exits 46 # with a different error message (e.g. "error: no such subcommand: 47 # `+stable`"), and exits with status 101. 48 # 49 # Unfortunately, in the rustc case, when plain rustc is in use, 50 # `rustc +stable` will exit with status 1, complaining about a missing 51 # "+stable" file. We'll examine the error output to try and distinguish 52 # between failing rustup and failing rustc. 53 @depends(prog, dependable(name)) 54 @imports(_from="__builtin__", _import="open") 55 @imports("os") 56 def unwrap(prog, name): 57 if not prog: 58 return 59 60 def from_rustup_which(): 61 out = check_cmd_output("rustup", "which", name, executable=prog).rstrip() 62 # If for some reason the above failed to return something, keep the 63 # PROG we found originally. 64 if out: 65 log.info("Actually using '%s'", out) 66 return out 67 68 log.info("No `rustup which` output, using '%s'", prog) 69 return prog 70 71 (retcode, stdout, stderr) = get_cmd_output(prog, "+stable") 72 73 if name == "cargo" and retcode != 101: 74 prog = from_rustup_which() 75 elif name == "rustc": 76 if retcode == 0: 77 prog = from_rustup_which() 78 elif "+stable" in stderr: 79 # PROG looks like plain `rustc`. 80 pass 81 else: 82 # Assume PROG looks like `rustup`. This case is a little weird, 83 # insofar as the user doesn't have the "stable" toolchain 84 # installed, but go ahead and unwrap anyway: the user might 85 # have only certain versions, beta, or nightly installed, and 86 # we'll catch invalid versions later. 87 prog = from_rustup_which() 88 89 return normalize_path(prog) 90 91 return unwrap 92 93 94 rustc = unwrap_rustup(rustc, "rustc") 95 cargo = unwrap_rustup(cargo, "cargo") 96 97 98 set_config("CARGO", cargo) 99 set_config("RUSTC", rustc) 100 101 102 @depends_if(rustc) 103 @checking("rustc version", lambda info: info.version) 104 def rustc_info(rustc): 105 if not rustc: 106 return 107 out = check_cmd_output(rustc, "--version", "--verbose").splitlines() 108 info = dict((s.strip() for s in line.split(":", 1)) for line in out[1:]) 109 return namespace( 110 version=Version(info.get("release", "0")), 111 commit=info.get("commit-hash", "unknown"), 112 host=info["host"], 113 llvm_version=Version(info.get("LLVM version", "0")), 114 ) 115 116 117 set_config( 118 "RUSTC_VERSION", 119 depends(rustc_info)(lambda info: str(info.version) if info else None), 120 ) 121 122 123 set_config( 124 "RUSTC_LLVM_VERSION", 125 depends(rustc_info)(lambda info: str(info.llvm_version) if info else None), 126 ) 127 128 set_config( 129 "MOZ_CLANG_NEWER_THAN_RUSTC_LLVM", 130 depends(c_compiler, rustc_info)( 131 lambda c_compiler, rustc_info: rustc_info 132 and c_compiler.type == "clang" 133 and c_compiler.version.major > rustc_info.llvm_version.major 134 ), 135 ) 136 137 138 @depends_if(cargo) 139 @checking("cargo version", lambda info: info.version) 140 @imports("re") 141 def cargo_info(cargo): 142 if not cargo: 143 return 144 out = check_cmd_output(cargo, "--version", "--verbose").splitlines() 145 info = dict((s.strip() for s in line.split(":", 1)) for line in out[1:]) 146 version = info.get("release") 147 # Older versions of cargo didn't support --verbose, in which case, they 148 # only output a not-really-pleasant-to-parse output. Fortunately, they 149 # don't error out, so we can just try some regexp matching on the output 150 # we already got. 151 if version is None: 152 VERSION_FORMAT = r"^cargo (\d\.\d+\.\d+).*" 153 154 m = re.search(VERSION_FORMAT, out[0]) 155 # Fail fast if cargo changes its output on us. 156 if not m: 157 die("Could not determine cargo version from output: %s", out) 158 version = m.group(1) 159 160 return namespace( 161 version=Version(version), 162 ) 163 164 165 @depends(rustc_info, cargo_info, target) 166 @imports(_from="mozboot.util", _import="MINIMUM_RUST_VERSION") 167 @imports(_from="textwrap", _import="dedent") 168 def rust_compiler(rustc_info, cargo_info, target): 169 if not rustc_info: 170 die( 171 dedent( 172 """\ 173 Rust compiler not found. 174 To compile rust language sources, you must have 'rustc' in your path. 175 See https://www.rust-lang.org/ for more information. 176 177 You can install rust by running './mach bootstrap' 178 or by directly running the installer from https://rustup.rs/ 179 """ 180 ) 181 ) 182 rustc_min_version = Version(MINIMUM_RUST_VERSION) 183 cargo_min_version = rustc_min_version 184 185 version = rustc_info.version 186 is_nightly = "nightly" in version.version 187 is_version_number_match = ( 188 version.major == rustc_min_version.major 189 and version.minor == rustc_min_version.minor 190 and version.patch == rustc_min_version.patch 191 ) 192 193 if version < rustc_min_version or (is_version_number_match and is_nightly): 194 die( 195 dedent( 196 """\ 197 Rust compiler {} is too old. 198 199 To compile Rust language sources please install at least 200 version {} of the 'rustc' toolchain (or, if using nightly, 201 at least one version newer than {}) and make sure it is 202 first in your path. 203 204 You can verify this by typing 'rustc --version'. 205 206 If you have the 'rustup' tool installed you can upgrade 207 to the latest release by typing 'rustup update'. The 208 installer is available from https://rustup.rs/ 209 """.format( 210 version, rustc_min_version, rustc_min_version 211 ) 212 ) 213 ) 214 215 if target.kernel == "WINNT" and (version.major, version.minor) == (1, 56): 216 die( 217 dedent( 218 """\ 219 Rust compiler 1.56.* is not supported for Windows builds. 220 221 Use a newer or an older version. 222 223 See https://github.com/rust-lang/rust/issues/88576. 224 """ 225 ) 226 ) 227 228 if not cargo_info: 229 die( 230 dedent( 231 """\ 232 Cargo package manager not found. 233 To compile Rust language sources, you must have 'cargo' in your path. 234 See https://www.rust-lang.org/ for more information. 235 236 You can install cargo by running './mach bootstrap' 237 or by directly running the installer from https://rustup.rs/ 238 """ 239 ) 240 ) 241 242 version = cargo_info.version 243 if version < cargo_min_version: 244 die( 245 dedent( 246 """\ 247 Cargo package manager {} is too old. 248 249 To compile Rust language sources please install at least 250 version {} of 'cargo' and make sure it is first in your path. 251 252 You can verify this by typing 'cargo --version'. 253 """ 254 ).format(version, cargo_min_version) 255 ) 256 257 return True 258 259 260 @depends(rustc, when=rust_compiler) 261 @imports(_from="__builtin__", _import="ValueError") 262 def rust_supported_targets(rustc): 263 out = check_cmd_output(rustc, "--print", "target-list").splitlines() 264 data = {} 265 for t in out: 266 try: 267 info = split_triplet(t, allow_wasi=True) 268 except ValueError: 269 if t.startswith("thumb"): 270 cpu, rest = t.split("-", 1) 271 retry = "-".join(("arm", rest)) 272 else: 273 continue 274 try: 275 info = split_triplet(retry, allow_wasi=True) 276 except ValueError: 277 continue 278 key = (info.cpu, info.endianness, info.os) 279 data.setdefault(key, []).append(namespace(rust_target=t, target=info)) 280 return data 281 282 283 def detect_rustc_target( 284 host_or_target, compiler_info, arm_target, rust_supported_targets 285 ): 286 # Rust's --target options are similar to, but not exactly the same 287 # as, the autoconf-derived targets we use. An example would be that 288 # Rust uses distinct target triples for targetting the GNU C++ ABI 289 # and the MSVC C++ ABI on Win32, whereas autoconf has a single 290 # triple and relies on the user to ensure that everything is 291 # compiled for the appropriate ABI. We need to perform appropriate 292 # munging to get the correct option to rustc. 293 # We correlate the autoconf-derived targets with the list of targets 294 # rustc gives us with --print target-list. 295 candidates = rust_supported_targets.get( 296 (host_or_target.cpu, host_or_target.endianness, host_or_target.os), [] 297 ) 298 299 def find_candidate(candidates): 300 if len(candidates) == 1: 301 return candidates[0].rust_target 302 elif not candidates: 303 return None 304 305 # We have multiple candidates. There are two cases where we can try to 306 # narrow further down using extra information from the build system. 307 # - For windows targets, correlate with the C compiler type 308 if host_or_target.kernel == "WINNT": 309 if host_or_target.abi: 310 if host_or_target.abi == "msvc": 311 suffix = "windows-msvc" 312 elif host_or_target.abi == "mingw": 313 suffix = "windows-gnullvm" 314 elif compiler_info.type in ("gcc", "clang"): 315 suffix = "windows-gnullvm" 316 else: 317 suffix = "windows-msvc" 318 narrowed = [ 319 c for c in candidates if c.rust_target.endswith("-{}".format(suffix)) 320 ] 321 if len(narrowed) == 1: 322 return narrowed[0].rust_target 323 elif narrowed: 324 candidates = narrowed 325 326 vendor_aliases = {"pc": ("w64", "windows")} 327 narrowed = [ 328 c 329 for c in candidates 330 if host_or_target.vendor in vendor_aliases.get(c.target.vendor, ()) 331 ] 332 333 if len(narrowed) == 1: 334 return narrowed[0].rust_target 335 336 # - For arm targets, correlate with arm_target 337 # we could be more thorough with the supported rust targets, but they 338 # don't support OSes that are supported to build Gecko anyways. 339 # Also, sadly, the only interface to check the rust target cpu features 340 # is --print target-spec-json, and it's unstable, so we have to rely on 341 # our own knowledge of what each arm target means. 342 if host_or_target.cpu == "arm" and host_or_target.endianness == "little": 343 prefixes = [] 344 if arm_target.arm_arch >= 7: 345 if arm_target.thumb2 and arm_target.fpu == "neon": 346 prefixes.append("thumbv7neon") 347 if arm_target.thumb2: 348 prefixes.append("thumbv7a") 349 prefixes.append("armv7") 350 if arm_target.arm_arch >= 6: 351 prefixes.append("armv6") 352 if host_or_target.os != "Android": 353 # arm-* rust targets are armv6... except arm-linux-androideabi 354 prefixes.append("arm") 355 if arm_target.arm_arch >= 5: 356 prefixes.append("armv5te") 357 if host_or_target.os == "Android": 358 # arm-* rust targets are armv6... except arm-linux-androideabi 359 prefixes.append("arm") 360 if arm_target.arm_arch >= 4: 361 prefixes.append("armv4t") 362 # rust freebsd targets are the only ones that don't have a 'hf' suffix 363 # for hard-float. Technically, that means if the float abi ever is not 364 # hard-float, this will pick a wrong target, but since rust only 365 # supports hard-float, let's assume that means freebsd only support 366 # hard-float. 367 if arm_target.float_abi == "hard" and host_or_target.os != "FreeBSD": 368 suffix = "hf" 369 else: 370 suffix = "" 371 for p in prefixes: 372 for c in candidates: 373 if c.rust_target.startswith( 374 "{}-".format(p) 375 ) and c.rust_target.endswith(suffix): 376 return c.rust_target 377 378 # See if we can narrow down on the exact alias. 379 # We use the sub_configure_alias to keep support mingw32 triplets as input. 380 narrowed = [ 381 c 382 for c in candidates 383 if c.target.sub_configure_alias == host_or_target.sub_configure_alias 384 ] 385 if len(narrowed) == 1: 386 return narrowed[0].rust_target 387 elif narrowed: 388 candidates = narrowed 389 390 # See if we can narrow down with the raw OS 391 narrowed = [c for c in candidates if c.target.raw_os == host_or_target.raw_os] 392 if len(narrowed) == 1: 393 return narrowed[0].rust_target 394 elif narrowed: 395 candidates = narrowed 396 397 # The wasm32-wasi target was renamed to wasm32-wasip1 398 if host_or_target.raw_os == "wasi": 399 narrowed = [c for c in candidates if c.target.raw_os == "wasip1"] 400 if len(narrowed) == 1: 401 return narrowed[0].rust_target 402 elif narrowed: 403 candidates = narrowed 404 405 # See if we can narrow down with the raw OS and raw CPU 406 narrowed = [ 407 c 408 for c in candidates 409 if c.target.raw_os == host_or_target.raw_os 410 and c.target.raw_cpu == host_or_target.raw_cpu 411 ] 412 if len(narrowed) == 1: 413 return narrowed[0].rust_target 414 415 # Finally, see if the vendor can be used to disambiguate. 416 narrowed = [c for c in candidates if c.target.vendor == host_or_target.vendor] 417 if len(narrowed) == 1: 418 return narrowed[0].rust_target 419 420 return None 421 422 rustc_target = find_candidate(candidates) 423 424 if rustc_target is None: 425 die("Don't know how to translate {} for rustc".format(host_or_target.alias)) 426 427 return rustc_target 428 429 430 @imports("os") 431 @imports(_from="textwrap", _import="dedent") 432 @imports(_from="mozbuild.configure.util", _import="LineIO") 433 @imports(_from="__builtin__", _import="open") 434 def assert_rust_compile(host_or_target, rustc_target, rustc): 435 # Check to see whether our rustc has a reasonably functional stdlib 436 # for our chosen target. 437 target_arg = "--target=" + rustc_target 438 with create_temporary_file(suffix=".rs") as in_path, create_temporary_file( 439 suffix=".rlib" 440 ) as out_path: 441 with open(in_path, "w") as fd: 442 source = b'pub extern "C" fn hello() { println!("Hello world"); }' 443 log.debug("Creating `%s` with content:", in_path) 444 with LineIO(lambda l: log.debug("| %s", l)) as out: 445 out.write(source) 446 447 fd.write(source.decode()) 448 449 cmd = [ 450 rustc, 451 "--crate-type", 452 "staticlib", 453 target_arg, 454 "-o", 455 out_path, 456 in_path, 457 ] 458 459 def failed(): 460 die( 461 dedent( 462 """\ 463 Cannot compile for {} with {} 464 The target may be unsupported, or you may not have 465 a rust std library for that target installed. Try: 466 467 rustup target add {} 468 """.format( 469 host_or_target.alias, rustc, rustc_target 470 ) 471 ) 472 ) 473 474 check_cmd_output(*cmd, onerror=failed) 475 if not os.path.exists(out_path) or os.path.getsize(out_path) == 0: 476 failed() 477 478 479 @depends( 480 rustc, 481 host, 482 host_c_compiler, 483 rustc_info.host, 484 rust_supported_targets, 485 arm_target, 486 when=rust_compiler, 487 ) 488 @checking("for rust host triplet") 489 @imports(_from="textwrap", _import="dedent") 490 def rust_host_triple( 491 rustc, host, compiler_info, rustc_host, rust_supported_targets, arm_target 492 ): 493 rustc_target = detect_rustc_target( 494 host, compiler_info, arm_target, rust_supported_targets 495 ) 496 if rustc_target != rustc_host: 497 if host.alias == rustc_target: 498 configure_host = host.alias 499 else: 500 configure_host = "{}/{}".format(host.alias, rustc_target) 501 die( 502 dedent( 503 """\ 504 The rust compiler host ({rustc}) is not suitable for the configure host ({configure}). 505 506 To resolve this, install and select a Rust toolchain for {rustc_target}: 507 rustup default stable-{rustc_target} 508 509 Then rerun configure. 510 """.format( 511 rustc=rustc_host, 512 configure=configure_host, 513 rustc_target=rustc_target, 514 ) 515 ) 516 ) 517 assert_rust_compile(host, rustc_target, rustc) 518 return rustc_target 519 520 521 @depends( 522 rustc, target, c_compiler, rust_supported_targets, arm_target, when=rust_compiler 523 ) 524 @checking("for rust target triplet") 525 def rust_target_triple( 526 rustc, target, compiler_info, rust_supported_targets, arm_target 527 ): 528 rustc_target = detect_rustc_target( 529 target, compiler_info, arm_target, rust_supported_targets 530 ) 531 assert_rust_compile(target, rustc_target, rustc) 532 return rustc_target 533 534 535 set_config("RUST_TARGET", rust_target_triple) 536 set_config("RUST_HOST_TARGET", rust_host_triple) 537 538 539 # This is used for putting source info into symbol files. 540 set_config("RUSTC_COMMIT", depends(rustc_info)(lambda i: i.commit)) 541 542 # Rustdoc is required by Rust tests below. 543 option(env="RUSTDOC", nargs=1, help="Path to the rustdoc program") 544 545 rustdoc = check_prog( 546 "RUSTDOC", 547 ["rustdoc"], 548 paths=rust_search_path, 549 input="RUSTDOC", 550 allow_missing=True, 551 ) 552 553 option( 554 env="RUSTDOCFLAGS", 555 nargs=1, 556 help="Extra options for the rustdoc program", 557 ) 558 set_config("RUSTDOCFLAGS", depends_if("RUSTDOCFLAGS")(lambda flags: flags[0])) 559 560 # This option is separate from --enable-tests because Rust tests are particularly 561 # expensive in terms of compile time (especially for code in libxul). 562 option( 563 "--enable-rust-tests", 564 help="Enable building and running of Rust tests during `make check`", 565 ) 566 567 568 @depends("--enable-rust-tests", rustdoc) 569 def rust_tests(enable_rust_tests, rustdoc): 570 if enable_rust_tests and not rustdoc: 571 die("--enable-rust-tests requires rustdoc") 572 return bool(enable_rust_tests) 573 574 575 set_config("MOZ_RUST_TESTS", rust_tests) 576 577 578 @depends(target, c_compiler, rustc) 579 @imports("os") 580 def rustc_natvis_ldflags(target, compiler_info, rustc): 581 if target.kernel == "WINNT" and compiler_info.type == "clang-cl": 582 sysroot = check_cmd_output(rustc, "--print", "sysroot").strip() 583 etc = os.path.join(sysroot, "lib/rustlib/etc") 584 ldflags = [] 585 if os.path.isdir(etc): 586 for f in os.listdir(etc): 587 if f.endswith(".natvis"): 588 ldflags.append("-NATVIS:" + normsep(os.path.join(etc, f))) 589 return ldflags 590 591 592 set_config("RUSTC_NATVIS_LDFLAGS", rustc_natvis_ldflags) 593 594 595 option( 596 "--enable-rust-debug", 597 default=depends(when="--enable-debug")(lambda: True), 598 help="{Build|Do not build} Rust code with debug assertions turned on", 599 ) 600 601 602 @depends(when="--enable-rust-debug") 603 def debug_rust(): 604 return True 605 606 607 set_config("MOZ_DEBUG_RUST", debug_rust) 608 set_define("MOZ_DEBUG_RUST", debug_rust) 609 610 # ============================================================== 611 612 option(env="RUSTFLAGS", nargs=1, help="Rust compiler flags") 613 set_config("RUSTFLAGS", depends("RUSTFLAGS")(lambda flags: flags)) 614 615 616 # Rust compiler flags 617 # ============================================================== 618 619 620 @depends(moz_optimize) 621 def rustc_opt_level_default(moz_optimize): 622 return "2" if moz_optimize else "0" 623 624 625 option( 626 env="RUSTC_OPT_LEVEL", 627 default=rustc_opt_level_default, 628 nargs=1, 629 help="Rust compiler optimization level (-C opt-level=%s)", 630 ) 631 632 633 @depends("RUSTC_OPT_LEVEL") 634 def rustc_opt_level(opt_level_option): 635 return opt_level_option[0] 636 637 638 set_config("CARGO_PROFILE_RELEASE_OPT_LEVEL", rustc_opt_level) 639 set_config("CARGO_PROFILE_DEV_OPT_LEVEL", rustc_opt_level) 640 641 642 @depends( 643 rustc_opt_level, 644 debug_rust, 645 target, 646 "--enable-debug-symbols", 647 "--enable-frame-pointers", 648 path_remapping, 649 path_remappings, 650 ) 651 def rust_compile_flags( 652 opt_level, 653 debug_rust, 654 target, 655 debug_symbols, 656 frame_pointers, 657 path_remapping, 658 path_remappings, 659 ): 660 # Cargo currently supports only two interesting profiles for building: 661 # development and release. Those map (roughly) to --enable-debug and 662 # --disable-debug in Gecko, respectively. 663 # 664 # But we'd also like to support an additional axis of control for 665 # optimization level. Since Cargo only supports 2 profiles, we're in 666 # a bit of a bind. 667 # 668 # Code here derives various compiler options given other configure options. 669 # The options defined here effectively override defaults specified in 670 # Cargo.toml files. 671 672 debug_assertions = None 673 debug_info = None 674 675 # opt-level=0 implies -C debug-assertions, which may not be desired 676 # unless Rust debugging is enabled. 677 if opt_level == "0" and not debug_rust: 678 debug_assertions = False 679 680 if debug_symbols: 681 debug_info = "2" 682 683 opts = [] 684 685 if debug_assertions is not None: 686 opts.append("debug-assertions=%s" % ("yes" if debug_assertions else "no")) 687 if debug_info is not None: 688 opts.append("debuginfo=%s" % debug_info) 689 if frame_pointers: 690 opts.append("force-frame-pointers=yes") 691 # CFG for arm64 is crashy, see `def security_hardening_cflags`. 692 if target.kernel == "WINNT" and target.cpu != "aarch64": 693 opts.append("control-flow-guard=yes") 694 695 flags = [] 696 for opt in opts: 697 flags.extend(["-C", opt]) 698 699 if "rust" in path_remapping: 700 # rustc has supported --remap-path-prefix since version 1.26, well 701 # before our required minimum Rust version, so there's no need to 702 # feature-detect or gate on versions. 703 for old, new in path_remappings: 704 flags.append(f"--remap-path-prefix={old}={new}") 705 706 return flags 707 708 709 # Rust incremental compilation 710 # ============================================================== 711 712 713 option("--disable-cargo-incremental", help="Disable incremental rust compilation") 714 715 716 @depends( 717 developer_options, 718 debug_rust, 719 moz_automation, 720 code_coverage, 721 "--disable-cargo-incremental", 722 using_sccache, 723 "RUSTC_WRAPPER", 724 ) 725 @imports("os") 726 def cargo_incremental( 727 developer_options, 728 debug_rust, 729 automation, 730 code_coverage, 731 enabled, 732 using_sccache, 733 rustc_wrapper, 734 ): 735 """Return a value for the CARGO_INCREMENTAL environment variable.""" 736 737 if not enabled: 738 return "0" 739 elif enabled.origin != "default": 740 return "1" 741 742 # We never want to use incremental compilation in automation. sccache 743 # handles our automation use case much better than incremental compilation 744 # would. 745 if automation: 746 return "0" 747 748 # Coverage instrumentation doesn't play well with incremental compilation 749 # https://github.com/rust-lang/rust/issues/50203. 750 if code_coverage: 751 return "0" 752 753 # Incremental compilation doesn't work as well as it should, and if we're 754 # using sccache, it's better to use sccache than incremental compilation. 755 if not using_sccache and rustc_wrapper: 756 rustc_wrapper = os.path.basename(rustc_wrapper[0]) 757 if os.path.splitext(rustc_wrapper)[0].lower() == "sccache": 758 using_sccache = True 759 if using_sccache: 760 return "0" 761 762 # Incremental compilation is automatically turned on for debug builds, so 763 # we don't need to do anything special here. 764 if debug_rust: 765 return 766 767 # Don't enable on --enable-release builds, because of the runtime 768 # performance cost. 769 if not developer_options: 770 return 771 772 # We're clear to use incremental compilation! 773 return "1" 774 775 776 set_config("CARGO_INCREMENTAL", cargo_incremental) 777 778 779 @depends(rust_compile_flags, "--enable-warnings-as-errors") 780 def rust_flags(compile_flags, warnings_as_errors): 781 warning_flags = [] 782 783 # Note that cargo passes --cap-lints warn to rustc for third-party code, so 784 # we don't need a very complicated setup. 785 if warnings_as_errors: 786 warning_flags.append("-Dwarnings") 787 else: 788 warning_flags.extend(("--cap-lints", "warn")) 789 790 return compile_flags + warning_flags 791 792 793 set_config("MOZ_RUST_DEFAULT_FLAGS", rust_flags)