Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,15 @@ Plus, it provides common wrappers around oft-used types like `Function`, `Global
## Installation

There are a couple, annoying steps you need to get it working before it'll
build. Number one, you'll need a custom `cllvm` pkg-config file, which is
included in the repo. Drop that in `/usr/local/lib/pkgconfig` and make sure
you have LLVM installed through `homebrew`:

```
brew install llvm
```
build.

- Install LLVM 3.9 using your favorite package manager. For example:
- `brew install llvm`
- Ensure `llvm-config` is in your `PATH`
- That will reside in the `/bin` folder wherever your package manager
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this is all that helpful, users don't really need to know this location to build. Maybe mention invoking which llvm-config or something.

Copy link
Member Author

Choose a reason for hiding this comment

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

It helped me because it didn't end up in my path after installing from homebrew :sad:

Copy link
Member

Choose a reason for hiding this comment

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

Oh, I see. Carry on.

installed LLVM.
- Create a pkg-config file for your specific LLVM installation.
- We have a utility for this: `swift utils/make-pkgconfig.swift`

Once you do that, you can add LLVMSwift as a dependency for your own Swift
compiler projects!
Expand Down
102 changes: 102 additions & 0 deletions utils/make-pkgconfig.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/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? {
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("cllvm.pc")

/// Ensure we have llvm-config in the PATH
guard let llvmConfig = 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)...")
print("Running llvm-config --libs all...")
let ldFlags = run(llvmConfig, args: ["--libs", "all"])!
.replacing(charactersIn: .newlines, with: "")
print("Running llvm-config --version...")
let version = run(llvmConfig, args: ["--version"])!
.replacing(charactersIn: .newlines, with: "")

// SwiftPM has a whitelisted set of cflags that it understands, and
// unfortunately that includes almost everything but the include dir.

print("Running llvm-config --cflags...")
let cFlags = run(llvmConfig, args: ["--cflags"])!
.replacing(charactersIn: .newlines, with: "")
.components(separatedBy: " ")
.filter { $0.hasPrefix("-I") }
.joined(separator: " ")

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

let s = [
"Name: cllvm",
"Description: The llvm library",
"Version: \(version)",
"Libs: \(ldFlags)",
"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 {
print("error: \(error)")
exit(-1)
}