Skip to content

Commit 3b17e85

Browse files
authored
Merge pull request #32 from harlanhaskins/pc-on-linux
Added utility for generating a pkg-config file
2 parents 2576d01 + e8e2a8b commit 3b17e85

File tree

2 files changed

+111
-7
lines changed

2 files changed

+111
-7
lines changed

README.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,15 @@ Plus, it provides common wrappers around oft-used types like `Function`, `Global
4444
## Installation
4545

4646
There are a couple, annoying steps you need to get it working before it'll
47-
build. Number one, you'll need a custom `cllvm` pkg-config file, which is
48-
included in the repo. Drop that in `/usr/local/lib/pkgconfig` and make sure
49-
you have LLVM installed through `homebrew`:
50-
51-
```
52-
brew install llvm
53-
```
47+
build.
48+
49+
- Install LLVM 3.9 using your favorite package manager. For example:
50+
- `brew install llvm`
51+
- Ensure `llvm-config` is in your `PATH`
52+
- That will reside in the `/bin` folder wherever your package manager
53+
installed LLVM.
54+
- Create a pkg-config file for your specific LLVM installation.
55+
- We have a utility for this: `swift utils/make-pkgconfig.swift`
5456

5557
Once you do that, you can add LLVMSwift as a dependency for your own Swift
5658
compiler projects!

utils/make-pkgconfig.swift

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
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+
let pipe = Pipe()
12+
let process = Process()
13+
process.launchPath = path
14+
process.arguments = args
15+
process.standardOutput = pipe
16+
process.launch()
17+
process.waitUntilExit()
18+
19+
let data = pipe.fileHandleForReading.readDataToEndOfFile()
20+
guard let result = String(data: data, encoding: .utf8)?
21+
.trimmingCharacters(in: .whitespacesAndNewlines),
22+
!result.isEmpty else { return nil }
23+
return result
24+
}
25+
26+
/// Finds the location of the provided binary on your system.
27+
func which(_ name: String) -> String? {
28+
return run("/usr/bin/which", args: [name])
29+
}
30+
31+
extension String: Error {
32+
/// Replaces all occurrences of characters in the provided set with
33+
/// the provided string.
34+
func replacing(charactersIn characterSet: CharacterSet,
35+
with separator: String) -> String {
36+
let components = self.components(separatedBy: characterSet)
37+
return components.joined(separator: separator)
38+
}
39+
}
40+
41+
func makeFile() throws {
42+
let pkgConfigPath = "/usr/local/lib/pkgconfig"
43+
let pkgConfigDir = URL(fileURLWithPath: pkgConfigPath)
44+
45+
// Make /usr/local/lib/pkgconfig if it doesn't already exist
46+
if !FileManager.default.fileExists(atPath: pkgConfigPath) {
47+
try FileManager.default.createDirectory(at: pkgConfigDir,
48+
withIntermediateDirectories: true)
49+
}
50+
let cllvmPath = pkgConfigDir.appendingPathComponent("cllvm.pc")
51+
52+
/// Ensure we have llvm-config in the PATH
53+
guard let llvmConfig = which("llvm-config") else {
54+
throw "Failed to find llvm-config. Ensure llvm-config is installed and " +
55+
"in your PATH"
56+
}
57+
58+
/// Extract the info we need from llvm-config
59+
60+
print("Found llvm-config at \(llvmConfig)...")
61+
print("Running llvm-config --libs all...")
62+
let ldFlags = run(llvmConfig, args: ["--libs", "all"])!
63+
.replacing(charactersIn: .newlines, with: "")
64+
print("Running llvm-config --version...")
65+
let version = run(llvmConfig, args: ["--version"])!
66+
.replacing(charactersIn: .newlines, with: "")
67+
68+
// SwiftPM has a whitelisted set of cflags that it understands, and
69+
// unfortunately that includes almost everything but the include dir.
70+
71+
print("Running llvm-config --cflags...")
72+
let cFlags = run(llvmConfig, args: ["--cflags"])!
73+
.replacing(charactersIn: .newlines, with: "")
74+
.components(separatedBy: " ")
75+
.filter { $0.hasPrefix("-I") }
76+
.joined(separator: " ")
77+
78+
/// Emit the pkg-config file to the path
79+
80+
let s = [
81+
"Name: cllvm",
82+
"Description: The llvm library",
83+
"Version: \(version)",
84+
"Libs: \(ldFlags)",
85+
"Requires.private:",
86+
"Cflags: \(cFlags)",
87+
].joined(separator: "\n")
88+
89+
print("Writing pkg-config file to \(cllvmPath.path)...")
90+
91+
try s.write(toFile: cllvmPath.path, atomically: true, encoding: .utf8)
92+
93+
print("\nSuccessfully wrote pkg-config file!")
94+
print("Make sure to re-run this script when you update LLVM.")
95+
}
96+
97+
do {
98+
try makeFile()
99+
} catch {
100+
print("error: \(error)")
101+
exit(-1)
102+
}

0 commit comments

Comments
 (0)