@@ -66,7 +66,7 @@ pub(crate) fn do_msvc_check(opts: &InstallOpts<'_>) -> Option<VsInstallPlan> {
66
66
}
67
67
}
68
68
69
- #[ derive( Debug ) ]
69
+ #[ derive( Debug , Eq , PartialEq ) ]
70
70
struct VsInstallError ( i32 ) ;
71
71
impl std:: error:: Error for VsInstallError { }
72
72
impl fmt:: Display for VsInstallError {
@@ -97,8 +97,21 @@ impl fmt::Display for VsInstallError {
97
97
write ! ( f, "{} (exit code {})" , message, self . 0 )
98
98
}
99
99
}
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
+ }
100
109
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 > {
102
115
// download the installer
103
116
let visual_studio_url = utils:: parse_url ( "https://aka.ms/vs/17/release/vs_community.exe" ) ?;
104
117
@@ -131,16 +144,7 @@ pub(crate) fn try_install_msvc() -> Result<()> {
131
144
132
145
// It's possible an earlier or later version of the Windows SDK has been
133
146
// 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 ( ) {
144
148
cmd. args ( [
145
149
"--add" ,
146
150
"Microsoft.VisualStudio.Component.Windows11SDK.22000" ,
@@ -154,12 +158,51 @@ pub(crate) fn try_install_msvc() -> Result<()> {
154
158
. context ( "error running Visual Studio installer" ) ?;
155
159
156
160
if exit_status. success ( ) {
157
- Ok ( ( ) )
161
+ Ok ( ContinueInstall :: Yes )
158
162
} 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
+ }
160
191
}
161
192
}
162
193
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
+
163
206
/// Run by rustup-gc-$num.exe to delete CARGO_HOME
164
207
pub fn complete_windows_uninstall ( ) -> Result < utils:: ExitCode > {
165
208
use std:: process:: Stdio ;
0 commit comments