Skip to content

Commit

Permalink
Merge pull request #1 from CodaFi/clang-clang-clang-went-the-trolley
Browse files Browse the repository at this point in the history
Get things building
  • Loading branch information
CodaFi authored Feb 16, 2017
2 parents 3871ada + 34a8f06 commit b4eef4d
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 18 deletions.
17 changes: 17 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
env:
global:
- LC_CTYPE=en_US.UTF-8
matrix:
include:
- os: osx
language: objective-c
osx_image: xcode8.2
before_install:
- export PATH=/usr/local/opt/llvm/bin:"${PATH}"
- brew install llvm
- sudo swift utils/make-pkgconfig.swift
script:
- swift test
notifications:
slack:
secure: ek/+U+e44bqP8+QCHojy2LhrN9iwY3N/TNNqNG5FZrp09Vidrd5KXWJOXFxlGrpeWdgTpi089YbEdTfxpcDIudUqDqLwPzS7wePiG2cEC1OT6l3yrhI4AvOe7EsNSOX8gzkuEnmrZVHwLLGe7JeR7JIQKoHMZsBcPYDnO8kRP0Ei3zOh47YUn75SE87egAgZOVBDbZYO3GWRa4WX64s8gaQYQ9a7EoUY0oX9rQ48FJs3rmEIhvIXdcOj9bGX7+o0j7l+IFial/Qh+B6bp4XkZU/tUVP6cuNVI1vxE1weVGCBhgt5wLhXTMewzoE5D1IgMZHVuzIBcDbBthSzQRttLSlYar6xTjXtRtOnb8tqZMWfUj3HBYCFYqtz7PGnZ3IflEVsPJW6tgSsoeB6egjzb8APP9mvhm8+zb1jQG1dqXLWErMjWqhlyPVPmHrxU2w/OLWLAJPY94GVmLnSuOw2pSz41spuEY80JcVVzoRbAOQWrwAujq2S3k93yvKpGq4eaT72Mt8g1CyZesByvzcLk99LEJSpqOIxUqXBd4RwHhay/sq8LllyyqY8ORsxEgwQluOAjEhATO/t/HUsu2ndn1k38U1c4HqXW7FDs1hffYEzZ/PGxciCS6Vt1bfST+iq34pzqpanENQCnX6mSR+D+M7mHlCWdsUihmxEcs5knuM=
12 changes: 12 additions & 0 deletions Package.pins
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"autoPin": true,
"pins": [
{
"package": "cclang",
"reason": null,
"repositoryURL": "https://github.com/trill-lang/cclang",
"version": "0.0.1"
}
],
"version": 1
}
29 changes: 14 additions & 15 deletions Sources/Clang/EvalResult.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,55 @@ import cclang
#endif

protocol EvalResultKind {
var clang: CXEvalResultKind { get }
var clang: CXEvalResult { get }
}

public struct IntResult: EvalResultKind {
let clang: CXEvalResultKind
let clang: CXEvalResult
public var value: Int {
return Int(clang_EvalResult_getAsInt(clang))
}
}

public struct FloatResult: EvalResultKind {
let clang: CXEvalResultKind
let clang: CXEvalResult
public var value: Double {
return Int(clang_EvalResult_getAsDouble(clang))
return Double(clang_EvalResult_getAsDouble(clang))
}
}

public struct ObjCStrLiteralResult: EvalResultKind {
let clang: CXEvalResultKind
let clang: CXEvalResult
public var value: String {
return String(cString: clang_EvalResult_getAsString(clang))
return String(cString: clang_EvalResult_getAsStr(clang))
}
}

public struct StrLiteralResult: EvalResultKind {
let clang: CXEvalResultKind
let clang: CXEvalResult
public var value: String {
return String(cString: clang_EvalResult_getAsString(clang))
return String(cString: clang_EvalResult_getAsStr(clang))
}
}

public struct CFStrResult: EvalResultKind {
let clang: CXEvalResultKind
let clang: CXEvalResult
public var value: String {
return String(cString: clang_EvalResult_getAsString(clang))
return String(cString: clang_EvalResult_getAsStr(clang))
}
}

public struct OtherResult: EvalResultKind {
let clang: CXEvalResultKind
let clang: CXEvalResult
}

public struct UnExposedResult: EvalResultKind {
let clang: CXEvalResultKind
let clang: CXEvalResult
}

