Skip to content

Commit c1f21a8

Browse files
committed
Add Swift Package Manager integration
1 parent 402551c commit c1f21a8

File tree

5 files changed

+137
-1
lines changed

5 files changed

+137
-1
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55
*.plist
66
/build
77
/dist
8-
*.sqlite
8+
*.sqlite
9+
.build

Package.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// swift-tools-version: 6.1
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "js",
8+
platforms: [.macOS(.v11), .iOS(.v11)],
9+
products: [
10+
// Products can be used to vend plugins, making them visible to other packages.
11+
.plugin(
12+
name: "jsPlugin",
13+
targets: ["jsPlugin"]),
14+
.library(
15+
name: "js",
16+
targets: ["js"])
17+
],
18+
targets: [
19+
// Build tool plugin that invokes the Makefile
20+
.plugin(
21+
name: "jsPlugin",
22+
capability: .buildTool(),
23+
path: "packages/swift/plugin"
24+
),
25+
// js library target
26+
.target(
27+
name: "js",
28+
dependencies: [],
29+
path: "packages/swift/extension",
30+
plugins: ["jsPlugin"]
31+
),
32+
]
33+
)

README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,29 @@ Download the appropriate pre-built binary for your platform from the official [R
3030
- Android
3131
- iOS
3232

33+
### Swift Package
34+
35+
You can [add this repository as a package dependency to your Swift project](https://developer.apple.com/documentation/xcode/adding-package-dependencies-to-your-app#Add-a-package-dependency). After adding the package, you'll need to set up SQLite with extension loading by following steps 4 and 5 of [this guide](https://github.com/sqliteai/sqlite-extensions-guide/blob/main/platforms/ios.md#4-set-up-sqlite-with-extension-loading).
36+
37+
Here's an example of how to use the package:
38+
```swift
39+
import js
40+
41+
...
42+
43+
var db: OpaquePointer?
44+
sqlite3_open(":memory:", &db)
45+
sqlite3_enable_load_extension(db, 1)
46+
var errMsg: UnsafeMutablePointer<Int8>? = nil
47+
sqlite3_load_extension(db, js.path, nil, &errMsg)
48+
var stmt: OpaquePointer?
49+
sqlite3_prepare_v2(db, "SELECT js_version()", -1, &stmt, nil)
50+
defer { sqlite3_finalize(stmt) }
51+
sqlite3_step(stmt)
52+
log("js_version(): \(String(cString: sqlite3_column_text(stmt, 0)))")
53+
sqlite3_close(db)
54+
```
55+
3356
### Loading the Extension
3457

3558
```sql

packages/swift/extension/js.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// js.swift
2+
// This file serves as a placeholder for the js target.
3+
// The actual SQLite extension is built using the Makefile through the build plugin.
4+
5+
import Foundation
6+
7+
/// Placeholder structure for js
8+
public struct js {
9+
/// Returns the path to the built js dylib inside the XCFramework
10+
public static var path: String {
11+
#if os(macOS)
12+
return "js.xcframework/macos-arm64_x86_64/js.framework/js"
13+
#elseif targetEnvironment(simulator)
14+
return "js.xcframework/ios-arm64_x86_64-simulator/js.framework/js"
15+
#else
16+
return "js.xcframework/ios-arm64/js.framework/js"
17+
#endif
18+
}
19+
}

packages/swift/plugin/js.swift

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import PackagePlugin
2+
import Foundation
3+
4+
@main
5+
struct js: BuildToolPlugin {
6+
/// Entry point for creating build commands for targets in Swift packages.
7+
func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] {
8+
let packageDirectory = context.package.directoryURL
9+
let outputDirectory = context.pluginWorkDirectoryURL
10+
return createjsBuildCommands(packageDirectory: packageDirectory, outputDirectory: outputDirectory)
11+
}
12+
}
13+
14+
#if canImport(XcodeProjectPlugin)
15+
import XcodeProjectPlugin
16+
17+
extension js: XcodeBuildToolPlugin {
18+
// Entry point for creating build commands for targets in Xcode projects.
19+
func createBuildCommands(context: XcodePluginContext, target: XcodeTarget) throws -> [Command] {
20+
let outputDirectory = context.pluginWorkDirectoryURL
21+
return createjsBuildCommands(packageDirectory: nil, outputDirectory: outputDirectory)
22+
}
23+
}
24+
25+
#endif
26+
27+
/// Shared function to create js build commands
28+
func createjsBuildCommands(packageDirectory: URL?, outputDirectory: URL) -> [Command] {
29+
30+
// For Xcode projects, use current directory; for Swift packages, use provided packageDirectory
31+
let workingDirectory = packageDirectory?.path ?? "$(pwd)"
32+
let packageDirInfo = packageDirectory != nil ? "Package directory: \(packageDirectory!.path)" : "Working directory: $(pwd)"
33+
34+
return [
35+
.prebuildCommand(
36+
displayName: "Building js XCFramework",
37+
executable: URL(fileURLWithPath: "/bin/bash"),
38+
arguments: [
39+
"-c",
40+
"""
41+
set -e
42+
echo "Starting js XCFramework prebuild..."
43+
echo "\(packageDirInfo)"
44+
45+
# Clean and create output directory
46+
rm -rf "\(outputDirectory.path)"
47+
mkdir -p "\(outputDirectory.path)"
48+
49+
# Build directly from source directory with custom output paths
50+
cd "\(workingDirectory)" && \
51+
echo "Building XCFramework..." && \
52+
make xcframework DIST_DIR="\(outputDirectory.path)" BUILD_DIR="\(outputDirectory.path)/build" && \
53+
rm -rf "\(outputDirectory.path)/build" && \
54+
echo "XCFramework build completed successfully!"
55+
"""
56+
],
57+
outputFilesDirectory: outputDirectory
58+
)
59+
]
60+
}

0 commit comments

Comments
 (0)