Skip to content

Commit b4eef4d

Browse files
authored
Merge pull request #1 from CodaFi/clang-clang-clang-went-the-trolley
Get things building
2 parents 3871ada + 34a8f06 commit b4eef4d

File tree

5 files changed

+165
-18
lines changed

5 files changed

+165
-18
lines changed

.travis.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
env:
2+
global:
3+
- LC_CTYPE=en_US.UTF-8
4+
matrix:
5+
include:
6+
- os: osx
7+
language: objective-c
8+
osx_image: xcode8.2
9+
before_install:
10+
- export PATH=/usr/local/opt/llvm/bin:"${PATH}"
11+
- brew install llvm
12+
- sudo swift utils/make-pkgconfig.swift
13+
script:
14+
- swift test
15+
notifications:
16+
slack:
17+
secure: ek/+U+e44bqP8+QCHojy2LhrN9iwY3N/TNNqNG5FZrp09Vidrd5KXWJOXFxlGrpeWdgTpi089YbEdTfxpcDIudUqDqLwPzS7wePiG2cEC1OT6l3yrhI4AvOe7EsNSOX8gzkuEnmrZVHwLLGe7JeR7JIQKoHMZsBcPYDnO8kRP0Ei3zOh47YUn75SE87egAgZOVBDbZYO3GWRa4WX64s8gaQYQ9a7EoUY0oX9rQ48FJs3rmEIhvIXdcOj9bGX7+o0j7l+IFial/Qh+B6bp4XkZU/tUVP6cuNVI1vxE1weVGCBhgt5wLhXTMewzoE5D1IgMZHVuzIBcDbBthSzQRttLSlYar6xTjXtRtOnb8tqZMWfUj3HBYCFYqtz7PGnZ3IflEVsPJW6tgSsoeB6egjzb8APP9mvhm8+zb1jQG1dqXLWErMjWqhlyPVPmHrxU2w/OLWLAJPY94GVmLnSuOw2pSz41spuEY80JcVVzoRbAOQWrwAujq2S3k93yvKpGq4eaT72Mt8g1CyZesByvzcLk99LEJSpqOIxUqXBd4RwHhay/sq8LllyyqY8ORsxEgwQluOAjEhATO/t/HUsu2ndn1k38U1c4HqXW7FDs1hffYEzZ/PGxciCS6Vt1bfST+iq34pzqpanENQCnX6mSR+D+M7mHlCWdsUihmxEcs5knuM=

Package.pins

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"autoPin": true,
3+
"pins": [
4+
{
5+
"package": "cclang",
6+
"reason": null,
7+
"repositoryURL": "https://github.com/trill-lang/cclang",
8+
"version": "0.0.1"
9+
}
10+
],
11+
"version": 1
12+
}

Sources/Clang/EvalResult.swift

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,56 +3,55 @@ import cclang
33
#endif
44

55
protocol EvalResultKind {
6-
var clang: CXEvalResultKind { get }
6+
var clang: CXEvalResult { get }
77
}
88

99
public struct IntResult: EvalResultKind {
10-
let clang: CXEvalResultKind
10+
let clang: CXEvalResult
1111
public var value: Int {
1212
return Int(clang_EvalResult_getAsInt(clang))
1313
}
1414
}
1515

1616
public struct FloatResult: EvalResultKind {
17-
let clang: CXEvalResultKind
17+
let clang: CXEvalResult
1818
public var value: Double {
19-
return Int(clang_EvalResult_getAsDouble(clang))
19+
return Double(clang_EvalResult_getAsDouble(clang))
2020
}
2121
}
2222

2323
public struct ObjCStrLiteralResult: EvalResultKind {
24-
let clang: CXEvalResultKind
24+
let clang: CXEvalResult
2525
public var value: String {
26-
return String(cString: clang_EvalResult_getAsString(clang))
26+
return String(cString: clang_EvalResult_getAsStr(clang))
2727
}
2828
}
2929

3030
public struct StrLiteralResult: EvalResultKind {
31-
let clang: CXEvalResultKind
31+
let clang: CXEvalResult
3232
public var value: String {
33-
return String(cString: clang_EvalResult_getAsString(clang))
33+
return String(cString: clang_EvalResult_getAsStr(clang))
3434
}
3535
}
3636

3737
public struct CFStrResult: EvalResultKind {
38-
let clang: CXEvalResultKind
38+
let clang: CXEvalResult
3939
public var value: String {
40-
return String(cString: clang_EvalResult_getAsString(clang))
40+
return String(cString: clang_EvalResult_getAsStr(clang))
4141
}
4242
}
4343

4444
public struct OtherResult: EvalResultKind {
45-
let clang: CXEvalResultKind
45+
let clang: CXEvalResult
4646
}
4747

4848
public struct UnExposedResult: EvalResultKind {
49-
let clang: CXEvalResultKind
49+
let clang: CXEvalResult
5050
}
5151

