Skip to content

Commit 08af05c

Browse files
authored
Windows: Remove the \\?\ prefix from paths (#259)
When a path is canonicalized on Windows, a `\\?\` prefix is used. However, it appears that cmake can have problems with that. This simply attempts to remove the prefix as we do still want to use absolute path here due to #200. Fixes #258
1 parent 6e68d9c commit 08af05c

File tree

1 file changed

+23
-1
lines changed

1 file changed

+23
-1
lines changed

src/lib.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1139,7 +1139,29 @@ fn uses_named_pipe_jobserver(makeflags: &OsStr) -> bool {
11391139
/// Attempt to canonicalize; fall back to the original path if unsuccessful, in case `cmake` knows
11401140
/// something we don't.
11411141
fn try_canonicalize(path: &Path) -> PathBuf {
1142-
path.canonicalize().unwrap_or_else(|_| path.to_owned())
1142+
let path = path.canonicalize().unwrap_or_else(|_| path.to_owned());
1143+
// On Windows, attempt to remove the verbatim prefix from the canonicalized path.
1144+
// FIXME(ChrisDenton): once MSRV is >=1.79 use `std::path::absolute` instead of canonicalize.
1145+
// That will avoid the need for this hack.
1146+
#[cfg(windows)]
1147+
{
1148+
use std::os::windows::ffi::{OsStrExt, OsStringExt};
1149+
let mut wide: Vec<u16> = path.as_os_str().encode_wide().collect();
1150+
if wide.starts_with(&[b'\\' as u16, b'\\' as u16, b'?' as u16, b'\\' as u16]) {
1151+
if wide.get(5..7) == Some(&[b':' as u16, b'\\' as u16]) {
1152+
// Convert \\?\C:\ to C:\
1153+
wide.copy_within(4.., 0);
1154+
wide.truncate(wide.len() - 4);
1155+
} else if wide.get(4..8) == Some(&[b'U' as u16, b'N' as u16, b'C' as u16, b'\\' as u16])
1156+
{
1157+
// Convert \\?\UNC\ to \\
1158+
wide.copy_within(8.., 2);
1159+
wide.truncate(wide.len() - (8 - 2));
1160+
}
1161+
return OsString::from_wide(&wide).into();
1162+
}
1163+
}
1164+
path
11431165
}
11441166

11451167
#[cfg(test)]

0 commit comments

Comments
 (0)