about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorChris Denton <christophersdenton@gmail.com>2020-05-17 15:22:47 +0100
committerChris Denton <christophersdenton@gmail.com>2020-05-20 15:04:11 +0100
commit2fd504ce2f4d41fb32a660fe2f68a06756df5b2d (patch)
treea4794c0e5252edf3da50b2cda56cddb82c12a5d8 /src
parent7faeae0d385730e712634fb2af331ea0140771b4 (diff)
downloadrust-2fd504ce2f4d41fb32a660fe2f68a06756df5b2d.tar.gz
rust-2fd504ce2f4d41fb32a660fe2f68a06756df5b2d.zip
Suggest installing VS Build Tools in more situations
When MSVC's `link.exe` wasn't found but another `link.exe` was, the error message given can be impenetrable to many users. The usual suspect is GNU's `link` tool. In this case, inform the user that they may need to install VS build tools.

This only applies when Microsoft's link tool is expected. Not `lld-link` or other MSVC compatible linkers.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_codegen_ssa/back/link.rs49
1 files changed, 49 insertions, 0 deletions
diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs
index ce158fb07da..632ed975064 100644
--- a/src/librustc_codegen_ssa/back/link.rs
+++ b/src/librustc_codegen_ssa/back/link.rs
@@ -609,6 +609,55 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
                 .note(&format!("{:?}", &cmd))
                 .note(&escape_string(&output))
                 .emit();
+
+                // If MSVC's `link.exe` was expected but the return code
+                // is not a Microsoft LNK error then suggest a way to fix or
+                // install the Visual Studio build tools.
+                if let Some(code) = prog.status.code() {
+                    if sess.target.target.options.is_like_msvc
+                        && flavor == LinkerFlavor::Msvc
+                        // Respect the command line override
+                        && sess.opts.cg.linker.is_none()
+                        // Match exactly "link.exe"
+                        && linker_path.to_str() == Some("link.exe")
+                        // All Microsoft `link.exe` linking error codes are
+                        // four digit numbers in the range 1000 to 9999 inclusive
+                        && (code < 1000 || code > 9999)
+                    {
+                        let is_vs_installed = windows_registry::find_vs_version().is_ok();
+                        let has_linker = windows_registry::find_tool(
+                            &sess.opts.target_triple.triple(),
+                            "link.exe",
+                        )
+                        .is_some();
+
+                        sess.note_without_error("`link.exe` returned an unexpected error");
+                        if is_vs_installed && has_linker {
+                            // the linker is broken
+                            sess.note_without_error(
+                                "the Visual Studio build tools may need to be repaired \
+                                using the Visual Studio installer",
+                            );
+                            sess.note_without_error(
+                                "or a necessary component may be missing from the \
+                                \"C++ build tools\" workload",
+                            );
+                        } else if is_vs_installed {
+                            // the linker is not installed
+                            sess.note_without_error(
+                                "in the Visual Studio installer, ensure the \
+                                \"C++ build tools\" workload is selected",
+                            );
+                        } else {
+                            // visual studio is not installed
+                            sess.note_without_error(
+                                "you may need to install Visual Studio build tools with the \
+                                \"C++ build tools\" workload",
+                            );
+                        }
+                    }
+                }
+
                 sess.abort_if_errors();
             }
             info!("linker stderr:\n{}", escape_string(&prog.stderr));