5252
/// Converts a CXEvalResultKind to a EvalResultKind, returning `nil` if it was unsuccessful
53-
func convertEvalResultKind(_ clang: CXEvalResultKind) -> EvalResultKind? {
54-
if <#clang thing is null?#> { return nil }
55-
switch <#Get clang kind#> {
53+
func convertEvalResultKind(_ clang: CXEvalResult) -> EvalResultKind? {
54+
switch clang_EvalResult_getKind(clang) {
5655
case CXEval_Int: return IntResult(clang: clang)
5756
case CXEval_Float: return FloatResult(clang: clang)
5857
case CXEval_ObjCStrLiteral: return ObjCStrLiteralResult(clang: clang)

Sources/Clang/Utilities.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,17 @@ extension CXString {
2121
}
2222

2323
extension Collection where Iterator.Element == String, IndexDistance == Int {
24-
func withUnsafeCStringBuffer<Result>(_ f: (UnsafeMutableBufferPointer<UnsafePointer<Int8>?>) throws -> Result) rethrows -> Result {
24+
func withUnsafeCStringBuffer<Result>(_ f: @escaping (UnsafeMutableBufferPointer<UnsafePointer<Int8>?>) throws -> Result) rethrows -> Result {
2525
let ptr = UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>.allocate(capacity: self.count)
2626
defer { freelist(ptr, count: self.count) }
2727
for (idx, str) in enumerated() {
2828
str.withCString { cStr in
2929
ptr[idx] = strdup(cStr)
3030
}
3131
}
32-
let constPtr = unsafeBitCast(ptr, to: UnsafeMutablePointer<UnsafePointer<Int8>?>.self)
33-
32+
return try ptr.withMemoryRebound(to: Optional<UnsafePointer<Int8>>.self, capacity: self.count) { constPtr in
3433
return try f(UnsafeMutableBufferPointer(start: constPtr, count: self.count))
34+
}
3535
}
3636
}
3737

utils/make-pkgconfig.swift

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#!/usr/bin/env swift
2+
import Foundation
3+
4+
/// Runs the specified program at the provided path.
5+
/// - parameter path: The full path of the executable you
6+
/// wish to run.
7+
/// - parameter args: The arguments you wish to pass to the
8+
/// process.
9+
/// - returns: The standard output of the process, or nil if it was empty.
10+
func run(_ path: String, args: [String] = []) -> String? {
11+
print("Running \(path) \(args.joined(separator: " "))...")
12+
let pipe = Pipe()
13+
let process = Process()
14+
process.launchPath = path
15+
process.arguments = args
16+
process.standardOutput = pipe
17+
process.launch()
18+
process.waitUntilExit()
19+
20+
let data = pipe.fileHandleForReading.readDataToEndOfFile()
21+
guard let result = String(data: data, encoding: .utf8)?
22+
.trimmingCharacters(in: .whitespacesAndNewlines),
23+
!result.isEmpty else { return nil }
24+
return result
25+
}
26+
27+
/// Finds the location of the provided binary on your system.
28+
func which(_ name: String) -> String? {
29+
return run("/usr/bin/which", args: [name])
30+
}
31+
32+
extension String: Error {
33+
/// Replaces all occurrences of characters in the provided set with
34+
/// the provided string.
35+
func replacing(charactersIn characterSet: CharacterSet,
36+
with separator: String) -> String {
37+
let components = self.components(separatedBy: characterSet)
38+
return components.joined(separator: separator)
39+
}
40+
}
41+
42+
func makeFile() throws {
43+
let pkgConfigPath = "/usr/local/lib/pkgconfig"
44+
let pkgConfigDir = URL(fileURLWithPath: pkgConfigPath)
45+
46+
// Make /usr/local/lib/pkgconfig if it doesn't already exist
47+
if !FileManager.default.fileExists(atPath: pkgConfigPath) {
48+
try FileManager.default.createDirectory(at: pkgConfigDir,
49+
withIntermediateDirectories: true)
50+
}
51+
let cllvmPath = pkgConfigDir.appendingPathComponent("cclang.pc")
52+
53+
/// Ensure we have llvm-config in the PATH
54+
guard let llvmConfig = which("llvm-config-3.9") ?? which("llvm-config") else {
55+
throw "Failed to find llvm-config. Ensure llvm-config is installed and " +
56+
"in your PATH"
57+
}
58+
59+
/// Extract the info we need from llvm-config
60+
61+
print("Found llvm-config at \(llvmConfig)...")
62+
63+
let version = run(llvmConfig, args: ["--version"])!
64+
.replacing(charactersIn: .newlines, with: "")
65+
66+
guard version.hasPrefix("3.9") else {
67+
throw "ClangSwift requires LLVM version >=3.9.0, but you have \(version)"
68+
}
69+
70+
let libFlags = [
71+
"-L/usr/local/Cellar/llvm/3.9.1/lib",
72+
"-lclangEdit",
73+
"-lclangFrontendTool",
74+
"-lclang",
75+
"-lclangAST",
76+
"-lclangLex",
77+
"-lclangBasic",
78+
"-lclangDriver",
79+
"-lclangAnalysis",
80+
"-lclangIndex",
81+
"-lclangASTMatchers",
82+
"-lclangSema",
83+
"-lclangParse",
84+
].joined(separator: " ")
85+
86+
let cFlags = "-I/usr/local/Cellar/llvm/3.9.1/include"
87+
// SwiftPM has a whitelisted set of cflags that it understands, and
88+
// unfortunately that includes almost everything but the include dir.
89+
90+
/// Emit the pkg-config file to the path
91+
92+
let s = [
93+
"Name: cclang",
94+
"Description: The llvm library",
95+
"Version: \(version)",
96+
"Libs: \(libFlags)",
97+
"Requires.private:",
98+
"Cflags: \(cFlags)",
99+
].joined(separator: "\n")
100+
101+
print("Writing pkg-config file to \(cllvmPath.path)...")
102+
103+
try s.write(toFile: cllvmPath.path, atomically: true, encoding: .utf8)
104+
105+
print("\nSuccessfully wrote pkg-config file!")
106+
print("Make sure to re-run this script when you update LLVM.")
107+
}
108+
109+
do {
110+
try makeFile()
111+
} catch {
112+
#if os(Linux)
113+
// FIXME: Printing the thrown error that here crashes on Linux.
114+
print("Unexpected error occured while writing the config file. Check permissions and try again.")
115+
#else
116+
print("error: \(error)")
117+
#endif
118+
exit(-1)
119+
}

0 commit comments

Comments
 (0)