22import Foundation
33
44#if os(Linux)
5- let libCPP = " -L/usr/lib -lc++ "
5+ let libCPP = " -L/usr/lib -lc++ "
66#elseif os(macOS)
7- let libCPP = " -lc++ "
7+ let libCPP = " -lc++ "
88#endif
99
1010/// Runs the specified program at the provided path.
@@ -25,110 +25,118 @@ func run(_ path: String, args: [String] = []) -> String? {
2525
2626 let data = pipe. fileHandleForReading. readDataToEndOfFile ( )
2727 guard let result = String ( data: data, encoding: . utf8) ?
28- . trimmingCharacters ( in: . whitespacesAndNewlines) ,
29- !result. isEmpty else { return nil }
28+ . trimmingCharacters ( in: . whitespacesAndNewlines) ,
29+ !result. isEmpty else { return nil }
3030 return result
3131}
3232
3333/// Finds the location of the provided binary on your system.
3434func which( _ name: String ) -> String ? {
35- return run ( " /usr/bin/which " , args: [ name] )
35+ run ( " /usr/bin/which " , args: [ name] )
3636}
3737
38- extension String : Error {
39- /// Replaces all occurrences of characters in the provided set with
40- /// the provided string.
41- func replacing( charactersIn characterSet: CharacterSet ,
42- with separator: String ) -> String {
43- let components = self . components ( separatedBy: characterSet)
44- return components. joined ( separator: separator)
45- }
38+ extension String {
39+ /// Replaces all occurrences of characters in the provided set with
40+ /// the provided string.
41+ func replacing( charactersIn characterSet: CharacterSet ,
42+ with separator: String ) -> String
43+ {
44+ let components = components ( separatedBy: characterSet)
45+ return components. joined ( separator: separator)
46+ }
47+ }
48+
49+ struct MakeFileError : Error {
50+ let message : String
51+
52+ init ( _ message: String ) {
53+ self . message = message
54+ }
4655}
4756
4857func makeFile( ) throws {
49- let brewPrefix = {
50- guard let brew = which ( " brew " ) else { return nil }
51- return run ( brew, args: [ " --prefix " ] )
52- } ( ) ?? " /usr/local "
53-
54- let pkgConfigPath = " \( brewPrefix) /lib/pkgconfig "
55- let pkgConfigDir = URL ( fileURLWithPath: pkgConfigPath)
56-
57- // Make <brew-prefix>/lib/pkgconfig if it doesn't already exist
58- if !FileManager. default. fileExists ( atPath: pkgConfigPath) {
59- try FileManager . default. createDirectory ( at: pkgConfigDir,
60- withIntermediateDirectories: true )
61- }
62- let cllvmPath = pkgConfigDir. appendingPathComponent ( " llvm.pc " )
63- let brewLLVMConfig = { which ( " \( brewPrefix) /opt/llvm/bin/llvm-config " ) }
64-
65- /// Ensure we have llvm-config in the PATH
66- guard let llvmConfig = which ( " llvm-config-15 " ) ?? which ( " llvm-config " ) ?? brewLLVMConfig ( ) else {
67- throw " Failed to find llvm-config. Ensure llvm-config is installed and " +
68- " in your PATH "
69- }
70-
71- /// Extract the info we need from llvm-config
72-
73- print ( " Found llvm-config at \( llvmConfig) ... " )
74-
75- let versionStr = run ( llvmConfig, args: [ " --version " ] ) !
76- . replacing ( charactersIn: . newlines, with: " " )
77- . replacingOccurrences ( of: " svn " , with: " " )
78- let components = versionStr. components ( separatedBy: " . " )
79- . compactMap { Int ( $0) }
80-
81- guard components. count == 3 else {
82- throw " Invalid version number \( versionStr) "
83- }
84-
85- let version = ( components [ 0 ] , components [ 1 ] , components [ 2 ] )
86-
87- guard version >= ( 15 , 0 , 0 ) else {
88- throw " LLVMSwift requires LLVM version >=15.0.0, but you have \( versionStr) "
89- }
90-
91- print ( " LLVM version is \( versionStr) " )
92-
93- let ldFlags = run ( llvmConfig, args: [ " --ldflags " , " --libs " , " all " ,
94- " --system-libs " ] ) !
95- . replacing ( charactersIn: . newlines, with: " " )
96- . components ( separatedBy: " " )
97- . filter { !$0. hasPrefix ( " -W " ) }
98- . joined ( separator: " " )
99-
100- // SwiftPM has a whitelisted set of cflags that it understands, and
101- // unfortunately that includes almost everything but the include dir.
102-
103- let cFlags = run ( llvmConfig, args: [ " --cflags " ] ) !
104- . replacing ( charactersIn: . newlines, with: " " )
105- . components ( separatedBy: " " )
106- . filter { $0. hasPrefix ( " -I " ) }
107- . joined ( separator: " " )
108-
109- /// Emit the pkg-config file to the path
110-
111- let s = [
112- " Name: cllvm " ,
113- " Description: The llvm library " ,
114- " Version: \( versionStr) " ,
115- " Libs: \( ldFlags) \( libCPP) " ,
116- " Requires.private: " ,
117- " Cflags: \( cFlags) " ,
118- ] . joined ( separator: " \n " )
119-
120- print ( " Writing pkg-config file to \( cllvmPath. path) ... " )
121-
122- try s. write ( toFile: cllvmPath. path, atomically: true , encoding: . utf8)
123-
124- print ( " \n Successfully wrote pkg-config file! " )
125- print ( " Make sure to re-run this script when you update LLVM. " )
58+ let brewPrefix = {
59+ guard let brew = which ( " brew " ) else { return nil }
60+ return run ( brew, args: [ " --prefix " ] )
61+ } ( ) ?? " /usr/local "
62+
63+ let pkgConfigPath = " \( brewPrefix) /lib/pkgconfig "
64+ let pkgConfigDir = URL ( fileURLWithPath: pkgConfigPath)
65+
66+ // Make <brew-prefix>/lib/pkgconfig if it doesn't already exist
67+ if !FileManager. default. fileExists ( atPath: pkgConfigPath) {
68+ try FileManager . default. createDirectory ( at: pkgConfigDir,
69+ withIntermediateDirectories: true )
70+ }
71+ let cllvmPath = pkgConfigDir. appendingPathComponent ( " llvm.pc " )
72+ let brewLLVMConfig = { which ( " \( brewPrefix) /opt/llvm/bin/llvm-config " ) }
73+
74+ /// Ensure we have llvm-config in the PATH
75+ guard let llvmConfig = which ( " llvm-config-15 " ) ?? which ( " llvm-config " ) ?? brewLLVMConfig ( ) else {
76+ throw MakeFileError ( " Failed to find llvm-config. Ensure llvm-config is installed and " +
77+ " in your PATH " )
78+ }
79+
80+ /// Extract the info we need from llvm-config
81+
82+ print ( " Found llvm-config at \( llvmConfig) ... " )
83+
84+ let versionStr = run ( llvmConfig, args: [ " --version " ] ) !
85+ . replacing ( charactersIn: . newlines, with: " " )
86+ . replacingOccurrences ( of: " svn " , with: " " )
87+ let components = versionStr. components ( separatedBy: " . " )
88+ . compactMap { Int ( $0) }
89+
90+ guard components. count == 3 else {
91+ throw MakeFileError ( " Invalid version number \( versionStr) " )
92+ }
93+
94+ let version = ( components [ 0 ] , components [ 1 ] , components [ 2 ] )
95+
96+ guard version >= ( 15 , 0 , 0 ) else {
97+ throw MakeFileError ( " LLVMSwift requires LLVM version >=15.0.0, but you have \( versionStr) " )
98+ }
99+
100+ print ( " LLVM version is \( versionStr) " )
101+
102+ let ldFlags = run ( llvmConfig, args: [ " --ldflags " , " --libs " , " all " ,
103+ " --system-libs " ] ) !
104+ . replacing ( charactersIn: . newlines, with: " " )
105+ . components ( separatedBy: " " )
106+ . filter { !$0. hasPrefix ( " -W " ) }
107+ . joined ( separator: " " )
108+
109+ // SwiftPM has a whitelisted set of cflags that it understands, and
110+ // unfortunately that includes almost everything but the include dir.
111+
112+ let cFlags = run ( llvmConfig, args: [ " --cflags " ] ) !
113+ . replacing ( charactersIn: . newlines, with: " " )
114+ . components ( separatedBy: " " )
115+ . filter { $0. hasPrefix ( " -I " ) }
116+ . joined ( separator: " " )
117+
118+ /// Emit the pkg-config file to the path
119+
120+ let s = [
121+ " Name: cllvm " ,
122+ " Description: The llvm library " ,
123+ " Version: \( versionStr) " ,
124+ " Libs: \( ldFlags) \( libCPP) " ,
125+ " Requires.private: " ,
126+ " Cflags: \( cFlags) " ,
127+ ] . joined ( separator: " \n " )
128+
129+ print ( " Writing pkg-config file to \( cllvmPath. path) ... " )
130+
131+ try s. write ( toFile: cllvmPath. path, atomically: true , encoding: . utf8)
132+
133+ print ( " \n Successfully wrote pkg-config file! " )
134+ print ( " Make sure to re-run this script when you update LLVM. " )
126135}
127136
128137do {
129- try makeFile ( )
138+ try makeFile ( )
130139} catch {
131- print ( " error: \( error) " )
132- exit ( - 1 )
140+ print ( " error: \( error) " )
141+ exit ( - 1 )
133142}
134-
0 commit comments