Skip to content

Commit af28502

Browse files
authored
Merge pull request #1340 from stephencelis/R4N-sqlcipher-spm
SQLCipher package
2 parents 1e425a1 + 5ea1c0d commit af28502

10 files changed

Lines changed: 210 additions & 70 deletions

File tree

.github/workflows/build.yml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@ on:
99
concurrency:
1010
group: ci-${{ github.ref }}
1111
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
12-
env:
13-
IOS_SIMULATOR: "iPhone 16"
14-
IOS_VERSION: "18.4"
1512
jobs:
1613
build:
17-
runs-on: macos-15
14+
strategy:
15+
matrix:
16+
os: [macos-15, macos-26]
17+
runs-on: ${{ matrix.os }}
18+
env:
19+
IOS_SIMULATOR: ${{ matrix.os == 'macos-15' && 'iPhone 16' || 'iPhone 16e' }}
20+
IOS_VERSION: ${{ matrix.os == 'macos-15' && '18.4' || '26.2' }}
1821
steps:
1922
- uses: actions/checkout@v4
2023
- name: "Lint"
@@ -23,6 +26,10 @@ jobs:
2326
env:
2427
PACKAGE_MANAGER_COMMAND: test -Xswiftc -warnings-as-errors
2528
run: ./run-tests.sh
29+
- name: "Run tests (PACKAGE_MANAGER_COMMAND: test --traits SQLCipher)"
30+
env:
31+
PACKAGE_MANAGER_COMMAND: test -Xswiftc -warnings-as-errors --traits SQLCipher
32+
run: ./run-tests.sh
2633
- name: "Run tests (SPM integration test)"
2734
env:
2835
SPM: run

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,4 @@ bin/
2929
.build
3030
Packages/
3131
.swiftpm/
32+
Package.resolved

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
0.15.5 (tbd), [diff][diff-0.15.5]
2+
========================================
3+
* SQLCipher package manager integration ([#1336][], [#1340][])
4+
15
0.15.4 (13-06-2025), [diff][diff-0.15.4]
26
========================================
37
* Fix cross compilation for linux on macOS fails ([#1317][])
@@ -271,4 +275,6 @@ For breaking changes, see [Upgrading.md](Documentation/Upgrading.md).
271275
[#1279]: https://github.com/stephencelis/SQLite.swift/pull/1279
272276
[#1280]: https://github.com/stephencelis/SQLite.swift/pull/1280
273277
[#1315]: https://github.com/stephencelis/SQLite.swift/pull/1315
274-
[#1317]: https://github.com/stephencelis/SQLite.swift/pull/1317
278+
[#1317]: https://github.com/stephencelis/SQLite.swift/pull/1317
279+
[#1336]: https://github.com/stephencelis/SQLite.swift/pull/1336
280+
[#1340]: https://github.com/stephencelis/SQLite.swift/pull/1340

Documentation/Index.md

Lines changed: 73 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
- [SQLite.swift Documentation](#sqliteswift-documentation)
44
- [Installation](#installation)
55
- [Swift Package Manager](#swift-package-manager)
6+
- [Using SQLite.swift with SQLCipher](#using-sqliteswift-with-sqlcipher)
67
- [Carthage](#carthage)
78
- [CocoaPods](#cocoapods)
89
- [Requiring a specific version of SQLite](#requiring-a-specific-version-of-sqlite)
9-
- [Using SQLite.swift with SQLCipher](#using-sqliteswift-with-sqlcipher)
1010
- [Manual](#manual)
1111
- [Getting Started](#getting-started)
1212
- [Connecting to a Database](#connecting-to-a-database)
@@ -119,7 +119,79 @@ process of downloading, compiling, and linking dependencies.
119119
$ swift build
120120
```
121121

122+
#### Using SQLite.swift with SQLCipher
123+
124+
If you want to use [SQLCipher][] with SQLite.swift you can specify the `SQLCipher` trait when consuming SQLite.swift.
125+
126+
```swift
127+
depdencies: [
128+
.package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.4", traits: ["SQLCipher"])
129+
]
130+
```
131+
132+
As of Xcode 26.2 (17C52), there's no direct way in the Xcode UI to select trait variations so you'll need to use a local wrapper package to pull in the SQLite.swift dependency with the `SQLCipher` trait enabled:
133+
134+
```swift
135+
// swift-tools-version: 6.1
136+
// The swift-tools-version declares the minimum version of Swift required to build this package.
137+
138+
import PackageDescription
139+
140+
let package = Package(
141+
name: "AppDependencies",
142+
platforms: [
143+
.macOS(.v10_14),
144+
.iOS(.v13),
145+
.macCatalyst(.v13),
146+
.watchOS(.v8),
147+
.tvOS(.v15),
148+
.visionOS(.v1)
149+
],
150+
products: [
151+
.library(
152+
name: "AppDependencies",
153+
targets: ["AppDependencies"]),
154+
],
155+
dependencies: [
156+
.package(
157+
url: "https://github.com/stephencelis/SQLite.swift.git",
158+
from: "0.15.4",
159+
traits: ["SQLCipher"])
160+
],
161+
targets: [
162+
.target(
163+
name: "AppDependencies",
164+
dependencies: [
165+
.product(
166+
name: "SQLite",
167+
package: "SQLite.swift")
168+
]
169+
)
170+
]
171+
)
172+
```
173+
174+
Within Xcode add your local `AppDependencies` wrapper package as a package dependency and SQLite.swift with SQLCipher functionality will be accessible.
175+
176+
Using the `SQLCipher` trait will cause SQLite.swift to include a dependency on SQLCipher.swift and enable `Connection` methods to set and change the database key:
177+
178+
```swift
179+
import SQLite
180+
181+
let db = try Connection("path/to/encrypted.sqlite3")
182+
try db.key("secret")
183+
try db.rekey("new secret") // changes encryption key on already encrypted db
184+
```
185+
186+
To encrypt an existing database:
187+
188+
```swift
189+
let db = try Connection("path/to/unencrypted.sqlite3")
190+
try db.sqlcipher_export(.uri("encrypted.sqlite3"), key: "secret")
191+
```
192+
122193
[Swift Package Manager]: https://swift.org/package-manager
194+
[SQLCipher]: https://www.zetetic.net/sqlcipher/
123195

124196
### Carthage
125197

@@ -191,41 +263,9 @@ end
191263

192264
See the [sqlite3 podspec][sqlite3pod] for more details.
193265

194-
#### Using SQLite.swift with SQLCipher
195-
196-
If you want to use [SQLCipher][] with SQLite.swift you can require the
197-
`SQLCipher` subspec in your Podfile (SPM is not supported yet, see [#1084](https://github.com/stephencelis/SQLite.swift/issues/1084)):
198-
199-
```ruby
200-
target 'YourAppTargetName' do
201-
# Make sure you only require the subspec, otherwise you app might link against
202-
# the system SQLite, which means the SQLCipher-specific methods won't work.
203-
pod 'SQLite.swift/SQLCipher', '~> 0.15.4'
204-
end
205-
```
206-
207-
This will automatically add a dependency to the SQLCipher pod as well as
208-
extend `Connection` with methods to change the database key:
209-
210-
```swift
211-
import SQLite
212-
213-
let db = try Connection("path/to/encrypted.sqlite3")
214-
try db.key("secret")
215-
try db.rekey("new secret") // changes encryption key on already encrypted db
216-
```
217-
218-
To encrypt an existing database:
219-
220-
```swift
221-
let db = try Connection("path/to/unencrypted.sqlite3")
222-
try db.sqlcipher_export(.uri("encrypted.sqlite3"), key: "secret")
223-
```
224-
225266
[CocoaPods]: https://cocoapods.org
226267
[CocoaPods Installation]: https://guides.cocoapods.org/using/getting-started.html#getting-started
227268
[sqlite3pod]: https://github.com/clemensg/sqlite3pod
228-
[SQLCipher]: https://www.zetetic.net/sqlcipher/
229269

230270
### Manual
231271

Package.swift

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,37 @@
1-
// swift-tools-version:5.9
1+
// swift-tools-version: 6.1
22
import PackageDescription
33

44
let deps: [Package.Dependency] = [
5-
.github("swiftlang/swift-toolchain-sqlite", exact: "1.0.7")
5+
.package(url: "https://github.com/swiftlang/swift-toolchain-sqlite", from: "1.0.7"),
6+
.package(url: "https://github.com/sqlcipher/SQLCipher.swift.git", from: "4.11.0")
67
]
78

9+
let applePlatforms: [PackageDescription.Platform] = [.iOS, .macOS, .watchOS, .tvOS, .visionOS]
10+
let sqlcipherTraitBuildSettingCondition: BuildSettingCondition? = .when(platforms: applePlatforms, traits: ["SQLCipher"])
11+
let cSettings: [CSetting] = [.define("SQLITE_HAS_CODEC", to: nil, sqlcipherTraitBuildSettingCondition)]
12+
let swiftSettings: [SwiftSetting] = [.define("SQLITE_HAS_CODEC", sqlcipherTraitBuildSettingCondition)]
13+
814
let targets: [Target] = [
915
.target(
1016
name: "SQLite",
1117
dependencies: [
12-
.product(name: "SwiftToolchainCSQLite", package: "swift-toolchain-sqlite", condition: .when(platforms: [.linux, .windows, .android]))
18+
.product(name: "SwiftToolchainCSQLite", package: "swift-toolchain-sqlite", condition: .when(platforms: [.linux, .windows, .android])),
19+
.product(name: "SQLCipher", package: "SQLCipher.swift", condition: .when(platforms: applePlatforms, traits: ["SQLCipher"]))
1320
],
14-
exclude: [
15-
"Info.plist"
16-
]
21+
exclude: ["Info.plist"],
22+
cSettings: cSettings,
23+
swiftSettings: swiftSettings
1724
)
1825
]
1926

2027
let testTargets: [Target] = [
2128
.testTarget(
2229
name: "SQLiteTests",
23-
dependencies: [
24-
"SQLite"
25-
],
30+
dependencies: ["SQLite"],
2631
path: "Tests/SQLiteTests",
27-
exclude: [
28-
"Info.plist"
29-
],
30-
resources: [
31-
.copy("Resources")
32-
]
32+
exclude: ["Info.plist"],
33+
resources: [.copy("Resources")],
34+
swiftSettings: swiftSettings
3335
)
3436
]
3537

@@ -48,13 +50,10 @@ let package = Package(
4850
targets: ["SQLite"]
4951
)
5052
],
53+
traits: [
54+
.trait(name: "SQLCipher", description: "Enables SQLCipher encryption when a key is supplied to Connection")
55+
],
5156
dependencies: deps,
52-
targets: targets + testTargets
57+
targets: targets + testTargets,
58+
swiftLanguageModes: [.v5],
5359
)
54-
55-
extension Package.Dependency {
56-
57-
static func github(_ repo: String, exact ver: Version) -> Package.Dependency {
58-
.package(url: "https://github.com/\(repo)", exact: ver)
59-
}
60-
}

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ syntax _and_ intent.
1818
- [Full-text search][] support
1919
- [Well-documented][See Documentation]
2020
- Extensively tested
21-
- [SQLCipher][] support via CocoaPods
21+
- [SQLCipher][] support via Swift Package Manager
2222
- [Schema query/migration][]
2323
- Works on [Linux](Documentation/Linux.md) (with some limitations)
2424
- Active support at

SQLite.swift.podspec

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Pod::Spec.new do |s|
2929
ss.exclude_files = 'Sources/**/Cipher.swift'
3030
ss.library = 'sqlite3'
3131
ss.resource_bundle = { 'SQLite.swift' => 'Sources/SQLite/PrivacyInfo.xcprivacy' }
32-
32+
3333
ss.test_spec 'tests' do |test_spec|
3434
test_spec.resources = 'Tests/SQLiteTests/Resources/*'
3535
test_spec.source_files = 'Tests/SQLiteTests/**/*.swift'
@@ -46,7 +46,7 @@ Pod::Spec.new do |s|
4646
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SQLITE_SWIFT_STANDALONE=1'
4747
}
4848
ss.dependency 'sqlite3'
49-
49+
5050
ss.test_spec 'tests' do |test_spec|
5151
test_spec.resources = 'Tests/SQLiteTests/Resources/*'
5252
test_spec.source_files = 'Tests/SQLiteTests/**/*.swift'
@@ -65,11 +65,11 @@ Pod::Spec.new do |s|
6565
ss.resource_bundle = { 'SQLite.swift' => 'Sources/SQLite/PrivacyInfo.xcprivacy' }
6666

6767
ss.xcconfig = {
68-
'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_SQLCIPHER',
69-
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SQLITE_HAS_CODEC=1 SQLITE_SWIFT_SQLCIPHER=1'
68+
'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_HAS_CODEC',
69+
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SQLITE_HAS_CODEC=1'
7070
}
7171
ss.dependency 'SQLCipher', '>= 4.0.0'
72-
72+
7373
ss.test_spec 'tests' do |test_spec|
7474
test_spec.resources = 'Tests/SQLiteTests/Resources/*'
7575
test_spec.source_files = 'Tests/SQLiteTests/**/*.swift'

Sources/SQLite/Core/Connection+Attach.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Foundation
22

33
extension Connection {
4-
#if SQLITE_SWIFT_SQLCIPHER
4+
#if SQLITE_HAS_CODEC
55
/// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#attach
66
public func attach(_ location: Location, as schemaName: String, key: String? = nil) throws {
77
if let key {

0 commit comments

Comments
 (0)