Skip to content
4 changes: 2 additions & 2 deletions Source/SourceKittenFramework/Module.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public struct Module {
return nodeModuleName == spmName
}
let inputs = node["inputs"]?.array(of: String.self) ?? []
return inputs.allSatisfy({ !$0.contains(".build/checkouts/") }) && !nodeModuleName.hasSuffix("Tests")
return inputs.allSatisfy({ !$0.contains(".build\\checkouts\\") }) && !nodeModuleName.hasSuffix("Tests")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return inputs.allSatisfy({ !$0.contains(".build\\checkouts\\") }) && !nodeModuleName.hasSuffix("Tests")
#if os(Windows)
let checkoutsPath = #".build\checkouts\"#
#else
let checkoutsPath = ".build/checkouts/"
#endif
return inputs.allSatisfy({ !$0.contains(checkoutsPath) }) && !nodeModuleName.hasSuffix("Tests")

}

guard let moduleCommand = commands.first(where: matchModuleName) else {
Expand Down Expand Up @@ -92,7 +92,7 @@ public struct Module {
*/
public init?(spmArguments: [String], spmName: String? = nil, inPath path: String = FileManager.default.currentDirectoryPath) {
fputs("Running swift build\n", stderr)
let buildResults = Exec.run("/usr/bin/env", ["swift", "build"] + spmArguments, currentDirectory: path, stderr: .merge)
let buildResults = Exec.run("C:\\Library\\Developer\\Toolchains\\unknown-Asserts-development.xctoolchain\\usr\\bin\\swift.exe", ["build"] + spmArguments, currentDirectory: path, stderr: .merge)
guard buildResults.terminationStatus == 0 else {
let file = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("swift-build-\(UUID().uuidString).log")
_ = try? buildResults.data.write(to: file)
Expand Down
64 changes: 63 additions & 1 deletion Source/SourceKittenFramework/library_wrapper.swift
Original file line number Diff line number Diff line change
@@ -1,16 +1,62 @@
import Foundation
#if os(Windows)
import WinSDK

@_transparent
internal func MAKELANGID(_ p: WORD, _ s: WORD) -> DWORD {
return DWORD((s << 10) | p)
}

struct WindowsError {
public let code: DWORD
}

extension WindowsError: CustomStringConvertible {
public var description: String {
let dwFlags: DWORD = DWORD(FORMAT_MESSAGE_ALLOCATE_BUFFER)
| DWORD(FORMAT_MESSAGE_FROM_SYSTEM)
| DWORD(FORMAT_MESSAGE_IGNORE_INSERTS)
let dwLanguageId: DWORD =
MAKELANGID(WORD(LANG_NEUTRAL), WORD(SUBLANG_DEFAULT))

var buffer: UnsafeMutablePointer<WCHAR>?
let dwResult = withUnsafeMutablePointer(to: &buffer) {
$0.withMemoryRebound(to: WCHAR.self, capacity: 2) {
FormatMessageW(dwFlags, nil, code, dwLanguageId, $0, 0, nil)
}
}
guard dwResult > 0, let message = buffer else { return "Unknown error" }
defer { LocalFree(message) }
return String(decodingCString: message, as: UTF16.self)
}
}
#endif

// MARK: - Shared Types & Functions

struct DynamicLinkLibrary {
fileprivate let handle: UnsafeMutableRawPointer
#if os(Windows)
typealias HandleType = HMODULE?
#else
typealias HandleType = UnsafeMutableRawPointer
#endif

fileprivate let handle: HandleType

func load<T>(symbol: String) -> T {
#if os(Windows)
if let sym = GetProcAddress(handle, symbol) {
return unsafeBitCast(sym, to: T.self)
}
let error = WindowsError(code: GetLastError())
fatalError("Finding symbol \(symbol) failed: \(error)")
#else
if let sym = dlsym(handle, symbol) {
return unsafeBitCast(sym, to: T.self)
}
let errorString = String(validatingUTF8: dlerror())
fatalError("Finding symbol \(symbol) failed: \(errorString ?? "unknown error")")
#endif
}
}

Expand All @@ -23,9 +69,15 @@ struct Loader {
// try all fullPaths that contains target file,
// then try loading with simple path that depends resolving to DYLD
for fullPath in fullPaths + [path] {
#if os(Windows)
if let handle = fullPath.withCString(encodedAs: UTF16.self, LoadLibraryW) {
return DynamicLinkLibrary(handle: handle)
}
#else
if let handle = dlopen(fullPath, RTLD_LAZY) {
return DynamicLinkLibrary(handle: handle)
}
#endif
}

fatalError("Loading \(path) failed")
Expand Down Expand Up @@ -101,6 +153,16 @@ let toolchainLoader = Loader(searchPaths: [
linuxDefaultLibPath
].compactMap({ $0 }))

#elseif os(Windows)

// MARK: - Windows

let toolchainLoader = Loader(searchPaths: [
"C:\\Library\\Developer\\Toolchains\\unknown-Asserts-development.xctoolchain\\usr\\bin",
].compactMap {
FileManager.default.fileExists(atPath: $0) ? $0 : nil
})

#else

// MARK: - Darwin
Expand Down
10 changes: 8 additions & 2 deletions Tests/SourceKittenFrameworkTests/ClangTranslationUnitTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,14 @@ class ClangTranslationUnitTests: XCTestCase {
}

private func compare(clangFixture fixture: String) {
let unit = ClangTranslationUnit(headerFiles: [fixturesDirectory + fixture + ".h"],
compilerArguments: ["-x", "objective-c", "-isysroot", sdkPath(), "-I", fixturesDirectory])
let path = URL(fileURLWithPath: fixturesDirectory + fixture + ".h")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pattern is used a lot now: URL(fileURLWithPath: ...).standardizedFileURL.withUnsafeFileSystemRepresentation { String(cString: $0!) }

Can you add some sort of shared helper for this? Open to API design ideas, but as a strawman: FileUtils.unsafeSystemPath(for path: String) -> String

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that the unsafeSystemPath makes sense, perhaps FileUtils.nativePathRepresentation? The withUnsafeFileSystemRepresentation is because the closure receives a UnsafePointer<CChar>, but we are transacting in String at this layer.

.standardizedFileURL
.withUnsafeFileSystemRepresentation { String(cString: $0!) }
let includes = URL(fileURLWithPath: fixturesDirectory)
.standardizedFileURL
.withUnsafeFileSystemRepresentation { String(cString: $0!) }
let unit = ClangTranslationUnit(headerFiles: [path],
compilerArguments: ["-x", "objective-c", "-isysroot", sdkPath(), "-I", includes])
compareJSONString(withFixtureNamed: (fixture as NSString).lastPathComponent, jsonString: unit)
}

Expand Down
18 changes: 18 additions & 0 deletions Tests/SourceKittenFrameworkTests/Fixtures/[email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"key.annotated_decl" : "<Declaration>struct DocumentedStruct<\/Declaration>",
"key.column" : 8,
"key.decl_lang" : "source.lang.swift",
"key.doc.full_as_xml" : "<Class file=\"DocInfo.swift\" line=\"28\" column=\"8\"><Name>DocumentedStruct<\/Name><USR>s:7DocInfo16DocumentedStructV<\/USR><Declaration>struct DocumentedStruct<\/Declaration><CommentParts><Abstract><Para>A documented struct<\/Para><\/Abstract><\/CommentParts><\/Class>",
"key.filepath" : "DocInfo.swift",
"key.fully_annotated_decl" : "<decl.struct><syntaxtype.keyword>struct<\/syntaxtype.keyword> <decl.name>DocumentedStruct<\/decl.name><\/decl.struct>",
"key.kind" : "source.lang.swift.decl.struct",
"key.length" : 16,
"key.line" : 28,
"key.modulename" : "DocInfo",
"key.name" : "DocumentedStruct",
"key.offset" : 416,
"key.reusingastcontext" : false,
"key.typename" : "DocumentedStruct.Type",
"key.typeusr" : "$s7DocInfo16DocumentedStructVmD",
"key.usr" : "s:7DocInfo16DocumentedStructV"
}
Loading