Skip to content

Commit 81c4cd8

Browse files
authored
Merge pull request #6 from mrLSD/feat/new-swift
Feat: Update to Swift 6 and fix related issues
2 parents 174917d + da1180a commit 81c4cd8

File tree

6 files changed

+124
-103
lines changed

6 files changed

+124
-103
lines changed

.github/workflows/swift.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ jobs:
1414
runs-on: macos-latest
1515
steps:
1616
- uses: actions/checkout@v4
17-
- uses: swift-actions/setup-swift@v1
17+
- uses: SwiftyLab/setup-swift@latest
1818
- name: Pre-install
1919
run: |
2020
brew update
21-
brew install llvm@18
21+
brew install llvm@19
2222
# Important: add empty string
2323
echo "" >> /Users/runner/.bash_profile
2424
echo 'export PATH="/opt/homebrew/opt/llvm/bin:$PATH"' >> /Users/runner/.bash_profile

Package.swift

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ let package = Package(
1212
targets: getTargets()
1313
)
1414

15+
struct GetConfigError: Error {
16+
let message: String
17+
init(_ message: String) {
18+
self.message = message
19+
}
20+
}
21+
1522
/// Get LLVM config flags
1623
func getLLVMConfig() throws -> ([String], [String], [Int]) {
1724
let brewPrefix = {
@@ -20,7 +27,7 @@ func getLLVMConfig() throws -> ([String], [String], [Int]) {
2027
}() ?? "/usr/local"
2128
/// Ensure we have llvm-config in the PATH
2229
guard let llvmConfig = which("llvm-config") ?? which("\(brewPrefix)/opt/llvm/bin/llvm-config") else {
23-
throw "Failed to find llvm-config. Ensure llvm-config is installed and in your PATH"
30+
throw GetConfigError("Failed to find llvm-config. Ensure llvm-config is installed and in your PATH")
2431
}
2532
// Fetch LLVM version
2633
let versionStr = run(llvmConfig, args: ["--version"])!
@@ -66,7 +73,7 @@ func which(_ name: String) -> String? {
6673
run("/usr/bin/which", args: [name])
6774
}
6875

69-
extension String: Error {
76+
extension String {
7077
/// Replaces all occurrences of characters in the provided set with the provided string.
7178
func replacing(charactersIn characterSet: CharacterSet,
7279
with separator: String) -> String
@@ -76,18 +83,18 @@ extension String: Error {
7683
}
7784
}
7885

79-
/// Check Environ,ent variable
86+
/// Check Environment variable
8087
func hasEnvironmentVariable(_ name: String) -> Bool {
8188
ProcessInfo.processInfo.environment[name] != nil
8289
}
8390

8491
func getTargets() -> [Target] {
8592
if hasEnvironmentVariable("CLI_BUILD") {
8693
let (cFlags, linkFlags, _) = try! getLLVMConfig()
87-
let customSystemLibrary: Target = .systemLibrary(
94+
let customSystemLibrary = Target.systemLibrary(
8895
name: "CLLVM"
8996
)
90-
let llvmTarget: Target = .target(
97+
let llvmTarget = Target.target(
9198
name: "LLVM",
9299
dependencies: ["CLLVM"],
93100
cSettings: [

Source/LLVM/Core/AddressSpace.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ import CLLVM
5050
/// - The address space is ultimately an integer value and in theory an address space identifier may take on
5151
/// any value. In practice, LLVM guarantees only 24 bits of precision, though higher address space
5252
/// identifiers may succeed in being properly represented.
53-
public struct AddressSpace: Equatable {
53+
public struct AddressSpace: Equatable, Sendable {
5454
let rawValue: UInt32
5555

5656
/// LLVM's default address space.

Source/LLVM/Core/Context.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public final class Context: ContextRef {
3434
/// recommended that each thread of execution attempting to access the LLVM
3535
/// API have its own `Context` instance, rather than rely on this global
3636
/// context.
37+
@MainActor
3738
public static let global = Context(llvm: LLVMGetGlobalContext()!)
3839

3940
/// Creates a new `Context` object.
@@ -222,7 +223,7 @@ public final class Context: ContextRef {
222223
}
223224
}
224225

225-
///Destroy a context instance.
226+
/// Destroy a context instance.
226227
///
227228
/// This should be called for every call to LLVMContextCreate() or memory will be leaked.
228229
public func dispose() {

Source/LLVM/Core/Core.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
import CLLVM
2+
#if os(Linux)
3+
import Glibc
4+
#else
5+
import Darwin
6+
#endif
27

38
/// This modules provide an interface to libLLVMCore, which implements the LLVM intermediate representation as well
49
/// as other related types and utilities.

utils/llvm-pkg.swift

Lines changed: 102 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
import 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.
3434
func 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

4857
func 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("\nSuccessfully 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("\nSuccessfully wrote pkg-config file!")
134+
print("Make sure to re-run this script when you update LLVM.")
126135
}
127136

128137
do {
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

Comments
 (0)