Skip to content

Commit a1b33b4

Browse files
committed
Make MSVC detection ludicrously robust
Should fix a few more edge cases Fixes #31151 Fixes #32159 Fixes #34484 Improves rust-lang-deprecated/rust-packaging#50 Signed-off-by: Peter Atashian <[email protected]>
1 parent 126af08 commit a1b33b4

File tree

4 files changed

+260
-181
lines changed

4 files changed

+260
-181
lines changed

src/librustc_trans/back/link.rs

+18-12
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,17 @@ pub fn build_link_meta<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
136136
return r;
137137
}
138138

139-
pub fn get_linker(sess: &Session) -> (String, Command) {
139+
// The third parameter is for an extra path to add to PATH for MSVC
140+
// cross linkers for host toolchain DLL dependencies
141+
pub fn get_linker(sess: &Session) -> (String, Command, Option<PathBuf>) {
140142
if let Some(ref linker) = sess.opts.cg.linker {
141-
(linker.clone(), Command::new(linker))
143+
(linker.clone(), Command::new(linker), None)
142144
} else if sess.target.target.options.is_like_msvc {
143-
("link.exe".to_string(), msvc::link_exe_cmd(sess))
145+
let (cmd, host) = msvc::link_exe_cmd(sess);
146+
("link.exe".to_string(), cmd, host)
144147
} else {
145148
(sess.target.target.options.linker.clone(),
146-
Command::new(&sess.target.target.options.linker))
149+
Command::new(&sess.target.target.options.linker), None)
147150
}
148151
}
149152

@@ -153,17 +156,15 @@ pub fn get_ar_prog(sess: &Session) -> String {
153156
})
154157
}
155158

156-
fn command_path(sess: &Session) -> OsString {
159+
fn command_path(sess: &Session, extra: Option<PathBuf>) -> OsString {
157160
// The compiler's sysroot often has some bundled tools, so add it to the
158161
// PATH for the child.
159162
let mut new_path = sess.host_filesearch(PathKind::All)
160163
.get_tools_search_paths();
161164
if let Some(path) = env::var_os("PATH") {
162165
new_path.extend(env::split_paths(&path));
163166
}
164-
if sess.target.target.options.is_like_msvc {
165-
new_path.extend(msvc::host_dll_path());
166-
}
167+
new_path.extend(extra);
167168
env::join_paths(new_path).unwrap()
168169
}
169170

@@ -379,7 +380,7 @@ fn archive_config<'a>(sess: &'a Session,
379380
src: input.map(|p| p.to_path_buf()),
380381
lib_search_paths: archive_search_paths(sess),
381382
ar_prog: get_ar_prog(sess),
382-
command_path: command_path(sess),
383+
command_path: command_path(sess, None),
383384
}
384385
}
385386

@@ -616,8 +617,8 @@ fn link_natively(sess: &Session,
616617
info!("preparing {:?} from {:?} to {:?}", crate_type, objects, out_filename);
617618

618619
// The invocations of cc share some flags across platforms
619-
let (pname, mut cmd) = get_linker(sess);
620-
cmd.env("PATH", command_path(sess));
620+
let (pname, mut cmd, extra) = get_linker(sess);
621+
cmd.env("PATH", command_path(sess, extra));
621622

622623
let root = sess.target_filesearch(PathKind::Native).get_lib_path();
623624
cmd.args(&sess.target.target.options.pre_link_args);
@@ -682,10 +683,15 @@ fn link_natively(sess: &Session,
682683
info!("linker stdout:\n{}", escape_string(&prog.stdout[..]));
683684
},
684685
Err(e) => {
685-
// Trying to diagnose https://github.com/rust-lang/rust/issues/33844
686686
sess.struct_err(&format!("could not exec the linker `{}`: {}", pname, e))
687687
.note(&format!("{:?}", &cmd))
688688
.emit();
689+
if sess.target.target.options.is_like_msvc && e.kind() == io::ErrorKind::NotFound {
690+
sess.note_without_error("the msvc targets depend on the msvc linker \
691+
but `link.exe` was not found");
692+
sess.note_without_error("please ensure that VS 2013 or VS 2015 was installed \
693+
with the Visual C++ option");
694+
}
689695
sess.abort_if_errors();
690696
}
691697
}

src/librustc_trans/back/msvc/arch.rs

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![allow(non_camel_case_types, non_snake_case)]
12+
13+
use libc::c_void;
14+
use std::mem;
15+
16+
type DWORD = u32;
17+
type WORD = u16;
18+
type LPVOID = *mut c_void;
19+
type DWORD_PTR = usize;
20+
21+
const PROCESSOR_ARCHITECTURE_INTEL: WORD = 0;
22+
const PROCESSOR_ARCHITECTURE_AMD64: WORD = 9;
23+
24+
#[repr(C)]
25+
struct SYSTEM_INFO {
26+
wProcessorArchitecture: WORD,
27+
_wReserved: WORD,
28+
_dwPageSize: DWORD,
29+
_lpMinimumApplicationAddress: LPVOID,
30+
_lpMaximumApplicationAddress: LPVOID,
31+
_dwActiveProcessorMask: DWORD_PTR,
32+
_dwNumberOfProcessors: DWORD,
33+
_dwProcessorType: DWORD,
34+
_dwAllocationGranularity: DWORD,
35+
_wProcessorLevel: WORD,
36+
_wProcessorRevision: WORD,
37+
}
38+
39+
extern "system" {
40+
fn GetNativeSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
41+
}
42+
43+
pub enum Arch {
44+
X86,
45+
Amd64,
46+
}
47+
48+
pub fn host_arch() -> Option<Arch> {
49+
let mut info = unsafe { mem::zeroed() };
50+
unsafe { GetNativeSystemInfo(&mut info) };
51+
match info.wProcessorArchitecture {
52+
PROCESSOR_ARCHITECTURE_INTEL => Some(Arch::X86),
53+
PROCESSOR_ARCHITECTURE_AMD64 => Some(Arch::Amd64),
54+
_ => None,
55+
}
56+
}

0 commit comments

Comments
 (0)