diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 5bd3759a6e0..35abbc77c12 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -147,6 +147,7 @@ pub mod util { pub mod nodemap; pub mod lev_distance; pub mod num; + pub mod fs; } pub mod lib { diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs index 7d8cf5b22a9..311ab1cbd0c 100644 --- a/src/librustc/metadata/filesearch.rs +++ b/src/librustc/metadata/filesearch.rs @@ -19,6 +19,7 @@ use std::io::prelude::*; use std::path::{Path, PathBuf}; use session::search_paths::{SearchPaths, PathKind}; +use util::fs as rustcfs; #[derive(Copy, Clone)] pub enum FileMatch { @@ -191,7 +192,10 @@ pub fn get_or_default_sysroot() -> PathBuf { fn canonicalize(path: Option) -> Option { path.and_then(|path| { match fs::canonicalize(&path) { - Ok(canon) => Some(canon), + // See comments on this target function, but the gist is that + // gcc chokes on verbatim paths which fs::canonicalize generates + // so we try to avoid those kinds of paths. + Ok(canon) => Some(rustcfs::fix_windows_verbatim_for_gcc(&canon)), Err(e) => panic!("failed to get realpath: {}", e), } }) diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 14bc19dffd5..7a8ce1bf48e 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -46,8 +46,9 @@ pub struct Session { pub entry_type: Cell>, pub plugin_registrar_fn: Cell>, pub default_sysroot: Option, - // The name of the root source file of the crate, in the local file system. The path is always - // expected to be absolute. `None` means that there is no source file. + // The name of the root source file of the crate, in the local file system. + // The path is always expected to be absolute. `None` means that there is no + // source file. pub local_crate_source_file: Option, pub working_dir: PathBuf, pub lint_store: RefCell, diff --git a/src/librustc/util/fs.rs b/src/librustc/util/fs.rs new file mode 100644 index 00000000000..3ae78fa7c19 --- /dev/null +++ b/src/librustc/util/fs.rs @@ -0,0 +1,38 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::path::{self, Path, PathBuf}; +use std::ffi::OsString; + +// Unfortunately, on windows, gcc cannot accept paths of the form `\\?\C:\...` +// (a verbatim path). This form of path is generally pretty rare, but the +// implementation of `fs::canonicalize` currently generates paths of this form, +// meaning that we're going to be passing quite a few of these down to gcc. +// +// For now we just strip the "verbatim prefix" of `\\?\` from the path. This +// will probably lose information in some cases, but there's not a whole lot +// more we can do with a buggy gcc... +pub fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf { + if !cfg!(windows) { + return p.to_path_buf() + } + let mut components = p.components(); + let prefix = match components.next() { + Some(path::Component::Prefix(p)) => p, + _ => return p.to_path_buf(), + }; + let disk = match prefix.kind() { + path::Prefix::VerbatimDisk(disk) => disk, + _ => return p.to_path_buf(), + }; + let mut base = OsString::from(format!("{}:", disk as char)); + base.push(components.as_path()); + PathBuf::from(base) +} diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 154e0a1f644..45d81ff0f65 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -479,7 +479,8 @@ pub fn phase_2_configure_and_expand(sess: &Session, let mut _old_path = OsString::new(); if cfg!(windows) { _old_path = env::var_os("PATH").unwrap_or(_old_path); - let mut new_path = sess.host_filesearch(PathKind::All).get_dylib_search_paths(); + let mut new_path = sess.host_filesearch(PathKind::All) + .get_dylib_search_paths(); new_path.extend(env::split_paths(&_old_path)); env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap()); } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 92c9549b377..8830cd13052 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -26,13 +26,14 @@ use middle::ty::{self, Ty}; use util::common::time; use util::ppaux; use util::sha2::{Digest, Sha256}; +use util::fs::fix_windows_verbatim_for_gcc; use rustc_back::tempdir::TempDir; use std::ffi::OsString; use std::fs::{self, PathExt}; use std::io::{self, Read, Write}; use std::mem; -use std::path::{self, Path, PathBuf}; +use std::path::{Path, PathBuf}; use std::process::Command; use std::str; use flate; @@ -1333,29 +1334,3 @@ fn add_upstream_native_libraries(cmd: &mut Command, sess: &Session) { } } } - -// Unfortunately, on windows, gcc cannot accept paths of the form `\\?\C:\...` -// (a verbatim path). This form of path is generally pretty rare, but the -// implementation of `fs::canonicalize` currently generates paths of this form, -// meaning that we're going to be passing quite a few of these down to gcc. -// -// For now we just strip the "verbatim prefix" of `\\?\` from the path. This -// will probably lose information in some cases, but there's not a whole lot -// more we can do with a buggy gcc... -fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf { - if !cfg!(windows) { - return p.to_path_buf() - } - let mut components = p.components(); - let prefix = match components.next() { - Some(path::Component::Prefix(p)) => p, - _ => return p.to_path_buf(), - }; - let disk = match prefix.kind() { - path::Prefix::VerbatimDisk(disk) => disk, - _ => return p.to_path_buf(), - }; - let mut base = OsString::from(format!("{}:", disk as char)); - base.push(components.as_path()); - PathBuf::from(base) -}