/// Converts a CXEvalResultKind to a EvalResultKind, returning `nil` if it was unsuccessful
func convertEvalResultKind(_ clang: CXEvalResultKind) -> EvalResultKind? {
if <#clang thing is null?#> { return nil }
switch <#Get clang kind#> {
func convertEvalResultKind(_ clang: CXEvalResult) -> EvalResultKind? {
switch clang_EvalResult_getKind(clang) {
case CXEval_Int: return IntResult(clang: clang)
case CXEval_Float: return FloatResult(clang: clang)
case CXEval_ObjCStrLiteral: return ObjCStrLiteralResult(clang: clang)
Expand Down
6 changes: 3 additions & 3 deletions Sources/Clang/Utilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@ extension CXString {
}

extension Collection where Iterator.Element == String, IndexDistance == Int {
func withUnsafeCStringBuffer<Result>(_ f: (UnsafeMutableBufferPointer<UnsafePointer<Int8>?>) throws -> Result) rethrows -> Result {
func withUnsafeCStringBuffer<Result>(_ f: @escaping (UnsafeMutableBufferPointer<UnsafePointer<Int8>?>) throws -> Result) rethrows -> Result {
let ptr = UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>.allocate(capacity: self.count)
defer { freelist(ptr, count: self.count) }
for (idx, str) in enumerated() {
str.withCString { cStr in
ptr[idx] = strdup(cStr)
}
}
let constPtr = unsafeBitCast(ptr, to: UnsafeMutablePointer<UnsafePointer<Int8>?>.self)

return try ptr.withMemoryRebound(to: Optional<UnsafePointer<Int8>>.self, capacity: self.count) { constPtr in
return try f(UnsafeMutableBufferPointer(start: constPtr, count: self.count))
}
}
}

Expand Down
119 changes: 119 additions & 0 deletions utils/make-pkgconfig.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#!/usr/bin/env swift
import Foundation

/// Runs the specified program at the provided path.
/// - parameter path: The full path of the executable you
/// wish to run.
/// - parameter args: The arguments you wish to pass to the
/// process.
/// - returns: The standard output of the process, or nil if it was empty.
func run(_ path: String, args: [String] = []) -> String? {
print("Running \(path) \(args.joined(separator: " "))...")
let pipe = Pipe()
let process = Process()
process.launchPath = path
process.arguments = args
process.standardOutput = pipe
process.launch()
process.waitUntilExit()

let data = pipe.fileHandleForReading.readDataToEndOfFile()
guard let result = String(data: data, encoding: .utf8)?
.trimmingCharacters(in: .whitespacesAndNewlines),
!result.isEmpty else { return nil }
return result
}

/// Finds the location of the provided binary on your system.
func which(_ name: String) -> String? {
return run("/usr/bin/which", args: [name])
}

extension String: Error {
/// Replaces all occurrences of characters in the provided set with
/// the provided string.
func replacing(charactersIn characterSet: CharacterSet,
with separator: String) -> String {
let components = self.components(separatedBy: characterSet)
return components.joined(separator: separator)
}
}

func makeFile() throws {
let pkgConfigPath = "/usr/local/lib/pkgconfig"
let pkgConfigDir = URL(fileURLWithPath: pkgConfigPath)

// Make /usr/local/lib/pkgconfig if it doesn't already exist
if !FileManager.default.fileExists(atPath: pkgConfigPath) {
try FileManager.default.createDirectory(at: pkgConfigDir,
withIntermediateDirectories: true)
}
let cllvmPath = pkgConfigDir.appendingPathComponent("cclang.pc")

/// Ensure we have llvm-config in the PATH
guard let llvmConfig = which("llvm-config-3.9") ?? which("llvm-config") else {
throw "Failed to find llvm-config. Ensure llvm-config is installed and " +
"in your PATH"
}

/// Extract the info we need from llvm-config

print("Found llvm-config at \(llvmConfig)...")

let version = run(llvmConfig, args: ["--version"])!
.replacing(charactersIn: .newlines, with: "")

guard version.hasPrefix("3.9") else {
throw "ClangSwift requires LLVM version >=3.9.0, but you have \(version)"
}

let libFlags = [
"-L/usr/local/Cellar/llvm/3.9.1/lib",
"-lclangEdit",
"-lclangFrontendTool",
"-lclang",
"-lclangAST",
"-lclangLex",
"-lclangBasic",
"-lclangDriver",
"-lclangAnalysis",
"-lclangIndex",
"-lclangASTMatchers",
"-lclangSema",
"-lclangParse",
].joined(separator: " ")

let cFlags = "-I/usr/local/Cellar/llvm/3.9.1/include"
// SwiftPM has a whitelisted set of cflags that it understands, and
// unfortunately that includes almost everything but the include dir.

/// Emit the pkg-config file to the path

let s = [
"Name: cclang",
"Description: The llvm library",
"Version: \(version)",
"Libs: \(libFlags)",
"Requires.private:",
"Cflags: \(cFlags)",
].joined(separator: "\n")

print("Writing pkg-config file to \(cllvmPath.path)...")

try s.write(toFile: cllvmPath.path, atomically: true, encoding: .utf8)

print("\nSuccessfully wrote pkg-config file!")
print("Make sure to re-run this script when you update LLVM.")
}

do {
try makeFile()
} catch {
#if os(Linux)
// FIXME: Printing the thrown error that here crashes on Linux.
print("Unexpected error occured while writing the config file. Check permissions and try again.")
#else
print("error: \(error)")
#endif
exit(-1)
}

0 comments on commit b4eef4d

Please sign in to comment.