Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make MSVC detection ludicrously robust #34492

Merged
merged 1 commit into from
Jul 2, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 18 additions & 12 deletions src/librustc_trans/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,17 @@ pub fn build_link_meta<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
return r;
}

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

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

fn command_path(sess: &Session) -> OsString {
fn command_path(sess: &Session, extra: Option<PathBuf>) -> OsString {
// The compiler's sysroot often has some bundled tools, so add it to the
// PATH for the child.
let mut new_path = sess.host_filesearch(PathKind::All)
.get_tools_search_paths();
if let Some(path) = env::var_os("PATH") {
new_path.extend(env::split_paths(&path));
}
if sess.target.target.options.is_like_msvc {
new_path.extend(msvc::host_dll_path());
}
new_path.extend(extra);
env::join_paths(new_path).unwrap()
}

Expand Down Expand Up @@ -379,7 +380,7 @@ fn archive_config<'a>(sess: &'a Session,
src: input.map(|p| p.to_path_buf()),
lib_search_paths: archive_search_paths(sess),
ar_prog: get_ar_prog(sess),
command_path: command_path(sess),
command_path: command_path(sess, None),
}
}

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

// The invocations of cc share some flags across platforms
let (pname, mut cmd) = get_linker(sess);
cmd.env("PATH", command_path(sess));
let (pname, mut cmd, extra) = get_linker(sess);
cmd.env("PATH", command_path(sess, extra));

let root = sess.target_filesearch(PathKind::Native).get_lib_path();
cmd.args(&sess.target.target.options.pre_link_args);
Expand Down Expand Up @@ -682,10 +683,15 @@ fn link_natively(sess: &Session,
info!("linker stdout:\n{}", escape_string(&prog.stdout[..]));
},
Err(e) => {
// Trying to diagnose https://github.com/rust-lang/rust/issues/33844
sess.struct_err(&format!("could not exec the linker `{}`: {}", pname, e))
.note(&format!("{:?}", &cmd))
.emit();
if sess.target.target.options.is_like_msvc && e.kind() == io::ErrorKind::NotFound {
sess.note_without_error("the msvc targets depend on the msvc linker \
but `link.exe` was not found");
sess.note_without_error("please ensure that VS 2013 or VS 2015 was installed \
with the Visual C++ option");
}
sess.abort_if_errors();
}
}
Expand Down
56 changes: 56 additions & 0 deletions src/librustc_trans/back/msvc/arch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(non_camel_case_types, non_snake_case)]

use libc::c_void;
use std::mem;

type DWORD = u32;
type WORD = u16;
type LPVOID = *mut c_void;
type DWORD_PTR = usize;

const PROCESSOR_ARCHITECTURE_INTEL: WORD = 0;
const PROCESSOR_ARCHITECTURE_AMD64: WORD = 9;

#[repr(C)]
struct SYSTEM_INFO {
wProcessorArchitecture: WORD,
_wReserved: WORD,
_dwPageSize: DWORD,
_lpMinimumApplicationAddress: LPVOID,
_lpMaximumApplicationAddress: LPVOID,
_dwActiveProcessorMask: DWORD_PTR,
_dwNumberOfProcessors: DWORD,
_dwProcessorType: DWORD,
_dwAllocationGranularity: DWORD,
_wProcessorLevel: WORD,
_wProcessorRevision: WORD,
}

extern "system" {
fn GetNativeSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
}

pub enum Arch {
X86,
Amd64,
}

pub fn host_arch() -> Option<Arch> {
let mut info = unsafe { mem::zeroed() };
unsafe { GetNativeSystemInfo(&mut info) };
match info.wProcessorArchitecture {
PROCESSOR_ARCHITECTURE_INTEL => Some(Arch::X86),
PROCESSOR_ARCHITECTURE_AMD64 => Some(Arch::Amd64),
_ => None,
}
}
Loading