22// The swift-tools-version declares the minimum version of Swift required to build this package.
33
44import PackageDescription
5+ import Foundation
6+
7+ let ( cFlags, linkFlags) = try ! getLLVMConfig ( )
58
69let package = Package (
710 name: " llvm-api " ,
@@ -11,17 +14,76 @@ let package = Package(
1114 targets: [
1215 . systemLibrary(
1316 name: " CLLVM " ,
14- path: " llvm-api/CLLVM " ,
15- pkgConfig: " CLLVM " ,
16- providers: [
17- . brew( [ " llvm " ] ) ,
18- ]
17+ path: " llvm-api/CLLVM "
1918 ) ,
2019 . target(
2120 name: " LLVM " ,
2221 dependencies: [ " CLLVM " ] ,
23- path: " llvm-api/LLVM "
22+ path: " llvm-api/LLVM " ,
23+ cSettings: [
24+ . unsafeFlags( cFlags)
25+ ] ,
26+ linkerSettings: [
27+ . unsafeFlags( linkFlags)
28+ ]
2429 ) ,
25- ] ,
26- cxxLanguageStandard: . cxx20
30+ ]
2731)
32+
33+ /// Get LLVM config flags
34+ func getLLVMConfig( ) throws -> ( [ String ] , [ String ] ) {
35+ let brewPrefix = {
36+ guard let brew = which ( " brew " ) else { return nil }
37+ return run ( brew, args: [ " --prefix " ] )
38+ } ( ) ?? " /usr/local "
39+ /// Ensure we have llvm-config in the PATH
40+ guard let llvmConfig = which ( " llvm-config " ) ?? which ( " \( brewPrefix) /opt/llvm/bin/llvm-config " ) else {
41+ throw " Failed to find llvm-config. Ensure llvm-config is installed and in your PATH "
42+ }
43+ // Get linkage (LD) flags
44+ let ldFlags = run ( llvmConfig, args: [ " --ldflags " , " --libs " , " all " , " --system-libs " ] ) !
45+ . replacing ( charactersIn: . newlines, with: " " )
46+ . components ( separatedBy: " " )
47+ . filter { !$0. hasPrefix ( " -W " ) }
48+ // Get C flags
49+ let cFlags = run ( llvmConfig, args: [ " --cflags " ] ) !
50+ . replacing ( charactersIn: . newlines, with: " " )
51+ . components ( separatedBy: " " )
52+ . filter { $0. hasPrefix ( " -I " ) }
53+ return ( cFlags, ldFlags)
54+ }
55+
56+ /// Runs the specified program at the provided path.
57+ /// - parameter path: The full path of the executable you wish to run.
58+ /// - parameter args: The arguments you wish to pass to the process.
59+ /// - returns: The standard output of the process, or nil if it was empty.
60+ func run( _ path: String , args: [ String ] = [ ] ) -> String ? {
61+ let pipe = Pipe ( )
62+ let process = Process ( )
63+ process. executableURL = URL ( fileURLWithPath: path)
64+ process. arguments = args
65+ process. standardOutput = pipe
66+ try ? process. run ( )
67+ process. waitUntilExit ( )
68+
69+ let data = pipe. fileHandleForReading. readDataToEndOfFile ( )
70+ guard let result = String ( data: data, encoding: . utf8) ?
71+ . trimmingCharacters ( in: . whitespacesAndNewlines) ,
72+ !result. isEmpty else { return nil }
73+ return result
74+ }
75+
76+ /// Finds the location of the provided binary on your system.
77+ func which( _ name: String ) -> String ? {
78+ run ( " /usr/bin/which " , args: [ name] )
79+ }
80+
81+ extension String : Error {
82+ /// Replaces all occurrences of characters in the provided set with the provided string.
83+ func replacing( charactersIn characterSet: CharacterSet ,
84+ with separator: String ) -> String
85+ {
86+ let components = components ( separatedBy: characterSet)
87+ return components. joined ( separator: separator)
88+ }
89+ }
0 commit comments