-
Notifications
You must be signed in to change notification settings - Fork 226
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #178 from jpsim/nn-swift-test
Runtime linking of Clang & SourceKit, codegen & update to latest Swift snapshot
- Loading branch information
Showing
69 changed files
with
646 additions
and
205 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
// | ||
// library_wrapper.swift | ||
// sourcekitten | ||
// | ||
// Created by Norio Nomura on 2/20/16. | ||
// Copyright © 2016 SourceKitten. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
struct DynamicLinkLibrary { | ||
let path: String | ||
let handle: UnsafeMutablePointer<Void> | ||
|
||
func loadSymbol<T>(symbol: String) -> T { | ||
let sym = Darwin.dlsym(handle, symbol) | ||
if sym == nil { | ||
let errorString = String(UTF8String: dlerror()) | ||
fatalError("Finding symbol \(symbol) failed: \(errorString)") | ||
} | ||
return unsafeBitCast(sym, T.self) | ||
} | ||
} | ||
|
||
let toolchainLoader = Loader(searchPaths: [ | ||
xcodeDefaultToolchainOverride, | ||
toolchainDir, | ||
xcodeSelectPath?.toolchainDir, | ||
/* | ||
These search paths are used when `xcode-select -p` points to | ||
"Command Line Tools OS X for Xcode", but Xcode.app exists. | ||
*/ | ||
applicationsDir?.xcodeDeveloperDir.toolchainDir, | ||
applicationsDir?.xcodeBetaDeveloperDir.toolchainDir, | ||
userApplicationsDir?.xcodeDeveloperDir.toolchainDir, | ||
userApplicationsDir?.xcodeBetaDeveloperDir.toolchainDir, | ||
].flatMap { path in | ||
if let fullPath = path?.usrLibDir where fullPath.isFile { | ||
return fullPath | ||
} | ||
return nil | ||
}) | ||
|
||
struct Loader { | ||
let searchPaths: [String] | ||
|
||
func load(path: String) -> DynamicLinkLibrary { | ||
let fullPaths = searchPaths.map { $0.stringByAppendingPathComponent(path) }.filter { $0.isFile } | ||
|
||
// try all fullPaths that contains target file, | ||
// then try loading with simple path that depends resolving to DYLD | ||
for fullPath in fullPaths + [path] { | ||
let handle = dlopen(fullPath, RTLD_LAZY) | ||
if handle != nil { | ||
return DynamicLinkLibrary(path: path, handle: handle) | ||
} | ||
} | ||
|
||
fatalError("Loading \(path) failed") | ||
} | ||
} | ||
|
||
/// Returns "XCODE_DEFAULT_TOOLCHAIN_OVERRIDE" environment variable | ||
/// | ||
/// `launch-with-toolchain` sets the toolchain path to the | ||
/// "XCODE_DEFAULT_TOOLCHAIN_OVERRIDE" environment variable. | ||
private let xcodeDefaultToolchainOverride: String? = | ||
NSProcessInfo.processInfo().environment["XCODE_DEFAULT_TOOLCHAIN_OVERRIDE"] | ||
|
||
/// Returns "TOOLCHAIN_DIR" environment variable | ||
/// | ||
/// `Xcode`/`xcodebuild` sets the toolchain path to the | ||
/// "TOOLCHAIN_DIR" environment variable. | ||
private let toolchainDir: String? = | ||
NSProcessInfo.processInfo().environment["TOOLCHAIN_DIR"] | ||
|
||
/// Returns result string of `xcode-select -p` | ||
private let xcodeSelectPath: String? = { | ||
let pathOfXcodeSelect = "/usr/bin/xcode-select" | ||
|
||
if !NSFileManager.defaultManager().isExecutableFileAtPath(pathOfXcodeSelect) { | ||
return nil | ||
} | ||
|
||
let task = NSTask() | ||
task.launchPath = pathOfXcodeSelect | ||
task.arguments = ["-p"] | ||
|
||
let pipe = NSPipe() | ||
task.standardOutput = pipe | ||
task.launch() // if xcode-select does not exist, crash with `NSInvalidArgumentException`. | ||
|
||
let data = pipe.fileHandleForReading.readDataToEndOfFile() | ||
guard let output = String(data: data, encoding: NSUTF8StringEncoding) else { | ||
return nil | ||
} | ||
|
||
var start = output.startIndex | ||
var contentsEnd = output.startIndex | ||
output.getLineStart(&start, end: nil, contentsEnd: &contentsEnd, forRange: start..<start) | ||
let xcodeSelectPath = output.substringWithRange(start..<contentsEnd) | ||
// Return nil if xcodeSelectPath points to "Command Line Tools OS X for Xcode" | ||
// because it doesn't contain `sourcekitd.framework`. | ||
if xcodeSelectPath == "/Library/Developer/CommandLineTools" { | ||
return nil | ||
} | ||
return xcodeSelectPath | ||
}() | ||
|
||
private let applicationsDir: String? = | ||
NSSearchPathForDirectoriesInDomains(.ApplicationDirectory, .SystemDomainMask, true).first | ||
|
||
private let userApplicationsDir: String? = | ||
NSSearchPathForDirectoriesInDomains(.ApplicationDirectory, .UserDomainMask, true).first | ||
|
||
private extension String { | ||
private var isFile: Bool { | ||
return NSFileManager.defaultManager().fileExistsAtPath(self) | ||
} | ||
|
||
private var toolchainDir: String { | ||
return stringByAppendingPathComponent("Toolchains/XcodeDefault.xctoolchain") | ||
} | ||
|
||
private var xcodeDeveloperDir: String { | ||
return stringByAppendingPathComponent("Xcode.app/Contents/Developer") | ||
} | ||
|
||
private var xcodeBetaDeveloperDir: String { | ||
return stringByAppendingPathComponent("Xcode-beta.app/Contents/Developer") | ||
} | ||
|
||
private var usrLibDir: String { | ||
return stringByAppendingPathComponent("/usr/lib") | ||
} | ||
|
||
private func stringByAppendingPathComponent(str: String) -> String { | ||
return (self as NSString).stringByAppendingPathComponent(str) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#if SWIFT_PACKAGE | ||
import Clang_C | ||
#endif | ||
private let library = toolchainLoader.load("libclang.dylib") | ||
internal let clang_getCString: @convention(c) (CXString) -> (UnsafePointer<Int8>) = library.loadSymbol("clang_getCString") | ||
internal let clang_disposeString: @convention(c) (CXString) -> () = library.loadSymbol("clang_disposeString") |
38 changes: 38 additions & 0 deletions
38
Source/SourceKittenFramework/library_wrapper_Documentation.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#if SWIFT_PACKAGE | ||
import Clang_C | ||
#endif | ||
private let library = toolchainLoader.load("libclang.dylib") | ||
internal let clang_Cursor_getParsedComment: @convention(c) (CXCursor) -> (CXComment) = library.loadSymbol("clang_Cursor_getParsedComment") | ||
internal let clang_Comment_getKind: @convention(c) (CXComment) -> (CXCommentKind) = library.loadSymbol("clang_Comment_getKind") | ||
internal let clang_Comment_getNumChildren: @convention(c) (CXComment) -> (UInt32) = library.loadSymbol("clang_Comment_getNumChildren") | ||
internal let clang_Comment_getChild: @convention(c) (CXComment, UInt32) -> (CXComment) = library.loadSymbol("clang_Comment_getChild") | ||
internal let clang_Comment_isWhitespace: @convention(c) (CXComment) -> (UInt32) = library.loadSymbol("clang_Comment_isWhitespace") | ||
internal let clang_InlineContentComment_hasTrailingNewline: @convention(c) (CXComment) -> (UInt32) = library.loadSymbol("clang_InlineContentComment_hasTrailingNewline") | ||
internal let clang_TextComment_getText: @convention(c) (CXComment) -> (CXString) = library.loadSymbol("clang_TextComment_getText") | ||
internal let clang_InlineCommandComment_getCommandName: @convention(c) (CXComment) -> (CXString) = library.loadSymbol("clang_InlineCommandComment_getCommandName") | ||
internal let clang_InlineCommandComment_getRenderKind: @convention(c) (CXComment) -> (CXCommentInlineCommandRenderKind) = library.loadSymbol("clang_InlineCommandComment_getRenderKind") | ||
internal let clang_InlineCommandComment_getNumArgs: @convention(c) (CXComment) -> (UInt32) = library.loadSymbol("clang_InlineCommandComment_getNumArgs") | ||
internal let clang_InlineCommandComment_getArgText: @convention(c) (CXComment, UInt32) -> (CXString) = library.loadSymbol("clang_InlineCommandComment_getArgText") | ||
internal let clang_HTMLTagComment_getTagName: @convention(c) (CXComment) -> (CXString) = library.loadSymbol("clang_HTMLTagComment_getTagName") | ||
internal let clang_HTMLStartTagComment_isSelfClosing: @convention(c) (CXComment) -> (UInt32) = library.loadSymbol("clang_HTMLStartTagComment_isSelfClosing") | ||
internal let clang_HTMLStartTag_getNumAttrs: @convention(c) (CXComment) -> (UInt32) = library.loadSymbol("clang_HTMLStartTag_getNumAttrs") | ||
internal let clang_HTMLStartTag_getAttrName: @convention(c) (CXComment, UInt32) -> (CXString) = library.loadSymbol("clang_HTMLStartTag_getAttrName") | ||
internal let clang_HTMLStartTag_getAttrValue: @convention(c) (CXComment, UInt32) -> (CXString) = library.loadSymbol("clang_HTMLStartTag_getAttrValue") | ||
internal let clang_BlockCommandComment_getCommandName: @convention(c) (CXComment) -> (CXString) = library.loadSymbol("clang_BlockCommandComment_getCommandName") | ||
internal let clang_BlockCommandComment_getNumArgs: @convention(c) (CXComment) -> (UInt32) = library.loadSymbol("clang_BlockCommandComment_getNumArgs") | ||
internal let clang_BlockCommandComment_getArgText: @convention(c) (CXComment, UInt32) -> (CXString) = library.loadSymbol("clang_BlockCommandComment_getArgText") | ||
internal let clang_BlockCommandComment_getParagraph: @convention(c) (CXComment) -> (CXComment) = library.loadSymbol("clang_BlockCommandComment_getParagraph") | ||
internal let clang_ParamCommandComment_getParamName: @convention(c) (CXComment) -> (CXString) = library.loadSymbol("clang_ParamCommandComment_getParamName") | ||
internal let clang_ParamCommandComment_isParamIndexValid: @convention(c) (CXComment) -> (UInt32) = library.loadSymbol("clang_ParamCommandComment_isParamIndexValid") | ||
internal let clang_ParamCommandComment_getParamIndex: @convention(c) (CXComment) -> (UInt32) = library.loadSymbol("clang_ParamCommandComment_getParamIndex") | ||
internal let clang_ParamCommandComment_isDirectionExplicit: @convention(c) (CXComment) -> (UInt32) = library.loadSymbol("clang_ParamCommandComment_isDirectionExplicit") | ||
internal let clang_ParamCommandComment_getDirection: @convention(c) (CXComment) -> (CXCommentParamPassDirection) = library.loadSymbol("clang_ParamCommandComment_getDirection") | ||
internal let clang_TParamCommandComment_getParamName: @convention(c) (CXComment) -> (CXString) = library.loadSymbol("clang_TParamCommandComment_getParamName") | ||
internal let clang_TParamCommandComment_isParamPositionValid: @convention(c) (CXComment) -> (UInt32) = library.loadSymbol("clang_TParamCommandComment_isParamPositionValid") | ||
internal let clang_TParamCommandComment_getDepth: @convention(c) (CXComment) -> (UInt32) = library.loadSymbol("clang_TParamCommandComment_getDepth") | ||
internal let clang_TParamCommandComment_getIndex: @convention(c) (CXComment, UInt32) -> (UInt32) = library.loadSymbol("clang_TParamCommandComment_getIndex") | ||
internal let clang_VerbatimBlockLineComment_getText: @convention(c) (CXComment) -> (CXString) = library.loadSymbol("clang_VerbatimBlockLineComment_getText") | ||
internal let clang_VerbatimLineComment_getText: @convention(c) (CXComment) -> (CXString) = library.loadSymbol("clang_VerbatimLineComment_getText") | ||
internal let clang_HTMLTagComment_getAsString: @convention(c) (CXComment) -> (CXString) = library.loadSymbol("clang_HTMLTagComment_getAsString") | ||
internal let clang_FullComment_getAsHTML: @convention(c) (CXComment) -> (CXString) = library.loadSymbol("clang_FullComment_getAsHTML") | ||
internal let clang_FullComment_getAsXML: @convention(c) (CXComment) -> (CXString) = library.loadSymbol("clang_FullComment_getAsXML") |
Oops, something went wrong.