fn drain_the_queue(
        mut self,
        cx: &mut Context<'_, '_>,
        plan: &mut BuildPlan,
        scope: &Scope<'_>,
        jobserver_helper: &HelperThread,
    ) -> Option<anyhow::Error> {
        trace!("queue: {:#?}", self.queue);

        // Iteratively execute the entire dependency graph. Each turn of the
        // loop starts out by scheduling as much work as possible (up to the
        // maximum number of parallel jobs we have tokens for). A local queue
        // is maintained separately from the main dependency queue as one
        // dequeue may actually dequeue quite a bit of work (e.g., 10 binaries
        // in one package).
        //
        // After a job has finished we update our internal state if it was
        // successful and otherwise wait for pending work to finish if it failed
        // and then immediately return.
        let mut error = None;
        // CAUTION! Do not use `?` or break out of the loop early. Every error
        // must be handled in such a way that the loop is still allowed to
        // drain event messages.
        loop {
            if error.is_none() {
                if let Err(e) = self.spawn_work_if_possible(cx, jobserver_helper, scope) {
                    self.handle_error(&mut cx.bcx.config.shell(), &mut error, e);
                }
            }

            // If after all that we're not actually running anything then we're
            // done!
            if self.active.is_empty() {
                break;
            }

            if let Err(e) = self.grant_rustc_token_requests() {
                self.handle_error(&mut cx.bcx.config.shell(), &mut error, e);
            }

            // And finally, before we block waiting for the next event, drop any
            // excess tokens we may have accidentally acquired. Due to how our
            // jobserver interface is architected we may acquire a token that we
            // don't actually use, and if this happens just relinquish it back
            // to the jobserver itself.
            for event in self.wait_for_events() {
                if let Err(event_err) = self.handle_event(cx, jobserver_helper, plan, event) {
                    self.handle_error(&mut cx.bcx.config.shell(), &mut error, event_err);
                }
            }
        }
        self.progress.clear();

        let profile_name = cx.bcx.build_config.requested_profile;
        // NOTE: this may be a bit inaccurate, since this may not display the
        // profile for what was actually built. Profile overrides can change
        // these settings, and in some cases different targets are built with
        // different profiles. To be accurate, it would need to collect a
        // list of Units built, and maybe display a list of the different
        // profiles used. However, to keep it simple and compatible with old
        // behavior, we just display what the base profile is.
        let profile = cx.bcx.profiles.base_profile();
        let mut opt_type = String::from(if profile.opt_level.as_str() == "0" {
            "unoptimized"
        } else {
            "optimized"
        });
        if profile.debuginfo.unwrap_or(0) != 0 {
            opt_type += " + debuginfo";
        }

        let time_elapsed = util::elapsed(cx.bcx.config.creation_time().elapsed());
        if let Err(e) = self.timings.finished(cx.bcx, &error) {
            if error.is_some() {
                crate::display_error(&e, &mut cx.bcx.config.shell());
            } else {
                return Some(e);
            }
        }
        if cx.bcx.build_config.emit_json() {
            let mut shell = cx.bcx.config.shell();
            let msg = machine_message::BuildFinished {
                success: error.is_none(),
            }
            .to_json_string();
            if let Err(e) = writeln!(shell.out(), "{}", msg) {
                if error.is_some() {
                    crate::display_error(&e.into(), &mut shell);
                } else {
                    return Some(e.into());
                }
            }
        }

        if let Some(e) = error {
            Some(e)
        } else if self.queue.is_empty() && self.pending_queue.is_empty() {
            let message = format!(
                "{} [{}] target(s) in {}",
                profile_name, opt_type, time_elapsed
            );
            if !cx.bcx.build_config.build_plan {
                // It doesn't really matter if this fails.
                drop(cx.bcx.config.shell().status("Finished", message));
                future_incompat::save_and_display_report(
                    cx.bcx,
                    &self.per_package_future_incompat_reports,
                );
            }

            None
        } else {
            debug!("queue: {:#?}", self.queue);
            Some(internal("finished with jobs still left in the queue"))
        }
    }
/// This is the "main" loop, where Cargo does all work to run the
/// compiler.
///
/// This returns an Option to prevent the use of `?` on `Result` types
/// because it is important for the loop to carefully handle errors.
This is the "main" loop, where Cargo does all work to run the
compiler.

