2
2
// The swift-tools-version declares the minimum version of Swift required to build this package.
3
3
4
4
import PackageDescription
5
+ import Foundation
6
+
7
+ let ( cFlags, linkFlags) = try ! getLLVMConfig ( )
5
8
6
9
let package = Package (
7
10
name: " llvm-api " ,
@@ -11,17 +14,76 @@ let package = Package(
11
14
targets: [
12
15
. systemLibrary(
13
16
name: " CLLVM " ,
14
- path: " llvm-api/CLLVM " ,
15
- pkgConfig: " CLLVM " ,
16
- providers: [
17
- . brew( [ " llvm " ] ) ,
18
- ]
17
+ path: " llvm-api/CLLVM "
19
18
) ,
20
19
. target(
21
20
name: " LLVM " ,
22
21
dependencies: [ " CLLVM " ] ,
23
- path: " llvm-api/LLVM "
22
+ path: " llvm-api/LLVM " ,
23
+ cSettings: [
24
+ . unsafeFlags( cFlags)
25
+ ] ,
26
+ linkerSettings: [
27
+ . unsafeFlags( linkFlags)
28
+ ]
24
29
) ,
25
- ] ,
26
- cxxLanguageStandard: . cxx20
30
+ ]
27
31
)
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