1use std::any::{Any, type_name};
2use std::cell::{Cell, RefCell};
3use std::collections::BTreeSet;
4use std::fmt::{Debug, Write};
5use std::hash::Hash;
6use std::ops::Deref;
7use std::path::{Path, PathBuf};
8use std::sync::OnceLock;
9use std::time::{Duration, Instant};
10use std::{env, fs};
11
12use clap::ValueEnum;
13#[cfg(feature = "tracing")]
14use tracing::instrument;
15
16pub use self::cargo::{Cargo, cargo_profile_var};
17pub use crate::Compiler;
18use crate::core::build_steps::compile::{Std, StdLink};
19use crate::core::build_steps::tool::RustcPrivateCompilers;
20use crate::core::build_steps::{
21 check, clean, clippy, compile, dist, doc, gcc, install, llvm, run, setup, test, tool, vendor,
22};
23use crate::core::builder::cli_paths::CLIStepPath;
24use crate::core::builder::step_stack::StepRecord;
25pub use crate::core::builder::step_stack::StepStack;
26use crate::core::config::flags::Subcommand;
27use crate::core::config::{DryRun, TargetSelection};
28use crate::utils::build_stamp::BuildStamp;
29use crate::utils::cache::Cache;
30use crate::utils::exec::{BootstrapCommand, ExecutionContext, command};
31use crate::utils::helpers::{self, LldThreads, add_dylib_path, exe, libdir, linker_args, t};
32use crate::utils::tracing::format_location;
33use crate::{Build, Crate, trace};
34
35mod cargo;
36mod cli_paths;
37mod step_stack;
38#[cfg(test)]
39mod tests;
40
41pub struct Builder<'a> {
44 pub build: &'a Build,
46
47 pub top_stage: u32,
51
52 pub kind: Kind,
54
55 cache: Cache,
58
59 stack: RefCell<Vec<Box<dyn AnyDebug>>>,
62
63 time_spent_on_dependencies: Cell<Duration>,
65
66 pub paths: Vec<PathBuf>,
70
71 submodule_paths_cache: OnceLock<Vec<String>>,
73
74 #[expect(clippy::type_complexity)]
78 log_cli_step_for_tests: Option<Box<dyn Fn(&StepDescription, &[PathSet], &[TargetSelection])>>,
79}
80
81impl Deref for Builder<'_> {
82 type Target = Build;
83
84 fn deref(&self) -> &Self::Target {
85 self.build
86 }
87}
88
89pub trait AnyDebug: Any + Debug {}
94impl<T: Any + Debug> AnyDebug for T {}
95impl dyn AnyDebug {
96 fn downcast_ref<T: Any>(&self) -> Option<&T> {
98 (self as &dyn Any).downcast_ref()
99 }
100
101 }
103
104pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash {
105 type Output: Clone;
107
108 const IS_HOST: bool = false;
115
116 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_>;
119
120 fn is_default_step(_builder: &Builder<'_>) -> bool {
134 false
135 }
136
137 fn run(self, builder: &Builder<'_>) -> Self::Output;
151
152 fn make_run(_run: RunConfig<'_>) {
156 unimplemented!()
161 }
162
163 fn metadata(&self) -> Option<StepMetadata> {
165 None
166 }
167}
168
169#[derive(Clone, Debug, PartialEq, Eq)]
171pub struct StepMetadata {
172 name: String,
173 kind: Kind,
174 target: TargetSelection,
175 built_by: Option<Compiler>,
176 stage: Option<u32>,
177 metadata: Option<String>,
179}
180
181impl StepMetadata {
182 pub fn build(name: &str, target: TargetSelection) -> Self {
183 Self::new(name, target, Kind::Build)
184 }
185
186 pub fn check(name: &str, target: TargetSelection) -> Self {
187 Self::new(name, target, Kind::Check)
188 }
189
190 pub fn clippy(name: &str, target: TargetSelection) -> Self {
191 Self::new(name, target, Kind::Clippy)
192 }
193
194 pub fn doc(name: &str, target: TargetSelection) -> Self {
195 Self::new(name, target, Kind::Doc)
196 }
197
198 pub fn dist(name: &str, target: TargetSelection) -> Self {
199 Self::new(name, target, Kind::Dist)
200 }
201
202 pub fn test(name: &str, target: TargetSelection) -> Self {
203 Self::new(name, target, Kind::Test)
204 }
205
206 pub fn run(name: &str, target: TargetSelection) -> Self {
207 Self::new(name, target, Kind::Run)
208 }
209
210 fn new(name: &str, target: TargetSelection, kind: Kind) -> Self {
211 Self { name: name.to_string(), kind, target, built_by: None, stage: None, metadata: None }
212 }
213
214 pub fn built_by(mut self, compiler: Compiler) -> Self {
215 self.built_by = Some(compiler);
216 self
217 }
218
219 pub fn stage(mut self, stage: u32) -> Self {
220 self.stage = Some(stage);
221 self
222 }
223
224 pub fn with_metadata(mut self, metadata: String) -> Self {
225 self.metadata = Some(metadata);
226 self
227 }
228
229 pub fn get_stage(&self) -> Option<u32> {
230 self.stage.or(self
231 .built_by
232 .map(|compiler| if self.name == "std" { compiler.stage } else { compiler.stage + 1 }))
235 }
236
237 pub fn get_name(&self) -> &str {
238 &self.name
239 }
240
241 pub fn get_target(&self) -> TargetSelection {
242 self.target
243 }
244}
245
246pub struct RunConfig<'a> {
247 pub builder: &'a Builder<'a>,
248 pub target: TargetSelection,
249 pub paths: Vec<PathSet>,
250}
251
252impl RunConfig<'_> {
253 pub fn build_triple(&self) -> TargetSelection {
254 self.builder.build.host_target
255 }
256
257 #[track_caller]
259 pub fn cargo_crates_in_set(&self) -> Vec<String> {
260 let mut crates = Vec::new();
261 for krate in &self.paths {
262 let path = &krate.assert_single_path().path;
263
264 let crate_name = self
265 .builder
266 .crate_paths
267 .get(path)
268 .unwrap_or_else(|| panic!("missing crate for path {}", path.display()));
269
270 crates.push(crate_name.to_string());
271 }
272 crates
273 }
274
275 pub fn make_run_crates(&self, alias: Alias) -> Vec<String> {
282 let has_alias =
283 self.paths.iter().any(|set| set.assert_single_path().path.ends_with(alias.as_str()));
284 if !has_alias {
285 return self.cargo_crates_in_set();
286 }
287
288 let crates = match alias {
289 Alias::Library => self.builder.in_tree_crates("sysroot", Some(self.target)),
290 Alias::Compiler => self.builder.in_tree_crates("rustc-main", Some(self.target)),
291 };
292
293 crates.into_iter().map(|krate| krate.name.to_string()).collect()
294 }
295}
296
297#[derive(Debug, Copy, Clone)]
298pub enum Alias {
299 Library,
300 Compiler,
301}
302
303impl Alias {
304 fn as_str(self) -> &'static str {
305 match self {
306 Alias::Library => "library",
307 Alias::Compiler => "compiler",
308 }
309 }
310}
311
312pub fn crate_description(crates: &[impl AsRef<str>]) -> String {
316 if crates.is_empty() {
317 return "".into();
318 }
319
320 let mut descr = String::from("{");
321 descr.push_str(crates[0].as_ref());
322 for krate in &crates[1..] {
323 descr.push_str(", ");
324 descr.push_str(krate.as_ref());
325 }
326 descr.push('}');
327 descr
328}
329
330struct StepDescription {
331 is_host: bool,
332 should_run: fn(ShouldRun<'_>) -> ShouldRun<'_>,
333 is_default_step_fn: fn(&Builder<'_>) -> bool,
334 make_run: fn(RunConfig<'_>),
335 name: &'static str,
336 kind: Kind,
337}
338
339#[derive(Clone, PartialOrd, Ord, PartialEq, Eq)]
340pub struct TaskPath {
341 pub path: PathBuf,
342 pub kind: Option<Kind>,
343}
344
345impl Debug for TaskPath {
346 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
347 if let Some(kind) = &self.kind {
348 write!(f, "{}::", kind.as_str())?;
349 }
350 write!(f, "{}", self.path.display())
351 }
352}
353
354#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
356pub enum PathSet {
357 Set(BTreeSet<TaskPath>),
368 Suite(TaskPath),
375}
376
377impl PathSet {
378 fn empty() -> PathSet {
379 PathSet::Set(BTreeSet::new())
380 }
381
382 fn one<P: Into<PathBuf>>(path: P, kind: Kind) -> PathSet {
383 let mut set = BTreeSet::new();
384 set.insert(TaskPath { path: path.into(), kind: Some(kind) });
385 PathSet::Set(set)
386 }
387
388 fn has(&self, needle: &Path, module: Kind) -> bool {
389 match self {
390 PathSet::Set(set) => set.iter().any(|p| Self::check(p, needle, module)),
391 PathSet::Suite(suite) => Self::check(suite, needle, module),
392 }
393 }
394
395 fn check(p: &TaskPath, needle: &Path, module: Kind) -> bool {
397 let check_path = || {
398 p.path.ends_with(needle) || p.path.starts_with(needle)
400 };
401 if let Some(p_kind) = &p.kind { check_path() && *p_kind == module } else { check_path() }
402 }
403
404 fn intersection_removing_matches(&self, needles: &mut [CLIStepPath], module: Kind) -> PathSet {
411 let mut check = |p| {
412 let mut result = false;
413 for n in needles.iter_mut() {
414 let matched = Self::check(p, &n.path, module);
415 if matched {
416 n.will_be_executed = true;
417 result = true;
418 }
419 }
420 result
421 };
422 match self {
423 PathSet::Set(set) => PathSet::Set(set.iter().filter(|&p| check(p)).cloned().collect()),
424 PathSet::Suite(suite) => {
425 if check(suite) {
426 self.clone()
427 } else {
428 PathSet::empty()
429 }
430 }
431 }
432 }
433
434 #[track_caller]
438 pub fn assert_single_path(&self) -> &TaskPath {
439 match self {
440 PathSet::Set(set) => {
441 assert_eq!(set.len(), 1, "called assert_single_path on multiple paths");
442 set.iter().next().unwrap()
443 }
444 PathSet::Suite(_) => unreachable!("called assert_single_path on a Suite path"),
445 }
446 }
447}
448
449impl StepDescription {
450 fn from<S: Step>(kind: Kind) -> StepDescription {
451 StepDescription {
452 is_host: S::IS_HOST,
453 should_run: S::should_run,
454 is_default_step_fn: S::is_default_step,
455 make_run: S::make_run,
456 name: std::any::type_name::<S>(),
457 kind,
458 }
459 }
460
461 fn maybe_run(&self, builder: &Builder<'_>, mut pathsets: Vec<PathSet>) {
462 pathsets.retain(|set| !self.is_excluded(builder, set));
463
464 if pathsets.is_empty() {
465 return;
466 }
467
468 let targets = if self.is_host { &builder.hosts } else { &builder.targets };
470
471 if let Some(ref log_cli_step) = builder.log_cli_step_for_tests {
473 log_cli_step(self, &pathsets, targets);
474 return;
476 }
477
478 for target in targets {
479 let run = RunConfig { builder, paths: pathsets.clone(), target: *target };
480 (self.make_run)(run);
481 }
482 }
483
484 fn is_excluded(&self, builder: &Builder<'_>, pathset: &PathSet) -> bool {
485 if builder.config.skip.iter().any(|e| pathset.has(e, builder.kind)) {
486 if !matches!(builder.config.get_dry_run(), DryRun::SelfCheck) {
487 println!("Skipping {pathset:?} because it is excluded");
488 }
489 return true;
490 }
491
492 if !builder.config.skip.is_empty()
493 && !matches!(builder.config.get_dry_run(), DryRun::SelfCheck)
494 {
495 builder.do_if_verbose(|| {
496 println!(
497 "{:?} not skipped for {:?} -- not in {:?}",
498 pathset, self.name, builder.config.skip
499 )
500 });
501 }
502 false
503 }
504}
505
506pub struct ShouldRun<'a> {
513 pub builder: &'a Builder<'a>,
514 kind: Kind,
515
516 paths: BTreeSet<PathSet>,
518}
519
520impl<'a> ShouldRun<'a> {
521 fn new(builder: &'a Builder<'_>, kind: Kind) -> ShouldRun<'a> {
522 ShouldRun { builder, kind, paths: BTreeSet::new() }
523 }
524
525 pub fn crate_or_deps(self, name: &str) -> Self {
530 let crates = self.builder.in_tree_crates(name, None);
531 self.crates(crates)
532 }
533
534 pub(crate) fn crates(mut self, crates: Vec<&Crate>) -> Self {
540 for krate in crates {
541 let path = krate.local_path(self.builder);
542 self.paths.insert(PathSet::one(path, self.kind));
543 }
544 self
545 }
546
547 pub fn alias(mut self, alias: &str) -> Self {
549 assert!(
553 self.kind == Kind::Setup || !self.builder.src.join(alias).exists(),
554 "use `builder.path()` for real paths: {alias}"
555 );
556 self.paths.insert(PathSet::Set(
557 std::iter::once(TaskPath { path: alias.into(), kind: Some(self.kind) }).collect(),
558 ));
559 self
560 }
561
562 fn assert_valid_path(&self, path: &str) {
563 let submodules_paths = self.builder.submodule_paths();
564
565 if !submodules_paths.iter().any(|sm_p| path.contains(sm_p)) {
567 assert!(
568 self.builder.src.join(path).exists(),
569 "`should_run.path` should correspond to a real on-disk path - use `alias` if there is no relevant path: {path}"
570 );
571 }
572 }
573
574 pub fn path(mut self, path: &str) -> Self {
579 self.assert_valid_path(path);
580
581 let task = TaskPath { path: path.into(), kind: Some(self.kind) };
582 self.paths.insert(PathSet::Set(BTreeSet::from_iter([task])));
583 self
584 }
585
586 pub fn selectors(mut self, paths: &[&str]) -> Self {
588 let mut set = BTreeSet::new();
589 for path in paths {
590 self.assert_valid_path(path);
591 set.insert(TaskPath { path: (*path).into(), kind: Some(self.kind) });
592 }
593 self.paths.insert(PathSet::Set(set));
594 self
595 }
596
597 fn is_suite_path(&self, requested_path: &Path) -> Option<&PathSet> {
599 self.paths.iter().find(|pathset| match pathset {
600 PathSet::Suite(suite) => requested_path.starts_with(&suite.path),
601 PathSet::Set(_) => false,
602 })
603 }
604
605 pub fn suite_path(mut self, suite: &str) -> Self {
606 self.paths.insert(PathSet::Suite(TaskPath { path: suite.into(), kind: Some(self.kind) }));
607 self
608 }
609
610 pub fn never(mut self) -> ShouldRun<'a> {
612 self.paths.insert(PathSet::empty());
613 self
614 }
615
616 fn pathset_for_paths_removing_matches(
626 &self,
627 paths: &mut [CLIStepPath],
628 kind: Kind,
629 ) -> Vec<PathSet> {
630 let mut sets = vec![];
631 for pathset in &self.paths {
632 let subset = pathset.intersection_removing_matches(paths, kind);
633 if subset != PathSet::empty() {
634 sets.push(subset);
635 }
636 }
637 sets
638 }
639}
640
641#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, PartialOrd, Ord, ValueEnum)]
642pub enum Kind {
643 #[value(alias = "b")]
644 Build,
645 #[value(alias = "c")]
646 Check,
647 Clippy,
648 Fix,
649 Format,
650 #[value(alias = "t")]
651 Test,
652 Miri,
653 MiriSetup,
654 MiriTest,
655 Bench,
656 #[value(alias = "d")]
657 Doc,
658 Clean,
659 Dist,
660 Install,
661 #[value(alias = "r")]
662 Run,
663 Setup,
664 Vendor,
665 Perf,
666}
667
668impl Kind {
669 pub fn as_str(&self) -> &'static str {
670 match self {
671 Kind::Build => "build",
672 Kind::Check => "check",
673 Kind::Clippy => "clippy",
674 Kind::Fix => "fix",
675 Kind::Format => "fmt",
676 Kind::Test => "test",
677 Kind::Miri => "miri",
678 Kind::MiriSetup => panic!("`as_str` is not supported for `Kind::MiriSetup`."),
679 Kind::MiriTest => panic!("`as_str` is not supported for `Kind::MiriTest`."),
680 Kind::Bench => "bench",
681 Kind::Doc => "doc",
682 Kind::Clean => "clean",
683 Kind::Dist => "dist",
684 Kind::Install => "install",
685 Kind::Run => "run",
686 Kind::Setup => "setup",
687 Kind::Vendor => "vendor",
688 Kind::Perf => "perf",
689 }
690 }
691
692 pub fn description(&self) -> String {
693 match self {
694 Kind::Test => "Testing",
695 Kind::Bench => "Benchmarking",
696 Kind::Doc => "Documenting",
697 Kind::Run => "Running",
698 Kind::Clippy => "Linting",
699 Kind::Perf => "Profiling & benchmarking",
700 _ => {
701 let title_letter = self.as_str()[0..1].to_ascii_uppercase();
702 return format!("{title_letter}{}ing", &self.as_str()[1..]);
703 }
704 }
705 .to_owned()
706 }
707}
708
709#[derive(Debug, Clone, Hash, PartialEq, Eq)]
710struct Libdir {
711 compiler: Compiler,
712 target: TargetSelection,
713}
714
715impl Step for Libdir {
716 type Output = PathBuf;
717
718 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
719 run.never()
720 }
721
722 fn run(self, builder: &Builder<'_>) -> PathBuf {
723 let relative_sysroot_libdir = builder.sysroot_libdir_relative(self.compiler);
724 let sysroot = builder.sysroot(self.compiler).join(relative_sysroot_libdir).join("rustlib");
725
726 if !builder.config.dry_run() {
727 if !builder.download_rustc() {
730 let sysroot_target_libdir = sysroot.join(self.target).join("lib");
731 builder.do_if_verbose(|| {
732 eprintln!(
733 "Removing sysroot {} to avoid caching bugs",
734 sysroot_target_libdir.display()
735 )
736 });
737 let _ = fs::remove_dir_all(&sysroot_target_libdir);
738 t!(fs::create_dir_all(&sysroot_target_libdir));
739 }
740
741 if self.compiler.stage == 0 {
742 dist::maybe_install_llvm_target(
746 builder,
747 self.compiler.host,
748 &builder.sysroot(self.compiler),
749 );
750 }
751 }
752
753 sysroot
754 }
755}
756
757#[cfg(feature = "tracing")]
758pub const STEP_SPAN_TARGET: &str = "STEP";
759
760impl<'a> Builder<'a> {
761 fn get_step_descriptions(kind: Kind) -> Vec<StepDescription> {
762 macro_rules! describe {
763 ($($rule:ty),+ $(,)?) => {{
764 vec![$(StepDescription::from::<$rule>(kind)),+]
765 }};
766 }
767 match kind {
768 Kind::Build => describe!(
769 compile::Std,
770 compile::Rustc,
771 compile::Assemble,
772 compile::CraneliftCodegenBackend,
773 compile::GccCodegenBackend,
774 compile::StartupObjects,
775 tool::BuildManifest,
776 tool::Rustbook,
777 tool::ErrorIndex,
778 tool::UnstableBookGen,
779 tool::Tidy,
780 tool::Linkchecker,
781 tool::CargoTest,
782 tool::Compiletest,
783 tool::RemoteTestServer,
784 tool::RemoteTestClient,
785 tool::RustInstaller,
786 tool::FeaturesStatusDump,
787 tool::Cargo,
788 tool::RustAnalyzer,
789 tool::RustAnalyzerProcMacroSrv,
790 tool::Rustdoc,
791 tool::Clippy,
792 tool::CargoClippy,
793 llvm::Llvm,
794 gcc::Gcc,
795 llvm::Sanitizers,
796 tool::Rustfmt,
797 tool::Cargofmt,
798 tool::Miri,
799 tool::CargoMiri,
800 llvm::Lld,
801 llvm::Enzyme,
802 llvm::CrtBeginEnd,
803 tool::RustdocGUITest,
804 tool::OptimizedDist,
805 tool::CoverageDump,
806 tool::LlvmBitcodeLinker,
807 tool::RustcPerf,
808 tool::WasmComponentLd,
809 tool::LldWrapper
810 ),
811 Kind::Clippy => describe!(
812 clippy::Std,
813 clippy::Rustc,
814 clippy::Bootstrap,
815 clippy::BuildHelper,
816 clippy::BuildManifest,
817 clippy::CargoMiri,
818 clippy::Clippy,
819 clippy::CodegenGcc,
820 clippy::CollectLicenseMetadata,
821 clippy::Compiletest,
822 clippy::CoverageDump,
823 clippy::Jsondocck,
824 clippy::Jsondoclint,
825 clippy::LintDocs,
826 clippy::LlvmBitcodeLinker,
827 clippy::Miri,
828 clippy::MiroptTestTools,
829 clippy::OptDist,
830 clippy::RemoteTestClient,
831 clippy::RemoteTestServer,
832 clippy::RustAnalyzer,
833 clippy::Rustdoc,
834 clippy::Rustfmt,
835 clippy::RustInstaller,
836 clippy::TestFloatParse,
837 clippy::Tidy,
838 clippy::CI,
839 ),
840 Kind::Check | Kind::Fix => describe!(
841 check::Rustc,
842 check::Rustdoc,
843 check::CraneliftCodegenBackend,
844 check::GccCodegenBackend,
845 check::Clippy,
846 check::Miri,
847 check::CargoMiri,
848 check::MiroptTestTools,
849 check::Rustfmt,
850 check::RustAnalyzer,
851 check::TestFloatParse,
852 check::Bootstrap,
853 check::RunMakeSupport,
854 check::Compiletest,
855 check::RustdocGuiTest,
856 check::FeaturesStatusDump,
857 check::CoverageDump,
858 check::Linkchecker,
859 check::BumpStage0,
860 check::Tidy,
861 check::Std,
868 ),
869 Kind::Test => describe!(
870 crate::core::build_steps::toolstate::ToolStateCheck,
871 test::Tidy,
872 test::BootstrapPy,
873 test::Bootstrap,
874 test::Ui,
875 test::Crashes,
876 test::Coverage,
877 test::MirOpt,
878 test::CodegenLlvm,
879 test::CodegenUnits,
880 test::AssemblyLlvm,
881 test::Incremental,
882 test::Debuginfo,
883 test::UiFullDeps,
884 test::RustdocHtml,
885 test::CoverageRunRustdoc,
886 test::Pretty,
887 test::CodegenCranelift,
888 test::CodegenGCC,
889 test::Crate,
890 test::CrateLibrustc,
891 test::CrateRustdoc,
892 test::CrateRustdocJsonTypes,
893 test::CrateBootstrap,
894 test::RemoteTestClientTests,
895 test::Linkcheck,
896 test::TierCheck,
897 test::Cargotest,
898 test::Cargo,
899 test::RustAnalyzer,
900 test::ErrorIndex,
901 test::Distcheck,
902 test::Nomicon,
903 test::Reference,
904 test::RustdocBook,
905 test::RustByExample,
906 test::TheBook,
907 test::UnstableBook,
908 test::RustcBook,
909 test::LintDocs,
910 test::EmbeddedBook,
911 test::EditionGuide,
912 test::Rustfmt,
913 test::Miri,
914 test::CargoMiri,
915 test::Clippy,
916 test::CompiletestTest,
917 test::StdarchVerify,
918 test::IntrinsicTest,
919 test::CrateRunMakeSupport,
920 test::CrateBuildHelper,
921 test::RustdocJSStd,
922 test::RustdocJSNotStd,
923 test::RustdocGUI,
924 test::RustdocTheme,
925 test::RustdocUi,
926 test::RustdocJson,
927 test::HtmlCheck,
928 test::RustInstaller,
929 test::TestFloatParse,
930 test::CollectLicenseMetadata,
931 test::RunMake,
932 test::RunMakeCargo,
933 test::BuildStd,
934 ),
935 Kind::Miri => describe!(test::Crate),
936 Kind::Bench => describe!(test::Crate, test::CrateLibrustc, test::CrateRustdoc),
937 Kind::Doc => describe!(
938 doc::UnstableBook,
939 doc::UnstableBookGen,
940 doc::TheBook,
941 doc::Standalone,
942 doc::Std,
943 doc::Rustc,
944 doc::Rustdoc,
945 doc::Rustfmt,
946 doc::ErrorIndex,
947 doc::Nomicon,
948 doc::Reference,
949 doc::RustdocBook,
950 doc::RustByExample,
951 doc::RustcBook,
952 doc::Cargo,
953 doc::CargoBook,
954 doc::Clippy,
955 doc::ClippyBook,
956 doc::Miri,
957 doc::EmbeddedBook,
958 doc::EditionGuide,
959 doc::StyleGuide,
960 doc::Tidy,
961 doc::Bootstrap,
962 doc::Releases,
963 doc::RunMakeSupport,
964 doc::BuildHelper,
965 doc::Compiletest,
966 ),
967 Kind::Dist => describe!(
968 dist::Docs,
969 dist::RustcDocs,
970 dist::JsonDocs,
971 dist::Mingw,
972 dist::Rustc,
973 dist::CraneliftCodegenBackend,
974 dist::GccCodegenBackend,
975 dist::Std,
976 dist::RustcDev,
977 dist::Analysis,
978 dist::Src,
979 dist::Cargo,
980 dist::RustAnalyzer,
981 dist::Rustfmt,
982 dist::Clippy,
983 dist::Miri,
984 dist::LlvmTools,
985 dist::LlvmBitcodeLinker,
986 dist::RustDev,
987 dist::Enzyme,
988 dist::Bootstrap,
989 dist::Extended,
990 dist::PlainSourceTarball,
995 dist::PlainSourceTarballGpl,
996 dist::BuildManifest,
997 dist::ReproducibleArtifacts,
998 dist::GccDev,
999 dist::Gcc
1000 ),
1001 Kind::Install => describe!(
1002 install::Docs,
1003 install::Std,
1004 install::Rustc,
1009 install::RustcDev,
1010 install::Cargo,
1011 install::RustAnalyzer,
1012 install::Rustfmt,
1013 install::Clippy,
1014 install::Miri,
1015 install::LlvmTools,
1016 install::Src,
1017 install::RustcCodegenCranelift,
1018 install::LlvmBitcodeLinker
1019 ),
1020 Kind::Run => describe!(
1021 run::BuildManifest,
1022 run::BumpStage0,
1023 run::ReplaceVersionPlaceholder,
1024 run::Miri,
1025 run::CollectLicenseMetadata,
1026 run::GenerateCopyright,
1027 run::GenerateWindowsSys,
1028 run::GenerateCompletions,
1029 run::UnicodeTableGenerator,
1030 run::FeaturesStatusDump,
1031 run::CyclicStep,
1032 run::CoverageDump,
1033 run::Rustfmt,
1034 run::GenerateHelp,
1035 ),
1036 Kind::Setup => {
1037 describe!(setup::Profile, setup::Hook, setup::Link, setup::Editor)
1038 }
1039 Kind::Clean => describe!(clean::CleanAll, clean::Rustc, clean::Std),
1040 Kind::Vendor => describe!(vendor::Vendor),
1041 Kind::Format | Kind::Perf => vec![],
1043 Kind::MiriTest | Kind::MiriSetup => unreachable!(),
1044 }
1045 }
1046
1047 pub fn get_help(build: &Build, kind: Kind) -> Option<String> {
1048 let step_descriptions = Builder::get_step_descriptions(kind);
1049 if step_descriptions.is_empty() {
1050 return None;
1051 }
1052
1053 let builder = Self::new_internal(build, kind, vec![]);
1054 let builder = &builder;
1055 let mut should_run = ShouldRun::new(builder, Kind::Build);
1058 for desc in step_descriptions {
1059 should_run.kind = desc.kind;
1060 should_run = (desc.should_run)(should_run);
1061 }
1062 let mut help = String::from("Available paths:\n");
1063 let mut add_path = |path: &Path| {
1064 t!(write!(help, " ./x.py {} {}\n", kind.as_str(), path.display()));
1065 };
1066 for pathset in should_run.paths {
1067 match pathset {
1068 PathSet::Set(set) => {
1069 for path in set {
1070 add_path(&path.path);
1071 }
1072 }
1073 PathSet::Suite(path) => {
1074 add_path(&path.path.join("..."));
1075 }
1076 }
1077 }
1078 Some(help)
1079 }
1080
1081 fn new_internal(build: &Build, kind: Kind, paths: Vec<PathBuf>) -> Builder<'_> {
1082 Builder {
1083 build,
1084 top_stage: build.config.stage,
1085 kind,
1086 cache: Cache::new(),
1087 stack: RefCell::new(Vec::new()),
1088 time_spent_on_dependencies: Cell::new(Duration::new(0, 0)),
1089 paths,
1090 submodule_paths_cache: Default::default(),
1091 log_cli_step_for_tests: None,
1092 }
1093 }
1094
1095 pub fn new(build: &Build) -> Builder<'_> {
1096 let paths = &build.config.paths;
1097 let (kind, paths) = match build.config.cmd {
1098 Subcommand::Build { .. } => (Kind::Build, &paths[..]),
1099 Subcommand::Check { .. } => (Kind::Check, &paths[..]),
1100 Subcommand::Clippy { .. } => (Kind::Clippy, &paths[..]),
1101 Subcommand::Fix => (Kind::Fix, &paths[..]),
1102 Subcommand::Doc { .. } => (Kind::Doc, &paths[..]),
1103 Subcommand::Test { .. } => (Kind::Test, &paths[..]),
1104 Subcommand::Miri { .. } => (Kind::Miri, &paths[..]),
1105 Subcommand::Bench { .. } => (Kind::Bench, &paths[..]),
1106 Subcommand::Dist => (Kind::Dist, &paths[..]),
1107 Subcommand::Install => (Kind::Install, &paths[..]),
1108 Subcommand::Run { .. } => (Kind::Run, &paths[..]),
1109 Subcommand::Clean { .. } => (Kind::Clean, &paths[..]),
1110 Subcommand::Format { .. } => (Kind::Format, &[][..]),
1111 Subcommand::Setup { profile: ref path } => (
1112 Kind::Setup,
1113 path.as_ref().map_or([].as_slice(), |path| std::slice::from_ref(path)),
1114 ),
1115 Subcommand::Vendor { .. } => (Kind::Vendor, &paths[..]),
1116 Subcommand::Perf { .. } => (Kind::Perf, &paths[..]),
1117 };
1118
1119 StepStack::with_current(|stack| stack.clear());
1120 Self::new_internal(build, kind, paths.to_owned())
1121 }
1122
1123 pub fn execute_cli(&self) {
1124 self.run_step_descriptions(&Builder::get_step_descriptions(self.kind), &self.paths);
1125 }
1126
1127 pub fn run_default_doc_steps(&self) {
1129 self.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), &[]);
1130 }
1131
1132 pub fn doc_rust_lang_org_channel(&self) -> String {
1133 let channel = match &*self.config.channel {
1134 "stable" => &self.version,
1135 "beta" => "beta",
1136 "nightly" | "dev" => "nightly",
1137 _ => "stable",
1139 };
1140
1141 format!("https://doc.rust-lang.org/{channel}")
1142 }
1143
1144 fn run_step_descriptions(&self, v: &[StepDescription], paths: &[PathBuf]) {
1145 cli_paths::match_paths_to_steps_and_run(self, v, paths);
1146 }
1147
1148 pub fn link_std_into_rustc_driver(&self, target: TargetSelection) -> bool {
1151 !target.triple.ends_with("-windows-gnu")
1152 }
1153
1154 #[track_caller]
1159 #[cfg_attr(
1160 feature = "tracing",
1161 instrument(
1162 level = "trace",
1163 name = "Builder::compiler",
1164 target = "COMPILER",
1165 skip_all,
1166 fields(
1167 stage = stage,
1168 host = ?host,
1169 ),
1170 ),
1171 )]
1172 pub fn compiler(&self, stage: u32, host: TargetSelection) -> Compiler {
1173 self.ensure(compile::Assemble { target_compiler: Compiler::new(stage, host) })
1174 }
1175
1176 #[track_caller]
1193 pub fn compiler_for_std(&self, stage: u32) -> Compiler {
1194 if compile::Std::should_be_uplifted_from_stage_1(self, stage) {
1195 self.compiler(1, self.host_target)
1196 } else {
1197 self.compiler(stage, self.host_target)
1198 }
1199 }
1200
1201 #[track_caller]
1213 #[cfg_attr(
1214 feature = "tracing",
1215 instrument(
1216 level = "trace",
1217 name = "Builder::compiler_for",
1218 target = "COMPILER_FOR",
1219 skip_all,
1220 fields(
1221 stage = stage,
1222 host = ?host,
1223 target = ?target,
1224 ),
1225 ),
1226 )]
1227 pub fn compiler_for(
1230 &self,
1231 stage: u32,
1232 host: TargetSelection,
1233 target: TargetSelection,
1234 ) -> Compiler {
1235 let mut resolved_compiler = if self.build.force_use_stage2(stage) {
1236 trace!(target: "COMPILER_FOR", ?stage, "force_use_stage2");
1237 self.compiler(2, self.config.host_target)
1238 } else if self.build.force_use_stage1(stage, target) {
1239 trace!(target: "COMPILER_FOR", ?stage, "force_use_stage1");
1240 self.compiler(1, self.config.host_target)
1241 } else {
1242 trace!(target: "COMPILER_FOR", ?stage, ?host, "no force, fallback to `compiler()`");
1243 self.compiler(stage, host)
1244 };
1245
1246 if stage != resolved_compiler.stage {
1247 resolved_compiler.forced_compiler(true);
1248 }
1249
1250 trace!(target: "COMPILER_FOR", ?resolved_compiler);
1251 resolved_compiler
1252 }
1253
1254 #[track_caller]
1261 #[cfg_attr(
1262 feature = "tracing",
1263 instrument(
1264 level = "trace",
1265 name = "Builder::std",
1266 target = "STD",
1267 skip_all,
1268 fields(
1269 compiler = ?compiler,
1270 target = ?target,
1271 ),
1272 ),
1273 )]
1274 pub fn std(&self, compiler: Compiler, target: TargetSelection) -> Option<BuildStamp> {
1275 if compiler.stage == 0 {
1285 if target != compiler.host {
1286 if self.local_rebuild {
1287 self.ensure(Std::new(compiler, target))
1288 } else {
1289 panic!(
1290 r"It is not possible to build the standard library for `{target}` using the stage0 compiler.
1291You have to build a stage1 compiler for `{}` first, and then use it to build a standard library for `{target}`.
1292Alternatively, you can set `build.local-rebuild=true` and use a stage0 compiler built from in-tree sources.
1293",
1294 compiler.host
1295 )
1296 }
1297 } else {
1298 self.ensure(StdLink::from_std(Std::new(compiler, target), compiler));
1300 None
1301 }
1302 } else {
1303 self.ensure(Std::new(compiler, target))
1306 }
1307 }
1308
1309 #[track_caller]
1310 pub fn sysroot(&self, compiler: Compiler) -> PathBuf {
1311 self.ensure(compile::Sysroot::new(compiler))
1312 }
1313
1314 #[track_caller]
1316 pub fn sysroot_target_bindir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf {
1317 self.ensure(Libdir { compiler, target }).join(target).join("bin")
1318 }
1319
1320 #[track_caller]
1323 pub fn sysroot_target_libdir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf {
1324 self.ensure(Libdir { compiler, target }).join(target).join("lib")
1325 }
1326
1327 pub fn sysroot_codegen_backends(&self, compiler: Compiler) -> PathBuf {
1328 self.sysroot_target_libdir(compiler, compiler.host).with_file_name("codegen-backends")
1329 }
1330
1331 pub fn rustc_libdir(&self, compiler: Compiler) -> PathBuf {
1337 if compiler.is_snapshot(self) {
1338 self.rustc_snapshot_libdir()
1339 } else {
1340 match self.config.libdir_relative() {
1341 Some(relative_libdir) if compiler.stage >= 1 => {
1342 self.sysroot(compiler).join(relative_libdir)
1343 }
1344 _ => self.sysroot(compiler).join(libdir(compiler.host)),
1345 }
1346 }
1347 }
1348
1349 pub fn libdir_relative(&self, compiler: Compiler) -> &Path {
1355 if compiler.is_snapshot(self) {
1356 libdir(self.config.host_target).as_ref()
1357 } else {
1358 match self.config.libdir_relative() {
1359 Some(relative_libdir) if compiler.stage >= 1 => relative_libdir,
1360 _ => libdir(compiler.host).as_ref(),
1361 }
1362 }
1363 }
1364
1365 pub fn sysroot_libdir_relative(&self, compiler: Compiler) -> &Path {
1370 match self.config.libdir_relative() {
1371 Some(relative_libdir) if compiler.stage >= 1 => relative_libdir,
1372 _ if compiler.stage == 0 => &self.build.initial_relative_libdir,
1373 _ => Path::new("lib"),
1374 }
1375 }
1376
1377 pub fn rustc_lib_paths(&self, compiler: Compiler) -> Vec<PathBuf> {
1378 let mut dylib_dirs = vec![self.rustc_libdir(compiler)];
1379
1380 if self.config.llvm_from_ci {
1382 let ci_llvm_lib = self.out.join(compiler.host).join("ci-llvm").join("lib");
1383 dylib_dirs.push(ci_llvm_lib);
1384 }
1385
1386 dylib_dirs
1387 }
1388
1389 pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut BootstrapCommand) {
1392 if cfg!(any(windows, target_os = "cygwin")) {
1396 return;
1397 }
1398
1399 add_dylib_path(self.rustc_lib_paths(compiler), cmd);
1400 }
1401
1402 pub fn rustc(&self, compiler: Compiler) -> PathBuf {
1404 if compiler.is_snapshot(self) {
1405 self.initial_rustc.clone()
1406 } else {
1407 self.sysroot(compiler).join("bin").join(exe("rustc", compiler.host))
1408 }
1409 }
1410
1411 pub fn rustc_cmd(&self, compiler: Compiler) -> BootstrapCommand {
1414 let mut cmd = command(self.rustc(compiler));
1415 self.add_rustc_lib_path(compiler, &mut cmd);
1416 cmd
1417 }
1418
1419 fn codegen_backends(&self, compiler: Compiler) -> impl Iterator<Item = PathBuf> {
1421 fs::read_dir(self.sysroot_codegen_backends(compiler))
1422 .into_iter()
1423 .flatten()
1424 .filter_map(Result::ok)
1425 .map(|entry| entry.path())
1426 }
1427
1428 #[track_caller]
1432 pub fn rustdoc_for_compiler(&self, target_compiler: Compiler) -> PathBuf {
1433 self.ensure(tool::Rustdoc { target_compiler })
1434 }
1435
1436 pub fn cargo_miri_cmd(&self, run_compiler: Compiler) -> BootstrapCommand {
1437 assert!(run_compiler.stage > 0, "miri can not be invoked at stage 0");
1438
1439 let compilers =
1440 RustcPrivateCompilers::new(self, run_compiler.stage, self.build.host_target);
1441 assert_eq!(run_compiler, compilers.target_compiler());
1442
1443 let miri = self.ensure(tool::Miri::from_compilers(compilers));
1445 let cargo_miri = self.ensure(tool::CargoMiri::from_compilers(compilers));
1446 let mut cmd = command(cargo_miri.tool_path);
1448 cmd.env("MIRI", &miri.tool_path);
1449 cmd.env("CARGO", &self.initial_cargo);
1450 add_dylib_path(self.rustc_lib_paths(run_compiler), &mut cmd);
1459 cmd
1460 }
1461
1462 pub fn cargo_clippy_cmd(&self, build_compiler: Compiler) -> BootstrapCommand {
1465 if build_compiler.stage == 0 {
1466 let cargo_clippy = self
1467 .config
1468 .initial_cargo_clippy
1469 .clone()
1470 .unwrap_or_else(|| self.build.config.download_clippy());
1471
1472 let mut cmd = command(cargo_clippy);
1473 cmd.env("CARGO", &self.initial_cargo);
1474 return cmd;
1475 }
1476
1477 let compilers = RustcPrivateCompilers::from_target_compiler(self, build_compiler);
1481
1482 let _ = self.ensure(tool::Clippy::from_compilers(compilers));
1483 let cargo_clippy = self.ensure(tool::CargoClippy::from_compilers(compilers));
1484 let mut dylib_path = helpers::dylib_path();
1485 dylib_path.insert(0, self.sysroot(build_compiler).join("lib"));
1486
1487 let mut cmd = command(cargo_clippy.tool_path);
1488 cmd.env(helpers::dylib_path_var(), env::join_paths(&dylib_path).unwrap());
1489 cmd.env("CARGO", &self.initial_cargo);
1490 cmd
1491 }
1492
1493 pub fn rustdoc_cmd(&self, compiler: Compiler) -> BootstrapCommand {
1494 let mut cmd = command(self.bootstrap_out.join("rustdoc"));
1495 cmd.env("RUSTC_STAGE", compiler.stage.to_string())
1496 .env("RUSTC_SYSROOT", self.sysroot(compiler))
1497 .env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler))
1500 .env("CFG_RELEASE_CHANNEL", &self.config.channel)
1501 .env("RUSTDOC_REAL", self.rustdoc_for_compiler(compiler))
1502 .env("RUSTC_BOOTSTRAP", "1");
1503
1504 cmd.arg("-Wrustdoc::invalid_codeblock_attributes");
1505
1506 if self.config.deny_warnings {
1507 cmd.arg("-Dwarnings");
1508 }
1509 cmd.arg("-Znormalize-docs");
1510 cmd.args(linker_args(self, compiler.host, LldThreads::Yes));
1511 cmd
1512 }
1513
1514 pub fn llvm_config(&self, target: TargetSelection) -> Option<PathBuf> {
1523 if self.config.llvm_enabled(target) && self.kind != Kind::Check && !self.config.dry_run() {
1524 let llvm::LlvmResult { host_llvm_config, .. } = self.ensure(llvm::Llvm { target });
1525 if host_llvm_config.is_file() {
1526 return Some(host_llvm_config);
1527 }
1528 }
1529 None
1530 }
1531
1532 pub fn require_and_update_all_submodules(&self) {
1535 for submodule in self.submodule_paths() {
1536 self.require_submodule(submodule, None);
1537 }
1538 }
1539
1540 pub fn submodule_paths(&self) -> &[String] {
1542 self.submodule_paths_cache.get_or_init(|| build_helper::util::parse_gitmodules(&self.src))
1543 }
1544
1545 #[track_caller]
1549 pub fn ensure<S: Step>(&'a self, step: S) -> S::Output {
1550 {
1551 let mut stack = self.stack.borrow_mut();
1552 for stack_step in stack.iter() {
1553 if stack_step.downcast_ref::<S>().is_none_or(|stack_step| *stack_step != step) {
1555 continue;
1556 }
1557 let mut out = String::new();
1558 out += &format!("\n\nCycle in build detected when adding {step:?}\n");
1559 for el in stack.iter().rev() {
1560 out += &format!("\t{el:?}\n");
1561 }
1562 panic!("{}", out);
1563 }
1564 if let Some(out) = self.cache.get(&step) {
1565 #[cfg(feature = "tracing")]
1566 {
1567 if let Some(parent) = stack.last() {
1568 let mut graph = self.build.step_graph.borrow_mut();
1569 graph.register_cached_step(&step, parent, self.config.dry_run());
1570 }
1571 }
1572 return out;
1573 }
1574
1575 #[cfg(feature = "tracing")]
1576 {
1577 let parent = stack.last();
1578 let mut graph = self.build.step_graph.borrow_mut();
1579 graph.register_step_execution(&step, parent, self.config.dry_run());
1580 }
1581
1582 let location = format_location(*std::panic::Location::caller());
1585 StepStack::with_current(|stack| {
1586 stack.push(StepRecord { info: pretty_print_step(&step), location });
1587 });
1588 stack.push(Box::new(step.clone()));
1589 }
1590
1591 #[cfg(feature = "build-metrics")]
1592 self.metrics.enter_step(&step, self);
1593
1594 if self.config.print_step_timings && !self.config.dry_run() {
1595 println!("[TIMING:start] {}", pretty_print_step(&step));
1596 }
1597
1598 let (out, dur) = {
1599 let start = Instant::now();
1600 let zero = Duration::new(0, 0);
1601 let parent = self.time_spent_on_dependencies.replace(zero);
1602
1603 #[cfg(feature = "tracing")]
1604 let _span = {
1605 let span = tracing::info_span!(
1607 target: STEP_SPAN_TARGET,
1608 "step",
1611 step_name = pretty_step_name::<S>(),
1612 args = step_debug_args(&step),
1613 location = format_location(*std::panic::Location::caller())
1614 );
1615 span.entered()
1616 };
1617
1618 let out = step.clone().run(self);
1619 let dur = start.elapsed();
1620 let deps = self.time_spent_on_dependencies.replace(parent + dur);
1621 (out, dur.saturating_sub(deps))
1622 };
1623
1624 if self.config.print_step_timings && !self.config.dry_run() {
1625 println!(
1626 "[TIMING:end] {} -- {}.{:03}",
1627 pretty_print_step(&step),
1628 dur.as_secs(),
1629 dur.subsec_millis()
1630 );
1631 }
1632
1633 #[cfg(feature = "build-metrics")]
1634 self.metrics.exit_step(self);
1635
1636 {
1637 let mut stack = self.stack.borrow_mut();
1638 let cur_step = stack.pop().expect("step stack empty");
1639 assert_eq!(cur_step.downcast_ref(), Some(&step));
1640
1641 StepStack::with_current(|stack| {
1642 stack.pop();
1643 });
1644 }
1645 self.cache.put(step, out.clone());
1646 out
1647 }
1648
1649 pub(crate) fn ensure_if_default<T, S: Step<Output = T>>(
1653 &'a self,
1654 step: S,
1655 kind: Kind,
1656 ) -> Option<S::Output> {
1657 let desc = StepDescription::from::<S>(kind);
1658 let should_run = (desc.should_run)(ShouldRun::new(self, desc.kind));
1659
1660 for pathset in &should_run.paths {
1662 if desc.is_excluded(self, pathset) {
1663 return None;
1664 }
1665 }
1666
1667 if (desc.is_default_step_fn)(self) { Some(self.ensure(step)) } else { None }
1669 }
1670
1671 pub(crate) fn was_invoked_explicitly<S: Step>(&'a self, kind: Kind) -> bool {
1673 let desc = StepDescription::from::<S>(kind);
1674 let should_run = (desc.should_run)(ShouldRun::new(self, desc.kind));
1675
1676 for path in &self.paths {
1677 if should_run.paths.iter().any(|s| s.has(path, desc.kind))
1678 && !desc.is_excluded(
1679 self,
1680 &PathSet::Suite(TaskPath { path: path.clone(), kind: Some(desc.kind) }),
1681 )
1682 {
1683 return true;
1684 }
1685 }
1686
1687 false
1688 }
1689
1690 pub(crate) fn maybe_open_in_browser<S: Step>(&self, path: impl AsRef<Path>) {
1691 if self.was_invoked_explicitly::<S>(Kind::Doc) {
1692 self.open_in_browser(path);
1693 } else {
1694 self.info(&format!("Doc path: {}", path.as_ref().display()));
1695 }
1696 }
1697
1698 pub(crate) fn open_in_browser(&self, path: impl AsRef<Path>) {
1699 let path = path.as_ref();
1700
1701 if self.config.dry_run() || !self.config.cmd.open() {
1702 self.info(&format!("Doc path: {}", path.display()));
1703 return;
1704 }
1705
1706 self.info(&format!("Opening doc {}", path.display()));
1707 if let Err(err) = opener::open(path) {
1708 self.info(&format!("{err}\n"));
1709 }
1710 }
1711
1712 pub fn exec_ctx(&self) -> &ExecutionContext {
1713 &self.config.exec_ctx
1714 }
1715}
1716
1717pub fn pretty_step_name<S: Step>() -> String {
1719 let path = type_name::<S>().rsplit("::").take(2).collect::<Vec<_>>();
1721 path.into_iter().rev().collect::<Vec<_>>().join("::")
1722}
1723
1724fn step_debug_args<S: Step>(step: &S) -> String {
1726 let step_dbg_repr = format!("{step:?}");
1727
1728 match (step_dbg_repr.find('{'), step_dbg_repr.rfind('}')) {
1730 (Some(brace_start), Some(brace_end)) => {
1731 step_dbg_repr[brace_start + 1..brace_end - 1].trim().to_string()
1732 }
1733 _ => String::new(),
1734 }
1735}
1736
1737fn pretty_print_step<S: Step>(step: &S) -> String {
1738 format!("{} {{ {} }}", pretty_step_name::<S>(), step_debug_args(step))
1739}
1740
1741impl<'a> AsRef<ExecutionContext> for Builder<'a> {
1742 fn as_ref(&self) -> &ExecutionContext {
1743 self.exec_ctx()
1744 }
1745}