22// instrumented stage1 rustc and merging the resulting profraw files eagerly.
33//
44// Usage:
5- // coverage-tool --config <compiletest-args> [--suite tests/ui/generics] [--out coverage/]
5+ // coverage-tool --out coverage/ [compiletest args...]
6+ //
7+ // All flags except --out are forwarded to compiletest's config parser,
8+ // so this tool is intended to be invoked by bootstrap the same way
9+ // compiletest is, with --out added.
610
711use std:: path:: PathBuf ;
812use std:: process:: Command ;
913use std:: sync:: Arc ;
1014use std:: { env, fs} ;
1115
1216use compiletest:: { collect_and_make_tests, parse_config} ;
13- use compiletest:: common:: Config ;
1417
1518fn main ( ) {
1619 let args: Vec < String > = env:: args ( ) . collect ( ) ;
1720
18- // Minimal CLI: --suite <dir> --out <dir>
19- // Everything else is passed through to compiletest's config parser.
20- let suite = arg_value ( & args, "--suite" )
21- . unwrap_or_else ( || "tests/ui" . to_string ( ) ) ;
21+ // Extract tool-specific flags; everything else goes to parse_config.
2222 let out_dir = arg_value ( & args, "--out" )
2323 . unwrap_or_else ( || "coverage" . to_string ( ) ) ;
2424
25+ // Read rustc-path and sysroot-base from args so we can invoke rustc
26+ // directly without touching private Config fields.
27+ let rustc_path = arg_value ( & args, "--rustc-path" )
28+ . unwrap_or_else ( find_stage1_rustc) ;
29+ let sysroot = arg_value ( & args, "--sysroot-base" )
30+ . unwrap_or_else ( find_stage1_sysroot) ;
31+
2532 fs:: create_dir_all ( & out_dir) . expect ( "failed to create output dir" ) ;
2633
27- // Build a minimal compiletest Config pointing at the test suite.
28- // In practice this would be constructed from bootstrap's config,
29- // but for now we parse the same flags compiletest accepts.
30- let config = build_config ( & suite) ;
34+ // Strip --out <val> from args and pass the rest to parse_config.
35+ let config_args = strip_flag ( args, "--out" ) ;
36+ let config = parse_config ( config_args) ;
3137 let config = Arc :: new ( config) ;
3238
3339 // Use compiletest to collect the full test list with all directives resolved.
@@ -53,17 +59,15 @@ fn main() {
5359
5460 // Compile the test with LLVM_PROFILE_FILE set so the instrumented
5561 // rustc emits a profraw file.
56- let _result = Command :: new ( config . rustc_path . as_str ( ) )
62+ let _result = Command :: new ( & rustc_path)
5763 . arg ( "--sysroot" )
58- . arg ( config . sysroot_base . as_str ( ) )
64+ . arg ( & sysroot )
5965 . arg ( test_file)
60- . arg ( "--edition" )
61- . arg ( test. revision . as_deref ( ) . unwrap_or ( "2015" ) )
62- . args ( & [ "-o" , "/dev/null" , "--crate-type" , "bin" ] )
66+ . args ( & [ "-o" , "/dev/null" ] )
6367 . env ( "LLVM_PROFILE_FILE" , & profile_file)
6468 . output ( ) ;
6569
66- // Collect any profraw files written
70+ // Collect any profraw files written.
6771 let profraws: Vec < PathBuf > = fs:: read_dir ( & tmpdir)
6872 . unwrap ( )
6973 . filter_map ( |e| e. ok ( ) )
@@ -77,7 +81,7 @@ fn main() {
7781 continue ;
7882 }
7983
80- // Eager merge into running profdata, then delete profraws
84+ // Eager merge into running profdata, then delete profraws.
8185 merge_profraws ( & profraws, & profdata_path) ;
8286 for f in & profraws {
8387 let _ = fs:: remove_file ( f) ;
@@ -105,7 +109,6 @@ fn merge_profraws(profraws: &[PathBuf], profdata: &PathBuf) {
105109}
106110
107111fn find_llvm_profdata ( ) -> String {
108- // Look in the same place bootstrap puts it
109112 glob:: glob ( "build/*/ci-llvm/bin/llvm-profdata" )
110113 . unwrap ( )
111114 . filter_map ( |p| p. ok ( ) )
@@ -114,6 +117,24 @@ fn find_llvm_profdata() -> String {
114117 . unwrap_or_else ( || "llvm-profdata" . to_string ( ) )
115118}
116119
120+ fn find_stage1_rustc ( ) -> String {
121+ glob:: glob ( "build/*/stage1/bin/rustc" )
122+ . unwrap ( )
123+ . filter_map ( |p| p. ok ( ) )
124+ . next ( )
125+ . map ( |p| p. display ( ) . to_string ( ) )
126+ . unwrap_or_else ( || "rustc" . to_string ( ) )
127+ }
128+
129+ fn find_stage1_sysroot ( ) -> String {
130+ glob:: glob ( "build/*/stage1" )
131+ . unwrap ( )
132+ . filter_map ( |p| p. ok ( ) )
133+ . next ( )
134+ . map ( |p| p. display ( ) . to_string ( ) )
135+ . unwrap_or_else ( || "build/host/stage1" . to_string ( ) )
136+ }
137+
117138fn tempdir ( ) -> PathBuf {
118139 let dir = std:: env:: temp_dir ( ) . join ( "cov_profraws" ) ;
119140 fs:: create_dir_all ( & dir) . unwrap ( ) ;
@@ -126,22 +147,20 @@ fn arg_value(args: &[String], flag: &str) -> Option<String> {
126147 . map ( |w| w[ 1 ] . clone ( ) )
127148}
128149
129- fn build_config ( suite : & str ) -> Config {
130- // Construct a minimal Config from environment/args.
131- // This is a stub — in practice bootstrap would pass the full config.
132- parse_config ( vec ! [
133- "coverage-tool" . to_string( ) ,
134- "--mode" . to_string( ) , "ui" . to_string( ) ,
135- "--suite-path" . to_string( ) , suite. to_string( ) ,
136- "--rustc-path" . to_string( ) , find_stage1_rustc( ) ,
137- ] )
138- }
139-
140- fn find_stage1_rustc ( ) -> String {
141- glob:: glob ( "build/*/stage1/bin/rustc" )
142- . unwrap ( )
143- . filter_map ( |p| p. ok ( ) )
144- . next ( )
145- . map ( |p| p. display ( ) . to_string ( ) )
146- . unwrap_or_else ( || "rustc" . to_string ( ) )
150+ /// Remove --flag <value> from an args list and return the rest.
151+ fn strip_flag ( args : Vec < String > , flag : & str ) -> Vec < String > {
152+ let mut out = Vec :: with_capacity ( args. len ( ) ) ;
153+ let mut skip = false ;
154+ for arg in args {
155+ if skip {
156+ skip = false ;
157+ continue ;
158+ }
159+ if arg == flag {
160+ skip = true ;
161+ continue ;
162+ }
163+ out. push ( arg) ;
164+ }
165+ out
147166}
0 commit comments