@@ -22,7 +22,7 @@ mod unit;
2222pub mod unit_dependencies;
2323pub mod unit_graph;
2424
25- use std:: collections:: HashSet ;
25+ use std:: collections:: { HashMap , HashSet } ;
2626use std:: env;
2727use std:: ffi:: { OsStr , OsString } ;
2828use std:: fs:: { self , File } ;
@@ -55,7 +55,7 @@ use crate::core::compiler::future_incompat::FutureIncompatReport;
5555pub use crate :: core:: compiler:: unit:: { Unit , UnitInterner } ;
5656use crate :: core:: manifest:: TargetSourcePath ;
5757use crate :: core:: profiles:: { PanicStrategy , Profile , Strip } ;
58- use crate :: core:: { Feature , PackageId , Target } ;
58+ use crate :: core:: { Feature , PackageId , Target , Verbosity } ;
5959use crate :: util:: errors:: { CargoResult , VerboseError } ;
6060use crate :: util:: interning:: InternedString ;
6161use crate :: util:: machine_message:: { self , Message } ;
@@ -654,13 +654,16 @@ fn rustdoc(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Work> {
654654 rustdoc. arg ( "-C" ) . arg ( format ! ( "metadata={}" , metadata) ) ;
655655
656656 let scrape_output_path = |unit : & Unit | -> CargoResult < PathBuf > {
657- let output_dir = cx. files ( ) . deps_dir ( unit) ;
658- Ok ( output_dir. join ( format ! ( "{}.examples" , unit. buildkey( ) ) ) )
657+ cx. outputs ( unit) . map ( |outputs| outputs[ 0 ] . path . clone ( ) )
659658 } ;
660659
661660 if unit. mode . is_doc_scrape ( ) {
662661 debug_assert ! ( cx. bcx. scrape_units. contains( unit) ) ;
663662
663+ if unit. target . is_test ( ) {
664+ rustdoc. arg ( "--scrape-tests" ) ;
665+ }
666+
664667 rustdoc. arg ( "-Zunstable-options" ) ;
665668
666669 rustdoc
@@ -678,18 +681,23 @@ fn rustdoc(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Work> {
678681 rustdoc. arg ( "--scrape-examples-target-crate" ) . arg ( name) ;
679682 }
680683 }
681- } else if cx. bcx . scrape_units . len ( ) > 0 && cx. bcx . ws . unit_needs_doc_scrape ( unit) {
682- // We only pass scraped examples to packages in the workspace
683- // since examples are only coming from reverse-dependencies of workspace packages
684+ }
684685
686+ let should_include_scrape_units = unit. mode . is_doc ( )
687+ && cx. bcx . scrape_units . len ( ) > 0
688+ && cx. bcx . ws . unit_needs_doc_scrape ( unit) ;
689+ let scrape_outputs = if should_include_scrape_units {
685690 rustdoc. arg ( "-Zunstable-options" ) ;
686-
687- for scrape_unit in & cx. bcx . scrape_units {
688- rustdoc
689- . arg ( "--with-examples" )
690- . arg ( scrape_output_path ( scrape_unit) ?) ;
691- }
692- }
691+ Some (
692+ cx. bcx
693+ . scrape_units
694+ . iter ( )
695+ . map ( |unit| Ok ( ( cx. files ( ) . metadata ( unit) , scrape_output_path ( unit) ?) ) )
696+ . collect :: < CargoResult < HashMap < _ , _ > > > ( ) ?,
697+ )
698+ } else {
699+ None
700+ } ;
693701
694702 build_deps_args ( & mut rustdoc, cx, unit) ?;
695703 rustdoc:: add_root_urls ( cx, unit, & mut rustdoc) ?;
@@ -700,19 +708,45 @@ fn rustdoc(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Work> {
700708 append_crate_version_flag ( unit, & mut rustdoc) ;
701709 }
702710
711+ let target_desc = unit. target . description_named ( ) ;
703712 let name = unit. pkg . name ( ) . to_string ( ) ;
704713 let build_script_outputs = Arc :: clone ( & cx. build_script_outputs ) ;
705714 let package_id = unit. pkg . package_id ( ) ;
706715 let manifest_path = PathBuf :: from ( unit. pkg . manifest_path ( ) ) ;
716+ let relative_manifest_path = manifest_path
717+ . strip_prefix ( cx. bcx . ws . root ( ) )
718+ . unwrap_or ( & manifest_path)
719+ . to_owned ( ) ;
707720 let target = Target :: clone ( & unit. target ) ;
708721 let mut output_options = OutputOptions :: new ( cx, unit) ;
709722 let script_metadata = cx. find_build_script_metadata ( unit) ;
723+ let failed_scrape_units = Arc :: clone ( & cx. failed_scrape_units ) ;
724+ let hide_diagnostics_for_scrape_unit = unit. mode . is_doc_scrape ( )
725+ && unit. target . doc_scrape_examples ( ) . is_unset ( )
726+ && !matches ! ( cx. bcx. config. shell( ) . verbosity( ) , Verbosity :: Verbose ) ;
727+ if hide_diagnostics_for_scrape_unit {
728+ output_options. show_diagnostics = false ;
729+ }
710730 Ok ( Work :: new ( move |state| {
711731 add_custom_flags (
712732 & mut rustdoc,
713733 & build_script_outputs. lock ( ) . unwrap ( ) ,
714734 script_metadata,
715735 ) ?;
736+
737+ // Add the output of scraped examples to the rustdoc command.
738+ // This action must happen after the unit's dependencies have finished,
739+ // because some of those deps may be Docscrape units which have failed.
740+ // So we dynamically determine which `--with-examples` flags to pass here.
741+ if let Some ( scrape_outputs) = scrape_outputs {
742+ let failed_scrape_units = failed_scrape_units. lock ( ) . unwrap ( ) ;
743+ for ( metadata, output_path) in & scrape_outputs {
744+ if !failed_scrape_units. contains ( metadata) {
745+ rustdoc. arg ( "--with-examples" ) . arg ( output_path) ;
746+ }
747+ }
748+ }
749+
716750 let crate_dir = doc_dir. join ( & crate_name) ;
717751 if crate_dir. exists ( ) {
718752 // Remove output from a previous build. This ensures that stale
@@ -722,7 +756,7 @@ fn rustdoc(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Work> {
722756 }
723757 state. running ( & rustdoc) ;
724758
725- rustdoc
759+ let result = rustdoc
726760 . exec_with_streaming (
727761 & mut |line| on_stdout_line ( state, line, package_id, & target) ,
728762 & mut |line| {
@@ -737,7 +771,23 @@ fn rustdoc(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Work> {
737771 } ,
738772 false ,
739773 )
740- . with_context ( || format ! ( "could not document `{}`" , name) ) ?;
774+ . with_context ( || format ! ( "could not document `{}`" , name) ) ;
775+
776+ if let Err ( e) = result {
777+ if hide_diagnostics_for_scrape_unit {
778+ let diag = format ! (
779+ "\
780+ failed to scan {target_desc} in package `{name}` for example code usage
781+ Try running with `--verbose` to see the error message.
782+ If this example should not be scanned, consider adding `doc-scrape-examples = false` to the `[[example]]` definition in {}" ,
783+ relative_manifest_path. display( )
784+ ) ;
785+ state. warning ( diag) ?;
786+ }
787+
788+ return Err ( e) ;
789+ }
790+
741791 Ok ( ( ) )
742792 } ) )
743793}
0 commit comments