This returns an Option to prevent the use of `?` on `Result` types
because it is important for the loop to carefully handle errors.
This is the " main " loop where Cargo does all work to run the compiler . This returns an Option to prevent the use of ` ? ` on ` Result ` types because it is important for the loop to carefully handle errors .
fn drain_the_queue(
        mut self,
        cx: &mut Context<'_, '_>,
        plan: &mut BuildPlan,
        scope: &Scope<'_>,
        jobserver_helper: &HelperThread,
    ) -> Option<anyhow::Error> {
        trace!("queue: {:#?}", self.queue);
        // Iteratively execute the entire dependency graph. Each turn of the
        // loop starts out by scheduling as much work as possible (up to the
        // maximum number of parallel jobs we have tokens for). A local queue
        // is maintained separately from the main dependency queue as one
        // dequeue may actually dequeue quite a bit of work (e.g., 10 binaries
        // in one package).
        //
        // After a job has finished we update our internal state if it was
        // successful and otherwise wait for pending work to finish if it failed
        // and then immediately return.
        let mut error = None;
        // CAUTION! Do not use `?` or break out of the loop early. Every error
        // must be handled in such a way that the loop is still allowed to
        // drain event messages.
        loop {
            if error.is_none() {
                if let Err(e) = self.spawn_work_if_possible(cx, jobserver_helper, scope) {
                    self.handle_error(&mut cx.bcx.config.shell(), &mut error, e);
                }
            }
            // If after all that we're not actually running anything then we're
            // done!
            if self.active.is_empty() {
                break;
            }
            if let Err(e) = self.grant_rustc_token_requests() {
                self.handle_error(&mut cx.bcx.config.shell(), &mut error, e);
            }
            // And finally, before we block waiting for the next event, drop any
            // excess tokens we may have accidentally acquired. Due to how our
            // jobserver interface is architected we may acquire a token that we
            // don't actually use, and if this happens just relinquish it back
            // to the jobserver itself.
            for event in self.wait_for_events() {
                if let Err(event_err) = self.handle_event(cx, jobserver_helper, plan, event) {
                    self.handle_error(&mut cx.bcx.config.shell(), &mut error, event_err);
                }
            }
        }
        self.progress.clear();
        let profile_name = cx.bcx.build_config.requested_profile;
        // NOTE: this may be a bit inaccurate, since this may not display the
        // profile for what was actually built. Profile overrides can change
        // these settings, and in some cases different targets are built with
        // different profiles. To be accurate, it would need to collect a
        // list of Units built, and maybe display a list of the different
        // profiles used. However, to keep it simple and compatible with old
        // behavior, we just display what the base profile is.
        let profile = cx.bcx.profiles.base_profile();
        let mut opt_type = String::from(if profile.opt_level.as_str() == "0" {
            "unoptimized"
        } else {
            "optimized"
        });
        if profile.debuginfo.unwrap_or(0) != 0 {
            opt_type += " + debuginfo";
        }
        let time_elapsed = util::elapsed(cx.bcx.config.creation_time().elapsed());
        if let Err(e) = self.timings.finished(cx.bcx, &error) {
            if error.is_some() {
                crate::display_error(&e, &mut cx.bcx.config.shell());
            } else {
                return Some(e);
            }
        }
        if cx.bcx.build_config.emit_json() {
            let mut shell = cx.bcx.config.shell();
            let msg = machine_message::BuildFinished {
                success: error.is_none(),
            }
            .to_json_string();
            if let Err(e) = writeln!(shell.out(), "{}", msg) {
                if error.is_some() {
                    crate::display_error(&e.into(), &mut shell);
                } else {
                    return Some(e.into());
                }
            }
        }
        if let Some(e) = error {
            Some(e)
        } else if self.queue.is_empty() && self.pending_queue.is_empty() {
            let message = format!(
                "{} [{}] target(s) in {}",
                profile_name, opt_type, time_elapsed
            );
            if !cx.bcx.build_config.build_plan {
                // It doesn't really matter if this fails.
                drop(cx.bcx.config.shell().status("Finished", message));
                future_incompat::save_and_display_report(
                    cx.bcx,
                    &self.per_package_future_incompat_reports,
                );
            }
            None
        } else {
            debug!("queue: {:#?}", self.queue);
            Some(internal("finished with jobs still left in the queue"))
        }
    }
