Skip to content

Commit 1c90200

Browse files
authored
TSCBasic: rework relative path construction on Windows (swiftlang#298)
When constructing a path relative to a root, compose the final path before canonicalization as the canonicalization may require lookups in the base location. We additionally pay a small penalty to convert the slashes to native separators. This is purely for aesthetic purposes, it ensures that the path is computed initially rather than delayed until use. This in conjunction with swiftlang/swift-package-manager#4237 enables the use of header search paths in SPM which are based in other targets.
1 parent 107e570 commit 1c90200

File tree

1 file changed

+22
-0
lines changed

1 file changed

+22
-0
lines changed

Sources/TSCBasic/Path.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,29 @@ public struct AbsolutePath: Hashable {
7575
if PathImpl(string: str).isAbsolute {
7676
self.init(str)
7777
} else {
78+
#if os(Windows)
79+
var joined: PWSTR!
80+
_ = basePath._impl.string.withCString(encodedAs: UTF16.self) { base in
81+
str.withCString(encodedAs: UTF16.self) { path in
82+
PathAllocCombine(base, path, ULONG(PATHCCH_ALLOW_LONG_PATHS.rawValue), &joined)
83+
}
84+
}
85+
defer { LocalFree(joined) }
86+
87+
let buffer: UnsafePointer<Int8> =
88+
String(decodingCString: joined, as: UTF16.self).fileSystemRepresentation
89+
defer { buffer.deallocate() }
90+
91+
var canonical: PWSTR!
92+
_ = String(cString: buffer).withCString(encodedAs: UTF16.self) {
93+
PathAllocCanonicalize($0, ULONG(PATHCCH_ALLOW_LONG_PATHS.rawValue), &canonical)
94+
}
95+
defer { LocalFree(canonical) }
96+
97+
self.init(String(decodingCString: canonical, as: UTF16.self))
98+
#else
7899
self.init(basePath, RelativePath(str))
100+
#endif
79101
}
80102
}
81103

0 commit comments

Comments
 (0)