Skip to content

Commit 899f26d

Browse files
authored
Revert canonicalizing the build directory and make the path absolute instead (#267)
Rather than canonicalising the build directory this simply makes it absolute. Unfortunately the current MSRV doesn't allow us to use `std::path::absolute` so for Windows I've added a direct call to the Windows API. Since the motivation for #200 is Windows, on non-Windows platforms this is now a no-op. Fixes cloudflare/boring#414
1 parent b8fb301 commit 899f26d

File tree

1 file changed

+48
-26
lines changed

1 file changed

+48
-26
lines changed

src/lib.rs

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,7 @@ impl Config {
555555
.clone()
556556
.unwrap_or_else(|| PathBuf::from(getenv_unwrap("OUT_DIR")));
557557

558-
let build_dir = try_canonicalize(&dst.join("build"));
558+
let build_dir = fix_build_dir(&dst.join("build"));
559559

560560
self.maybe_clear(&build_dir);
561561
let _ = fs::create_dir_all(&build_dir);
@@ -1004,7 +1004,10 @@ impl Config {
10041004
// CMake will apparently store canonicalized paths which normally
10051005
// isn't relevant to us but we canonicalize it here to ensure
10061006
// we're both checking the same thing.
1007-
let path = try_canonicalize(&self.path);
1007+
let path = self
1008+
.path
1009+
.canonicalize()
1010+
.unwrap_or_else(|_| self.path.to_owned());
10081011

10091012
let mut f = match File::open(dir.join("CMakeCache.txt")) {
10101013
Ok(f) => f,
@@ -1139,32 +1142,51 @@ fn uses_named_pipe_jobserver(makeflags: &OsStr) -> bool {
11391142
.contains("--jobserver-auth=fifo:")
11401143
}
11411144

1142-
/// Attempt to canonicalize; fall back to the original path if unsuccessful, in case `cmake` knows
1143-
/// something we don't.
1144-
fn try_canonicalize(path: &Path) -> PathBuf {
1145-
let path = path.canonicalize().unwrap_or_else(|_| path.to_owned());
1146-
// On Windows, attempt to remove the verbatim prefix from the canonicalized path.
1147-
// FIXME(ChrisDenton): once MSRV is >=1.79 use `std::path::absolute` instead of canonicalize.
1148-
// That will avoid the need for this hack.
1149-
#[cfg(windows)]
1150-
{
1151-
use std::os::windows::ffi::{OsStrExt, OsStringExt};
1152-
let mut wide: Vec<u16> = path.as_os_str().encode_wide().collect();
1153-
if wide.starts_with(&[b'\\' as u16, b'\\' as u16, b'?' as u16, b'\\' as u16]) {
1154-
if wide.get(5..7) == Some(&[b':' as u16, b'\\' as u16]) {
1155-
// Convert \\?\C:\ to C:\
1156-
wide.copy_within(4.., 0);
1157-
wide.truncate(wide.len() - 4);
1158-
} else if wide.get(4..8) == Some(&[b'U' as u16, b'N' as u16, b'C' as u16, b'\\' as u16])
1159-
{
1160-
// Convert \\?\UNC\ to \\
1161-
wide.copy_within(8.., 2);
1162-
wide.truncate(wide.len() - (8 - 2));
1163-
}
1164-
return OsString::from_wide(&wide).into();
1145+
#[cfg(not(windows))]
1146+
fn fix_build_dir(path: &Path) -> PathBuf {
1147+
path.into()
1148+
}
1149+
1150+
// Change relative paths to absolute to workaround #200 where
1151+
// some flavors of CMake on Windows otherwise fail with
1152+
// `error MSB1009: Project file does not exist`
1153+
#[cfg(windows)]
1154+
fn fix_build_dir(path: &Path) -> PathBuf {
1155+
use std::os::windows::ffi::{OsStrExt, OsStringExt};
1156+
use std::ptr::null_mut;
1157+
if path.is_absolute() {
1158+
return path.into();
1159+
}
1160+
#[link(name = "kernel32", kind = "raw-dylib")]
1161+
extern "system" {
1162+
fn GetFullPathNameW(
1163+
lpfilename: *const u16,
1164+
nbufferlength: u32,
1165+
lpbuffer: *mut u16,
1166+
lpfilepart: *mut *mut u16,
1167+
) -> u32;
1168+
}
1169+
1170+
// FIXME(ChrisDenton): once MSRV is >=1.79 use `std::path::absolute` instead of this.
1171+
let path_utf16: Vec<u16> = path.as_os_str().encode_wide().chain([0]).collect();
1172+
unsafe {
1173+
// Calling `GetFullPathNameW` with a buffer of length zero will return the necessary buffer size.
1174+
let expected_len = GetFullPathNameW(path_utf16.as_ptr(), 0, null_mut(), null_mut());
1175+
let mut buffer = vec![0; expected_len as usize];
1176+
let len = GetFullPathNameW(
1177+
path_utf16.as_ptr(),
1178+
expected_len,
1179+
buffer.as_mut_ptr(),
1180+
null_mut(),
1181+
) as usize;
1182+
if len == 0 || len > buffer.len() {
1183+
// Failed to get the absolute path. Fallback to using the original path.
1184+
return path.into();
11651185
}
1186+
// If successful then `len` will be the length of the path that was written to the buffer.
1187+
buffer.truncate(len);
1188+
OsString::from_wide(&buffer).into()
11661189
}
1167-
path
11681190
}
11691191

11701192
#[cfg(windows)]

0 commit comments

Comments
 (0)