fn drain_the_queue ( mut self , cx : & mut Context < ' _ , ' _ > , plan : & mut BuildPlan , scope : & Scope < ' _ > , jobserver_helper : & HelperThread , ) -> Option < anyhow :: Error > { trace ! ( " " self queue ) ; // Iteratively execute the entire dependency graph. Each turn of the // loop starts out by scheduling as much work as possible (up to the // maximum number of parallel jobs we have tokens for). A local queue // is maintained separately from the main dependency queue as one // dequeue may actually dequeue quite a bit of work (e.g., 10 binaries // in one package). // // After a job has finished we update our internal state if it was // successful and otherwise wait for pending work to finish if it failed // and then immediately return. let mut error = None ; // CAUTION! Do not use `?` or break out of the loop early. Every error // must be handled in such a way that the loop is still allowed to // drain event messages. loop { if error . is_none ( ) { if let Err ( e ) = self . spawn_work_if_possible ( cx , jobserver_helper , scope ) { self . handle_error ( & mut cx . bcx . config . shell ( ) , & mut error , e ) ; } } // If after all that we're not actually running anything then we're // done! if self . active . is_empty ( ) { break ; } if let Err ( e ) = self . grant_rustc_token_requests ( ) { self . handle_error ( & mut cx . bcx . config . shell ( ) , & mut error , e ) ; } // And finally, before we block waiting for the next event, drop any // excess tokens we may have accidentally acquired. Due to how our // jobserver interface is architected we may acquire a token that we // don't actually use, and if this happens just relinquish it back // to the jobserver itself. for event in self . wait_for_events ( ) { if let Err ( event_err ) = self . handle_event ( cx , jobserver_helper , plan , event ) { self . handle_error ( & mut cx . bcx . config . shell ( ) , & mut error , event_err ) ; } } } self . progress . clear ( ) ; let profile_name = cx . bcx . build_config . requested_profile ; // NOTE: this may be a bit inaccurate, since this may not display the // profile for what was actually built. Profile overrides can change // these settings, and in some cases different targets are built with // different profiles. To be accurate, it would need to collect a // list of Units built, and maybe display a list of the different // profiles used. However, to keep it simple and compatible with old // behavior, we just display what the base profile is. let profile = cx . bcx . profiles . base_profile ( ) ; let mut opt_type = String :: from ( if profile . opt_level . as_str ( ) == " " { " " } else { " " } ) ; if profile . debuginfo . unwrap_or ( 0 ) != 0 { opt_type += " " ; } let time_elapsed = util :: elapsed ( cx . bcx . config . creation_time ( ) . elapsed ( ) ) ; if let Err ( e ) = self . timings . finished ( cx . bcx , & error ) { if error . is_some ( ) { crate :: display_error ( & e , & mut cx . bcx . config . shell ( ) ) ; } else { return Some ( e ) ; } } if cx . bcx . build_config . emit_json ( ) { let mut shell = cx . bcx . config . shell ( ) ; let msg = machine_message :: BuildFinished { success : error . is_none ( ) , } . to_json_string ( ) ; if let Err ( e ) = writeln ! ( shell out ( ) " " msg ) { if error . is_some ( ) { crate :: display_error ( & e . into ( ) , & mut shell ) ; } else { return Some ( e . into ( ) ) ; } } } if let Some ( e ) = error { Some ( e ) } else if self . queue . is_empty ( ) && self . pending_queue . is_empty ( ) { let message = format ! ( " " profile_name opt_type time_elapsed ) ; if ! cx . bcx . build_config . build_plan { // It doesn't really matter if this fails. drop ( cx . bcx . config . shell ( ) . status ( " " , message ) ) ; future_incompat :: save_and_display_report ( cx . bcx , & self . per_package_future_incompat_reports , ) ; } None } else { debug ! ( " " self queue ) ; Some ( internal ( " " ) ) } }
This is the "main" loop, where Cargo does all work to run the
compiler.
This is the " main " loop where Cargo does all work to run the compiler .
mut self
cx
&mut Context<'_, '_>
plan
&mut BuildPlan
scope
&Scope<'_>
jobserver_helper
&HelperThread
mut self
cx
&mut Context<'_, '_>
plan
&mut BuildPlan
scope
&Scope<'_>
jobserver_helper
&HelperThread