From e400a2edadadbe8ee03b74f7f508f37078aa6a5a Mon Sep 17 00:00:00 2001 From: Harlan Haskins Date: Sat, 14 Jan 2017 15:29:01 -0500 Subject: [PATCH 1/3] Added utility for generating a pkg-config file --- utils/make-pkgconfig.swift | 97 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 utils/make-pkgconfig.swift diff --git a/utils/make-pkgconfig.swift b/utils/make-pkgconfig.swift new file mode 100644 index 00000000..ff8f6eff --- /dev/null +++ b/utils/make-pkgconfig.swift @@ -0,0 +1,97 @@ +#!/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") + + try s.write(toFile: cllvmPath.path, atomically: true, encoding: .utf8) +} + +do { + try makeFile() +} catch { + print("error: \(error)") + exit(-1) +} From e5ee180b08c687ff3c319c019d322cdbc876dfff Mon Sep 17 00:00:00 2001 From: Harlan Haskins Date: Sat, 14 Jan 2017 15:32:50 -0500 Subject: [PATCH 2/3] Added more logging --- utils/make-pkgconfig.swift | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/utils/make-pkgconfig.swift b/utils/make-pkgconfig.swift index ff8f6eff..95c62772 100644 --- a/utils/make-pkgconfig.swift +++ b/utils/make-pkgconfig.swift @@ -58,17 +58,17 @@ func makeFile() throws { /// Extract the info we need from llvm-config print("Found llvm-config at \(llvmConfig)...") - print("Running llvm-config --libs all") + print("Running llvm-config --libs all...") let ldFlags = run(llvmConfig, args: ["--libs", "all"])! .replacing(charactersIn: .newlines, with: "") - print("Running llvm-config --version") + 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") + print("Running llvm-config --cflags...") let cFlags = run(llvmConfig, args: ["--cflags"])! .replacing(charactersIn: .newlines, with: "") .components(separatedBy: " ") @@ -86,7 +86,12 @@ func makeFile() throws { "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 { From e8e2a8bdef91c173b91b6fcfbe5d67074c852a75 Mon Sep 17 00:00:00 2001 From: Harlan Haskins Date: Sat, 14 Jan 2017 15:47:55 -0500 Subject: [PATCH 3/3] Added build instructions to README --- README.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 389333fb..95667718 100644 --- a/README.md +++ b/README.md @@ -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 + 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!