Skip to content

Commit 1016d58

Browse files
committed
Add Swift Package support
1 parent 84deabb commit 1016d58

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
@@ -7,4 +7,5 @@
77
/dist
88
*.sqlite
99
*.a
10-
.vscode
10+
.vscode
11+
.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: "vector",
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: "vectorPlugin",
13+
targets: ["vectorPlugin"]),
14+
.library(
15+
name: "vector",
16+
targets: ["vector"])
17+
],
18+
targets: [
19+
// Build tool plugin that invokes the Makefile
20+
.plugin(
21+
name: "vectorPlugin",
22+
capability: .buildTool(),
23+
path: "packages/swift/plugin"
24+
),
25+
// vector library target
26+
.target(
27+
name: "vector",
28+
dependencies: [],
29+
path: "packages/swift/extension",
30+
plugins: ["vectorPlugin"]
31+
),
32+
]
33+
)

README.md

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

4545
You can download the WebAssembly (WASM) version of SQLite with the SQLite Vector extension enabled from: https://www.npmjs.com/package/@sqliteai/sqlite-wasm
4646

47+
### Swift Package
48+
49+
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).
50+
51+
Here's an example of how to use the package:
52+
```swift
53+
import vector
54+
55+
...
56+
57+
var db: OpaquePointer?
58+
sqlite3_open(":memory:", &db)
59+
sqlite3_enable_load_extension(db, 1)
60+
var errMsg: UnsafeMutablePointer<Int8>? = nil
61+
sqlite3_load_extension(db, vector.path, nil, &errMsg)
62+
var stmt: OpaquePointer?
63+
sqlite3_prepare_v2(db, "SELECT vector_version()", -1, &stmt, nil)
64+
defer { sqlite3_finalize(stmt) }
65+
sqlite3_step(stmt)
66+
log("vector_version(): \(String(cString: sqlite3_column_text(stmt, 0)))")
67+
sqlite3_close(db)
68+
```
69+
4770
### Loading the Extension
4871

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

packages/swift/plugin/vector.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 vector: 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 createvectorBuildCommands(packageDirectory: packageDirectory, outputDirectory: outputDirectory)
11+
}
12+
}
13+
14+
#if canImport(XcodeProjectPlugin)
15+
import XcodeProjectPlugin
16+
17+
extension vector: 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 createvectorBuildCommands(packageDirectory: nil, outputDirectory: outputDirectory)
22+
}
23+
}
24+
25+
#endif
26+
27+
/// Shared function to create vector build commands
28+
func createvectorBuildCommands(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 vector XCFramework",
37+
executable: URL(fileURLWithPath: "/bin/bash"),
38+
arguments: [
39+
"-c",
40+
"""
41+
set -e
42+
echo "Starting vector 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 with native network..." && \
52+
make xcframework NATIVE_NETWORK=ON DIST_DIR="\(outputDirectory.path)" BUILD_RELEASE="\(outputDirectory.path)/build/release" BUILD_TEST="\(outputDirectory.path)/build/test" && \
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)