@@ -23,6 +23,7 @@ use rustc_target::spec::{Target, TargetTriple};
2323use tempfile:: Builder as TempFileBuilder ;
2424
2525use std:: env;
26+ use std:: fs:: File ;
2627use std:: io:: { self , Write } ;
2728use std:: panic;
2829use std:: path:: { Path , PathBuf } ;
@@ -31,6 +32,8 @@ use std::str;
3132use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
3233use std:: sync:: { Arc , Mutex } ;
3334
35+ use tempfile:: tempdir;
36+
3437use crate :: clean:: { types:: AttributesExt , Attributes } ;
3538use crate :: config:: Options as RustdocOptions ;
3639use crate :: html:: markdown:: { self , ErrorCodes , Ignore , LangString } ;
@@ -48,7 +51,51 @@ pub(crate) struct GlobalTestOptions {
4851 pub ( crate ) attrs : Vec < String > ,
4952}
5053
51- pub ( crate ) fn run ( options : RustdocOptions ) -> Result < ( ) , ErrorGuaranteed > {
54+ pub ( crate ) fn generate_args_file ( file_path : & Path , options : & RustdocOptions ) -> Result < ( ) , String > {
55+ let mut file = File :: create ( file_path)
56+ . map_err ( |error| format ! ( "failed to create args file: {error:?}" ) ) ?;
57+
58+ // We now put the common arguments into the file we created.
59+ let mut content = vec ! [ "--crate-type=bin" . to_string( ) ] ;
60+
61+ for cfg in & options. cfgs {
62+ content. push ( format ! ( "--cfg={cfg}" ) ) ;
63+ }
64+ if !options. check_cfgs . is_empty ( ) {
65+ content. push ( "-Zunstable-options" . to_string ( ) ) ;
66+ for check_cfg in & options. check_cfgs {
67+ content. push ( format ! ( "--check-cfg={check_cfg}" ) ) ;
68+ }
69+ }
70+
71+ if let Some ( sysroot) = & options. maybe_sysroot {
72+ content. push ( format ! ( "--sysroot={}" , sysroot. display( ) ) ) ;
73+ }
74+ for lib_str in & options. lib_strs {
75+ content. push ( format ! ( "-L{lib_str}" ) ) ;
76+ }
77+ for extern_str in & options. extern_strs {
78+ content. push ( format ! ( "--extern={extern_str}" ) ) ;
79+ }
80+ content. push ( "-Ccodegen-units=1" . to_string ( ) ) ;
81+ for codegen_options_str in & options. codegen_options_strs {
82+ content. push ( format ! ( "-C{codegen_options_str}" ) ) ;
83+ }
84+ for unstable_option_str in & options. unstable_opts_strs {
85+ content. push ( format ! ( "-Z{unstable_option_str}" ) ) ;
86+ }
87+
88+ let content = content. join ( "\n " ) ;
89+
90+ file. write ( content. as_bytes ( ) )
91+ . map_err ( |error| format ! ( "failed to write arguments to temporary file: {error:?}" ) ) ?;
92+ Ok ( ( ) )
93+ }
94+
95+ pub ( crate ) fn run (
96+ dcx : & rustc_errors:: DiagCtxt ,
97+ options : RustdocOptions ,
98+ ) -> Result < ( ) , ErrorGuaranteed > {
5299 let input = config:: Input :: File ( options. input . clone ( ) ) ;
53100
54101 let invalid_codeblock_attributes_name = crate :: lint:: INVALID_CODEBLOCK_ATTRIBUTES . name ;
@@ -118,6 +165,15 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
118165 let externs = options. externs . clone ( ) ;
119166 let json_unused_externs = options. json_unused_externs ;
120167
168+ let temp_dir = match tempdir ( )
169+ . map_err ( |error| format ! ( "failed to create temporary directory: {error:?}" ) )
170+ {
171+ Ok ( temp_dir) => temp_dir,
172+ Err ( error) => return crate :: wrap_return ( dcx, Err ( error) ) ,
173+ } ;
174+ let file_path = temp_dir. path ( ) . join ( "rustdoc-cfgs" ) ;
175+ crate :: wrap_return ( dcx, generate_args_file ( & file_path, & options) ) ?;
176+
121177 let ( tests, unused_extern_reports, compiling_test_count) =
122178 interface:: run_compiler ( config, |compiler| {
123179 compiler. enter ( |queries| {
@@ -134,6 +190,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
134190 Some ( compiler. sess . psess . clone_source_map ( ) ) ,
135191 None ,
136192 enable_per_target_ignores,
193+ file_path,
137194 ) ;
138195
139196 let mut hir_collector = HirCollector {
@@ -334,6 +391,7 @@ fn run_test(
334391 path : PathBuf ,
335392 test_id : & str ,
336393 report_unused_externs : impl Fn ( UnusedExterns ) ,
394+ arg_file : PathBuf ,
337395) -> Result < ( ) , TestFailure > {
338396 let ( test, line_offset, supports_color) =
339397 make_test ( test, Some ( crate_name) , lang_string. test_harness , opts, edition, Some ( test_id) ) ;
@@ -347,19 +405,9 @@ fn run_test(
347405 . as_deref ( )
348406 . unwrap_or_else ( || rustc_interface:: util:: rustc_path ( ) . expect ( "found rustc" ) ) ;
349407 let mut compiler = wrapped_rustc_command ( & rustdoc_options. test_builder_wrappers , rustc_binary) ;
350- compiler. arg ( "--crate-type" ) . arg ( "bin" ) ;
351- for cfg in & rustdoc_options. cfgs {
352- compiler. arg ( "--cfg" ) . arg ( & cfg) ;
353- }
354- if !rustdoc_options. check_cfgs . is_empty ( ) {
355- compiler. arg ( "-Z" ) . arg ( "unstable-options" ) ;
356- for check_cfg in & rustdoc_options. check_cfgs {
357- compiler. arg ( "--check-cfg" ) . arg ( & check_cfg) ;
358- }
359- }
360- if let Some ( sysroot) = rustdoc_options. maybe_sysroot {
361- compiler. arg ( "--sysroot" ) . arg ( sysroot) ;
362- }
408+
409+ compiler. arg ( & format ! ( "@{}" , arg_file. display( ) ) ) ;
410+
363411 compiler. arg ( "--edition" ) . arg ( & edition. to_string ( ) ) ;
364412 compiler. env ( "UNSTABLE_RUSTDOC_TEST_PATH" , path) ;
365413 compiler. env ( "UNSTABLE_RUSTDOC_TEST_LINE" , format ! ( "{}" , line as isize - line_offset as isize ) ) ;
@@ -370,22 +418,10 @@ fn run_test(
370418 if rustdoc_options. json_unused_externs . is_enabled ( ) && !lang_string. compile_fail {
371419 compiler. arg ( "--error-format=json" ) ;
372420 compiler. arg ( "--json" ) . arg ( "unused-externs" ) ;
373- compiler. arg ( "-Z" ) . arg ( "unstable-options" ) ;
374421 compiler. arg ( "-W" ) . arg ( "unused_crate_dependencies" ) ;
422+ compiler. arg ( "-Z" ) . arg ( "unstable-options" ) ;
375423 }
376- for lib_str in & rustdoc_options. lib_strs {
377- compiler. arg ( "-L" ) . arg ( & lib_str) ;
378- }
379- for extern_str in & rustdoc_options. extern_strs {
380- compiler. arg ( "--extern" ) . arg ( & extern_str) ;
381- }
382- compiler. arg ( "-Ccodegen-units=1" ) ;
383- for codegen_options_str in & rustdoc_options. codegen_options_strs {
384- compiler. arg ( "-C" ) . arg ( & codegen_options_str) ;
385- }
386- for unstable_option_str in & rustdoc_options. unstable_opts_strs {
387- compiler. arg ( "-Z" ) . arg ( & unstable_option_str) ;
388- }
424+
389425 if no_run && !lang_string. compile_fail && rustdoc_options. persist_doctests . is_none ( ) {
390426 compiler. arg ( "--emit=metadata" ) ;
391427 }
@@ -941,6 +977,7 @@ pub(crate) struct Collector {
941977 visited_tests : FxHashMap < ( String , usize ) , usize > ,
942978 unused_extern_reports : Arc < Mutex < Vec < UnusedExterns > > > ,
943979 compiling_test_count : AtomicUsize ,
980+ arg_file : PathBuf ,
944981}
945982
946983impl Collector {
@@ -952,6 +989,7 @@ impl Collector {
952989 source_map : Option < Lrc < SourceMap > > ,
953990 filename : Option < PathBuf > ,
954991 enable_per_target_ignores : bool ,
992+ arg_file : PathBuf ,
955993 ) -> Collector {
956994 Collector {
957995 tests : Vec :: new ( ) ,
@@ -967,6 +1005,7 @@ impl Collector {
9671005 visited_tests : FxHashMap :: default ( ) ,
9681006 unused_extern_reports : Default :: default ( ) ,
9691007 compiling_test_count : AtomicUsize :: new ( 0 ) ,
1008+ arg_file,
9701009 }
9711010 }
9721011
@@ -1067,6 +1106,8 @@ impl Tester for Collector {
10671106 )
10681107 } ;
10691108
1109+ let arg_file = self . arg_file . clone ( ) ;
1110+
10701111 debug ! ( "creating test {name}: {test}" ) ;
10711112 self . tests . push ( test:: TestDescAndFn {
10721113 desc : test:: TestDesc {
@@ -1108,6 +1149,7 @@ impl Tester for Collector {
11081149 path,
11091150 & test_id,
11101151 report_unused_externs,
1152+ arg_file,
11111153 ) ;
11121154
11131155 if let Err ( err) = res {
0 commit comments