1111use std:: path:: { self , Path , PathBuf } ;
1212use std:: ffi:: OsString ;
1313
14- // Unfortunately, on windows, gcc cannot accept paths of the form `\\?\C:\...`
15- // (a verbatim path). This form of path is generally pretty rare, but the
16- // implementation of `fs::canonicalize` currently generates paths of this form,
17- // meaning that we're going to be passing quite a few of these down to gcc.
14+ // Unfortunately, on windows, it looks like msvcrt.dll is silently translating
15+ // verbatim paths under the hood to non-verbatim paths! This manifests itself as
16+ // gcc looking like it cannot accept paths of the form `\\?\C:\...`, but the
17+ // real bug seems to lie in msvcrt.dll.
18+ //
19+ // Verbatim paths are generally pretty rare, but the implementation of
20+ // `fs::canonicalize` currently generates paths of this form, meaning that we're
21+ // going to be passing quite a few of these down to gcc, so we need to deal with
22+ // this case.
1823//
1924// For now we just strip the "verbatim prefix" of `\\?\` from the path. This
2025// will probably lose information in some cases, but there's not a whole lot
21- // more we can do with a buggy gcc...
26+ // more we can do with a buggy msvcrt...
27+ //
28+ // For some more information, see this comment:
29+ // https://github.com/rust-lang/rust/issues/25505#issuecomment-102876737
2230pub fn fix_windows_verbatim_for_gcc ( p : & Path ) -> PathBuf {
2331 if !cfg ! ( windows) {
2432 return p. to_path_buf ( )
@@ -28,11 +36,20 @@ pub fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf {
2836 Some ( path:: Component :: Prefix ( p) ) => p,
2937 _ => return p. to_path_buf ( ) ,
3038 } ;
31- let disk = match prefix. kind ( ) {
32- path:: Prefix :: VerbatimDisk ( disk) => disk,
33- _ => return p. to_path_buf ( ) ,
34- } ;
35- let mut base = OsString :: from ( format ! ( "{}:" , disk as char ) ) ;
36- base. push ( components. as_path ( ) ) ;
37- PathBuf :: from ( base)
39+ match prefix. kind ( ) {
40+ path:: Prefix :: VerbatimDisk ( disk) => {
41+ let mut base = OsString :: from ( format ! ( "{}:" , disk as char ) ) ;
42+ base. push ( components. as_path ( ) ) ;
43+ PathBuf :: from ( base)
44+ }
45+ path:: Prefix :: VerbatimUNC ( server, share) => {
46+ let mut base = OsString :: from ( r"\\" ) ;
47+ base. push ( server) ;
48+ base. push ( r"\" ) ;
49+ base. push ( share) ;
50+ base. push ( components. as_path ( ) ) ;
51+ PathBuf :: from ( base)
52+ }
53+ _ => p. to_path_buf ( ) ,
54+ }
3855}
0 commit comments