55
66use std:: path:: PathBuf ;
77
8+ use build_helper:: exit;
89use clap_complete:: { Generator , shells} ;
910
1011use crate :: core:: build_steps:: dist:: distdir;
1112use crate :: core:: build_steps:: test;
1213use crate :: core:: build_steps:: tool:: { self , RustcPrivateCompilers , SourceType , Tool } ;
1314use crate :: core:: build_steps:: vendor:: { Vendor , default_paths_to_vendor} ;
14- use crate :: core:: builder:: { Builder , Kind , RunConfig , ShouldRun , Step } ;
15+ use crate :: core:: builder:: { Builder , Kind , RunConfig , ShouldRun , Step , StepMetadata } ;
1516use crate :: core:: config:: TargetSelection ;
1617use crate :: core:: config:: flags:: get_completion;
1718use crate :: utils:: exec:: command;
@@ -100,8 +101,17 @@ impl Step for ReplaceVersionPlaceholder {
100101 }
101102}
102103
104+ /// Invoke the Miri tool on a specified file.
105+ ///
106+ /// Note that Miri always executed on the host, as it is an interpreter.
107+ /// That means that `x run miri --target FOO` will build miri for the host,
108+ /// prepare a miri sysroot for the target `FOO` and then execute miri with
109+ /// the target `FOO`.
103110#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
104111pub struct Miri {
112+ /// The build compiler that will build miri and the target compiler to which miri links.
113+ compilers : RustcPrivateCompilers ,
114+ /// The target which will miri interpret.
105115 target : TargetSelection ,
106116}
107117
@@ -113,14 +123,9 @@ impl Step for Miri {
113123 }
114124
115125 fn make_run ( run : RunConfig < ' _ > ) {
116- run. builder . ensure ( Miri { target : run. target } ) ;
117- }
118-
119- fn run ( self , builder : & Builder < ' _ > ) {
120- let host = builder. build . host_target ;
121- let target = self . target ;
126+ let builder = run. builder ;
122127
123- // `x run` uses stage 0 by default but miri does not work well with stage 0.
128+ // `x run` uses stage 0 by default, but miri does not work well with stage 0.
124129 // Change the stage to 1 if it's not set explicitly.
125130 let stage = if builder. config . is_explicit_stage ( ) || builder. top_stage >= 1 {
126131 builder. top_stage
@@ -129,14 +134,22 @@ impl Step for Miri {
129134 } ;
130135
131136 if stage == 0 {
132- eprintln ! ( "miri cannot be run at stage 0" ) ;
133- std :: process :: exit ( 1 ) ;
137+ eprintln ! ( "ERROR: miri cannot be run at stage 0" ) ;
138+ exit ! ( 1 ) ;
134139 }
135140
136- // This compiler runs on the host, we'll just use it for the target.
137- let compilers = RustcPrivateCompilers :: new ( builder, stage, target) ;
138- let miri_build = builder. ensure ( tool:: Miri :: from_compilers ( compilers) ) ;
139- let host_compiler = miri_build. build_compiler ;
141+ // Miri always runs on the host, because it can interpret code for any target
142+ let compilers = RustcPrivateCompilers :: new ( builder, stage, builder. host_target ) ;
143+
144+ run. builder . ensure ( Miri { compilers, target : run. target } ) ;
145+ }
146+
147+ fn run ( self , builder : & Builder < ' _ > ) {
148+ let host = builder. build . host_target ;
149+ let compilers = self . compilers ;
150+ let target = self . target ;
151+
152+ builder. ensure ( tool:: Miri :: from_compilers ( compilers) ) ;
140153
141154 // Get a target sysroot for Miri.
142155 let miri_sysroot =
@@ -147,7 +160,7 @@ impl Step for Miri {
147160 // add_rustc_lib_path does not add the path that contains librustc_driver-<...>.so.
148161 let mut miri = tool:: prepare_tool_cargo (
149162 builder,
150- host_compiler ,
163+ compilers . build_compiler ( ) ,
151164 Mode :: ToolRustc ,
152165 host,
153166 Kind :: Run ,
@@ -167,6 +180,10 @@ impl Step for Miri {
167180
168181 miri. into_cmd ( ) . run ( builder) ;
169182 }
183+
184+ fn metadata ( & self ) -> Option < StepMetadata > {
185+ Some ( StepMetadata :: run ( "miri" , self . target ) . built_by ( self . compilers . build_compiler ( ) ) )
186+ }
170187}
171188
172189#[ derive( Debug , Clone , Hash , PartialEq , Eq ) ]
0 commit comments