@@ -66,7 +66,7 @@ pub(crate) fn do_msvc_check(opts: &InstallOpts<'_>) -> Option<VsInstallPlan> {
6666 }
6767}
6868
69- #[ derive( Debug ) ]
69+ #[ derive( Debug , Eq , PartialEq ) ]
7070struct VsInstallError ( i32 ) ;
7171impl std:: error:: Error for VsInstallError { }
7272impl fmt:: Display for VsInstallError {
@@ -97,8 +97,21 @@ impl fmt::Display for VsInstallError {
9797 write ! ( f, "{} (exit code {})" , message, self . 0 )
9898 }
9999}
100+ impl VsInstallError {
101+ const REBOOTING_NOW : Self = Self ( 1641 ) ;
102+ const REBOOT_REQUIRED : Self = Self ( 3010 ) ;
103+ }
104+
105+ pub ( crate ) enum ContinueInstall {
106+ Yes ,
107+ No ,
108+ }
100109
101- pub ( crate ) fn try_install_msvc ( ) -> Result < ( ) > {
110+ /// Tries to install the needed Visual Studio components.
111+ ///
112+ /// Returns `Ok(ContinueInstall::No)` if installing Visual Studio was successful
113+ /// but the rustup install should not be continued at this time.
114+ pub ( crate ) fn try_install_msvc ( opts : & InstallOpts < ' _ > ) -> Result < ContinueInstall > {
102115 // download the installer
103116 let visual_studio_url = utils:: parse_url ( "https://aka.ms/vs/17/release/vs_community.exe" ) ?;
104117
@@ -131,16 +144,7 @@ pub(crate) fn try_install_msvc() -> Result<()> {
131144
132145 // It's possible an earlier or later version of the Windows SDK has been
133146 // installed separately from Visual Studio so installing it can be skipped.
134- let mut has_libs = false ;
135- if let Some ( paths) = process ( ) . var_os ( "lib" ) {
136- for mut path in split_paths ( & paths) {
137- path. push ( "kernel32.lib" ) ;
138- if path. exists ( ) {
139- has_libs = true ;
140- }
141- }
142- } ;
143- if !has_libs {
147+ if !has_windows_sdk_libs ( ) {
144148 cmd. args ( [
145149 "--add" ,
146150 "Microsoft.VisualStudio.Component.Windows11SDK.22000" ,
@@ -154,12 +158,51 @@ pub(crate) fn try_install_msvc() -> Result<()> {
154158 . context ( "error running Visual Studio installer" ) ?;
155159
156160 if exit_status. success ( ) {
157- Ok ( ( ) )
161+ Ok ( ContinueInstall :: Yes )
158162 } else {
159- Err ( VsInstallError ( exit_status. code ( ) . unwrap ( ) ) ) . context ( "failed to install Visual Studio" )
163+ match VsInstallError ( exit_status. code ( ) . unwrap ( ) ) {
164+ err @ VsInstallError :: REBOOT_REQUIRED => {
165+ // A reboot is required but the user opted to delay it.
166+ warn ! ( "{}" , err) ;
167+ Ok ( ContinueInstall :: Yes )
168+ }
169+ err @ VsInstallError :: REBOOTING_NOW => {
170+ // The user is wanting to reboot right now, so we should
171+ // not continue the install.
172+ warn ! ( "{}" , err) ;
173+ info ! ( "\n Run rustup-init after restart to continue install" ) ;
174+ Ok ( ContinueInstall :: No )
175+ }
176+ err => {
177+ // It's possible that the installer returned a non-zero exit code
178+ // even though the required components were successfully installed.
179+ // In that case we warn about the error but continue on.
180+ let have_msvc = do_msvc_check ( opts) . is_none ( ) ;
181+ let has_libs = has_windows_sdk_libs ( ) ;
182+ if have_msvc && has_libs {
183+ warn ! ( "Visual Studio is installed but a problem ocurred during installation" ) ;
184+ warn ! ( "{}" , err) ;
185+ Ok ( ContinueInstall :: Yes )
186+ } else {
187+ Err ( err) . context ( "failed to install Visual Studio" )
188+ }
189+ }
190+ }
160191 }
161192}
162193
194+ fn has_windows_sdk_libs ( ) -> bool {
195+ if let Some ( paths) = process ( ) . var_os ( "lib" ) {
196+ for mut path in split_paths ( & paths) {
197+ path. push ( "kernel32.lib" ) ;
198+ if path. exists ( ) {
199+ return true ;
200+ }
201+ }
202+ } ;
203+ false
204+ }
205+
163206/// Run by rustup-gc-$num.exe to delete CARGO_HOME
164207pub fn complete_windows_uninstall ( ) -> Result < utils:: ExitCode > {
165208 use std:: process:: Stdio ;
0 commit comments