From 79e44e73d645bd7e261b374cee1383007ddfae1b Mon Sep 17 00:00:00 2001 From: Jan Berkel Date: Mon, 12 Jan 2026 23:51:01 +0100 Subject: [PATCH 01/14] Traits automatically set up define with the trait name --- Package.swift | 7 ++----- SQLite.swift.podspec | 2 +- Sources/SQLite/Core/Connection+Attach.swift | 2 +- Sources/SQLite/Extensions/Cipher.swift | 2 +- Tests/SQLiteTests/Extensions/CipherTests.swift | 2 +- 5 files changed, 6 insertions(+), 9 deletions(-) diff --git a/Package.swift b/Package.swift index b88137ce..ee4fde8f 100644 --- a/Package.swift +++ b/Package.swift @@ -9,7 +9,6 @@ let deps: [Package.Dependency] = [ let applePlatforms: [PackageDescription.Platform] = [.iOS, .macOS, .watchOS, .tvOS, .visionOS] let sqlcipherTraitBuildSettingCondition: BuildSettingCondition? = .when(platforms: applePlatforms, traits: ["SQLCipher"]) let cSettings: [CSetting] = [.define("SQLITE_HAS_CODEC", to: nil, sqlcipherTraitBuildSettingCondition)] -let swiftSettings: [SwiftSetting] = [.define("SQLITE_HAS_CODEC", sqlcipherTraitBuildSettingCondition)] let targets: [Target] = [ .target( @@ -19,8 +18,7 @@ let targets: [Target] = [ .product(name: "SQLCipher", package: "SQLCipher.swift", condition: .when(platforms: applePlatforms, traits: ["SQLCipher"])) ], exclude: ["Info.plist"], - cSettings: cSettings, - swiftSettings: swiftSettings + cSettings: cSettings ) ] @@ -30,8 +28,7 @@ let testTargets: [Target] = [ dependencies: ["SQLite"], path: "Tests/SQLiteTests", exclude: ["Info.plist"], - resources: [.copy("Resources")], - swiftSettings: swiftSettings + resources: [.copy("Resources")] ) ] diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec index 27db91ec..bc800bdd 100644 --- a/SQLite.swift.podspec +++ b/SQLite.swift.podspec @@ -65,7 +65,7 @@ Pod::Spec.new do |s| ss.resource_bundle = { 'SQLite.swift' => 'Sources/SQLite/PrivacyInfo.xcprivacy' } ss.xcconfig = { - 'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_HAS_CODEC', + 'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLCipher', 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SQLITE_HAS_CODEC=1' } ss.dependency 'SQLCipher', '>= 4.0.0' diff --git a/Sources/SQLite/Core/Connection+Attach.swift b/Sources/SQLite/Core/Connection+Attach.swift index f2b1f007..d980bc45 100644 --- a/Sources/SQLite/Core/Connection+Attach.swift +++ b/Sources/SQLite/Core/Connection+Attach.swift @@ -1,7 +1,7 @@ import Foundation extension Connection { - #if SQLITE_HAS_CODEC + #if SQLCipher /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#attach public func attach(_ location: Location, as schemaName: String, key: String? = nil) throws { if let key { diff --git a/Sources/SQLite/Extensions/Cipher.swift b/Sources/SQLite/Extensions/Cipher.swift index 4bdfca53..6955b44a 100644 --- a/Sources/SQLite/Extensions/Cipher.swift +++ b/Sources/SQLite/Extensions/Cipher.swift @@ -1,4 +1,4 @@ -#if SQLITE_HAS_CODEC +#if SQLCipher import SQLCipher /// Extension methods for [SQLCipher](https://www.zetetic.net/sqlcipher/). diff --git a/Tests/SQLiteTests/Extensions/CipherTests.swift b/Tests/SQLiteTests/Extensions/CipherTests.swift index 41dcb3d9..255d2d23 100644 --- a/Tests/SQLiteTests/Extensions/CipherTests.swift +++ b/Tests/SQLiteTests/Extensions/CipherTests.swift @@ -1,4 +1,4 @@ -#if SQLITE_HAS_CODEC +#if SQLCipher import XCTest import SQLite import SQLCipher From df532ad35959acf71e636f927830f25d77fa65ff Mon Sep 17 00:00:00 2001 From: Jan Berkel Date: Tue, 13 Jan 2026 10:00:34 +0100 Subject: [PATCH 02/14] Clean up Package.swift --- .swiftlint.yml | 1 + Package.swift | 64 +++++++++++++++++++++++--------------------------- 2 files changed, 30 insertions(+), 35 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index 1bb21cd5..fe24828b 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -10,6 +10,7 @@ disabled_rules: # rule identifiers to exclude from running included: # paths to include during linting. `--path` is ignored if present. takes precendence over `excluded`. - Sources - Tests + - Package.swift excluded: # paths to ignore during linting. overridden by `included`. identifier_name: diff --git a/Package.swift b/Package.swift index ee4fde8f..0c660b8a 100644 --- a/Package.swift +++ b/Package.swift @@ -1,36 +1,29 @@ // swift-tools-version: 6.1 import PackageDescription - -let deps: [Package.Dependency] = [ - .package(url: "https://github.com/swiftlang/swift-toolchain-sqlite", from: "1.0.7"), - .package(url: "https://github.com/sqlcipher/SQLCipher.swift.git", from: "4.11.0") -] - let applePlatforms: [PackageDescription.Platform] = [.iOS, .macOS, .watchOS, .tvOS, .visionOS] -let sqlcipherTraitBuildSettingCondition: BuildSettingCondition? = .when(platforms: applePlatforms, traits: ["SQLCipher"]) -let cSettings: [CSetting] = [.define("SQLITE_HAS_CODEC", to: nil, sqlcipherTraitBuildSettingCondition)] -let targets: [Target] = [ - .target( - name: "SQLite", - dependencies: [ - .product(name: "SwiftToolchainCSQLite", package: "swift-toolchain-sqlite", condition: .when(platforms: [.linux, .windows, .android])), - .product(name: "SQLCipher", package: "SQLCipher.swift", condition: .when(platforms: applePlatforms, traits: ["SQLCipher"])) - ], - exclude: ["Info.plist"], - cSettings: cSettings - ) -] +let target: Target = .target( + name: "SQLite", + dependencies: [ + .product(name: "SwiftToolchainCSQLite", + package: "swift-toolchain-sqlite", + condition: .when(platforms: [.linux, .windows, .android])), + .product(name: "SQLCipher", + package: "SQLCipher.swift", + condition: .when(platforms: applePlatforms, traits: ["SQLCipher"])) + ], + exclude: ["Info.plist"], + cSettings: [ + .define("SQLITE_HAS_CODEC", .when(platforms: applePlatforms, traits: ["SQLCipher"])) + ] +) -let testTargets: [Target] = [ - .testTarget( - name: "SQLiteTests", - dependencies: ["SQLite"], - path: "Tests/SQLiteTests", - exclude: ["Info.plist"], - resources: [.copy("Resources")] - ) -] +let testTarget: Target = .testTarget( + name: "SQLiteTests", + dependencies: ["SQLite"], + exclude: ["Info.plist"], + resources: [.copy("Resources")] +) let package = Package( name: "SQLite.swift", @@ -42,15 +35,16 @@ let package = Package( .visionOS(.v1) ], products: [ - .library( - name: "SQLite", - targets: ["SQLite"] - ) + .library(name: "SQLite", targets: ["SQLite"]) ], traits: [ - .trait(name: "SQLCipher", description: "Enables SQLCipher encryption when a key is supplied to Connection") + .trait(name: "SQLCipher", + description: "Enables SQLCipher encryption when a key is supplied to Connection") + ], + dependencies: [ + .package(url: "https://github.com/swiftlang/swift-toolchain-sqlite", from: "1.0.7"), + .package(url: "https://github.com/sqlcipher/SQLCipher.swift.git", from: "4.11.0") ], - dependencies: deps, - targets: targets + testTargets, + targets: [target, testTarget], swiftLanguageModes: [.v5], ) From 47e50bf9102928730a51f2a3ebaece54d080e7ba Mon Sep 17 00:00:00 2001 From: Jan Berkel Date: Tue, 13 Jan 2026 10:14:32 +0100 Subject: [PATCH 03/14] Convert into trait --- .github/workflows/build.yml | 4 ++++ Package.swift | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a50bffee..402da31e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,6 +26,10 @@ jobs: env: PACKAGE_MANAGER_COMMAND: test -Xswiftc -warnings-as-errors run: ./run-tests.sh + - name: "Run tests (PACKAGE_MANAGER_COMMAND: test --traits SwiftToolchainCSQLite)" + env: + PACKAGE_MANAGER_COMMAND: test -Xswiftc -warnings-as-errors --traits SwiftToolchainCSQLite + run: ./run-tests.sh - name: "Run tests (PACKAGE_MANAGER_COMMAND: test --traits SQLCipher)" env: PACKAGE_MANAGER_COMMAND: test -Xswiftc -warnings-as-errors --traits SQLCipher diff --git a/Package.swift b/Package.swift index 0c660b8a..d2d0128c 100644 --- a/Package.swift +++ b/Package.swift @@ -7,7 +7,7 @@ let target: Target = .target( dependencies: [ .product(name: "SwiftToolchainCSQLite", package: "swift-toolchain-sqlite", - condition: .when(platforms: [.linux, .windows, .android])), + condition: .when(traits: ["SwiftToolchainCSQLite"])), .product(name: "SQLCipher", package: "SQLCipher.swift", condition: .when(platforms: applePlatforms, traits: ["SQLCipher"])) @@ -39,7 +39,9 @@ let package = Package( ], traits: [ .trait(name: "SQLCipher", - description: "Enables SQLCipher encryption when a key is supplied to Connection") + description: "Enables SQLCipher encryption when a key is supplied to Connection"), + .trait(name: "SwiftToolchainCSQLite", + description: "Uses the SQLite from SwiftToolchain") ], dependencies: [ .package(url: "https://github.com/swiftlang/swift-toolchain-sqlite", from: "1.0.7"), From 30fe3034dffe0d3cfb235c37fc0c3b1a8ed9e705 Mon Sep 17 00:00:00 2001 From: Jan Berkel Date: Tue, 13 Jan 2026 10:51:40 +0100 Subject: [PATCH 04/14] Update xcbeautify --- Makefile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 52a25a12..e00e4b6e 100644 --- a/Makefile +++ b/Makefile @@ -7,14 +7,14 @@ IOS_VERSION = 16.4 SWIFTLINT_VERSION=0.52.2 SWIFTLINT=bin/swiftlint-$(SWIFTLINT_VERSION) SWIFTLINT_URL=https://github.com/realm/SwiftLint/releases/download/$(SWIFTLINT_VERSION)/portable_swiftlint.zip -XCBEAUTIFY_VERSION=0.20.0 +XCBEAUTIFY_VERSION=3.1.2 XCBEAUTIFY=bin/xcbeautify-$(XCBEAUTIFY_VERSION) ifeq ($(shell uname), Linux) XCBEAUTIFY_PLATFORM=x86_64-unknown-linux-gnu.tar.xz else XCBEAUTIFY_PLATFORM=universal-apple-macosx.zip endif -XCBEAUTIFY_URL=https://github.com/tuist/xcbeautify/releases/download/$(XCBEAUTIFY_VERSION)/xcbeautify-$(XCBEAUTIFY_VERSION)-$(XCBEAUTIFY_PLATFORM) +XCBEAUTIFY_URL=https://github.com/cpisciotta/xcbeautify/releases/download/$(XCBEAUTIFY_VERSION)/xcbeautify-$(XCBEAUTIFY_VERSION)-$(XCBEAUTIFY_PLATFORM) CURL_OPTS=--fail --silent -L --retry 3 ifeq ($(BUILD_SCHEME),SQLite iOS) @@ -60,10 +60,10 @@ $(XCBEAUTIFY): curl $(CURL_OPTS) $(XCBEAUTIFY_URL) -o $$FILE; \ case "$${FILE#*.}" in \ "zip") \ - unzip -o $$FILE xcbeautify; \ + unzip -o $$FILE release/xcbeautify; \ ;; \ "tar.xz") \ - tar -xvf $$FILE xcbeautify; \ + tar -xvf $$FILE release/xcbeautify; \ ;; \ *) \ echo "unknown extension $${FILE#*.}!"; \ @@ -71,6 +71,6 @@ $(XCBEAUTIFY): ;; \ esac; \ mkdir -p bin; \ - mv xcbeautify $@ && rm -f $$FILE; + mv release/xcbeautify $@ && rm -f $$FILE; .PHONY: test clean repl sloc From e5f413a9a9035aeb8b7ab0db6cdaaf50509e1f7e Mon Sep 17 00:00:00 2001 From: Jan Berkel Date: Tue, 13 Jan 2026 20:22:50 +0100 Subject: [PATCH 05/14] Use traits for other configurations --- Package.swift | 10 +++++-- SQLite.swift.podspec | 21 +++++++------- Sources/SQLite/Core/Backup.swift | 8 ++--- .../SQLite/Core/Connection+Aggregation.swift | 8 ++--- Sources/SQLite/Core/Connection.swift | 8 ++--- Sources/SQLite/Core/Result.swift | 8 ++--- Sources/SQLite/Core/Statement.swift | 8 ++--- Sources/SQLite/Helpers.swift | 8 ++--- .../Core/Connection+AttachTests.swift | 8 ++--- Tests/SQLiteTests/Core/ConnectionTests.swift | 29 +++++++++++++------ Tests/SQLiteTests/Core/ResultTests.swift | 8 ++--- Tests/SQLiteTests/Core/StatementTests.swift | 8 ++--- .../Typed/QueryIntegrationTests.swift | 8 ++--- 13 files changed, 78 insertions(+), 62 deletions(-) diff --git a/Package.swift b/Package.swift index d2d0128c..7930502f 100644 --- a/Package.swift +++ b/Package.swift @@ -38,10 +38,16 @@ let package = Package( .library(name: "SQLite", targets: ["SQLite"]) ], traits: [ + .trait(name: "SystemSQLite", + description: "Uses the system-provided SQLite (on Apple platforms)"), + .trait(name: "SwiftToolchainCSQLite", + description: "Include SQLite from the Swift toolchain"), + // this will note compile, just included for sake of completeness + .trait(name: "StandaloneSQLite", + description: "Assumes SQLite to be already available as 'sqlite3'"), .trait(name: "SQLCipher", description: "Enables SQLCipher encryption when a key is supplied to Connection"), - .trait(name: "SwiftToolchainCSQLite", - description: "Uses the SQLite from SwiftToolchain") + .default(enabledTraits: ["SystemSQLite"]) ], dependencies: [ .package(url: "https://github.com/swiftlang/swift-toolchain-sqlite", from: "1.0.7"), diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec index bc800bdd..1c95606c 100644 --- a/SQLite.swift.podspec +++ b/SQLite.swift.podspec @@ -24,52 +24,51 @@ Pod::Spec.new do |s| s.watchos.deployment_target = '4.0' s.visionos.deployment_target = '1.0' + # uses the built-in sqlite3 library s.subspec 'standard' do |ss| + ss.library = 'sqlite3' ss.source_files = 'Sources/SQLite/**/*.{c,h,m,swift}' ss.exclude_files = 'Sources/**/Cipher.swift' - ss.library = 'sqlite3' ss.resource_bundle = { 'SQLite.swift' => 'Sources/SQLite/PrivacyInfo.xcprivacy' } - + ss.xcconfig = { + 'OTHER_SWIFT_FLAGS' => '$(inherited) -DSystemSQLite' + } ss.test_spec 'tests' do |test_spec| test_spec.resources = 'Tests/SQLiteTests/Resources/*' test_spec.source_files = 'Tests/SQLiteTests/**/*.swift' end end + # uses SQLite from https://github.com/clemensg/sqlite3pod s.subspec 'standalone' do |ss| + ss.dependency 'sqlite3' ss.source_files = 'Sources/SQLite/**/*.{c,h,m,swift}' ss.exclude_files = 'Sources/**/Cipher.swift' ss.resource_bundle = { 'SQLite.swift' => 'Sources/SQLite/PrivacyInfo.xcprivacy' } - ss.xcconfig = { - 'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_STANDALONE', - 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SQLITE_SWIFT_STANDALONE=1' + 'OTHER_SWIFT_FLAGS' => '$(inherited) -DStandaloneSQLite' } - ss.dependency 'sqlite3' - ss.test_spec 'tests' do |test_spec| test_spec.resources = 'Tests/SQLiteTests/Resources/*' test_spec.source_files = 'Tests/SQLiteTests/**/*.swift' end end + # uses SQLCipher from https://github.com/sqlcipher/sqlcipher s.subspec 'SQLCipher' do |ss| + ss.dependency 'SQLCipher', '>= 4.0.0' # Disable unsupported visionOS # https://github.com/sqlcipher/sqlcipher/issues/483 ss.ios.deployment_target = s.deployment_target(:ios) ss.tvos.deployment_target = s.deployment_target(:tvos) ss.osx.deployment_target = s.deployment_target(:osx) ss.watchos.deployment_target = s.deployment_target(:watchos) - ss.source_files = 'Sources/SQLite/**/*.{c,h,m,swift}' ss.resource_bundle = { 'SQLite.swift' => 'Sources/SQLite/PrivacyInfo.xcprivacy' } - ss.xcconfig = { 'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLCipher', 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SQLITE_HAS_CODEC=1' } - ss.dependency 'SQLCipher', '>= 4.0.0' - ss.test_spec 'tests' do |test_spec| test_spec.resources = 'Tests/SQLiteTests/Resources/*' test_spec.source_files = 'Tests/SQLiteTests/**/*.swift' diff --git a/Sources/SQLite/Core/Backup.swift b/Sources/SQLite/Core/Backup.swift index 51413896..90d1794f 100644 --- a/Sources/SQLite/Core/Backup.swift +++ b/Sources/SQLite/Core/Backup.swift @@ -24,14 +24,14 @@ import Foundation import Dispatch -#if canImport(sqlite3) +#if StandaloneSQLite import sqlite3 -#elseif canImport(SQLCipher) +#elseif SQLCipher import SQLCipher -#elseif canImport(SwiftToolchainCSQLite) +#elseif SwiftToolchainCSQLite import SwiftToolchainCSQLite #else -import SQLite3 +import SQLite3 // SystemSQLite #endif /// An object representing database backup. diff --git a/Sources/SQLite/Core/Connection+Aggregation.swift b/Sources/SQLite/Core/Connection+Aggregation.swift index 4c347e7d..38d2164c 100644 --- a/Sources/SQLite/Core/Connection+Aggregation.swift +++ b/Sources/SQLite/Core/Connection+Aggregation.swift @@ -1,12 +1,12 @@ import Foundation -#if canImport(sqlite3) +#if StandaloneSQLite import sqlite3 -#elseif canImport(SQLCipher) +#elseif SQLCipher import SQLCipher -#elseif canImport(SwiftToolchainCSQLite) +#elseif SwiftToolchainCSQLite import SwiftToolchainCSQLite #else -import SQLite3 +import SQLite3 // SystemSQLite #endif extension Connection { diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift index 9ab4c839..c5aa4424 100644 --- a/Sources/SQLite/Core/Connection.swift +++ b/Sources/SQLite/Core/Connection.swift @@ -24,14 +24,14 @@ import Foundation import Dispatch -#if canImport(sqlite3) +#if StandaloneSQLite import sqlite3 -#elseif canImport(SQLCipher) +#elseif SQLCipher import SQLCipher -#elseif canImport(SwiftToolchainCSQLite) +#elseif SwiftToolchainCSQLite import SwiftToolchainCSQLite #else -import SQLite3 +import SQLite3 // SystemSQLite #endif /// A connection to SQLite. diff --git a/Sources/SQLite/Core/Result.swift b/Sources/SQLite/Core/Result.swift index eae2712b..db690bb2 100644 --- a/Sources/SQLite/Core/Result.swift +++ b/Sources/SQLite/Core/Result.swift @@ -1,11 +1,11 @@ -#if canImport(sqlite3) +#if StandaloneSQLite import sqlite3 -#elseif canImport(SQLCipher) +#elseif SQLCipher import SQLCipher -#elseif canImport(SwiftToolchainCSQLite) +#elseif SwiftToolchainCSQLite import SwiftToolchainCSQLite #else -import SQLite3 +import SQLite3 // SystemSQLite #endif public enum Result: Error { diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift index e52c8692..2f15c366 100644 --- a/Sources/SQLite/Core/Statement.swift +++ b/Sources/SQLite/Core/Statement.swift @@ -22,14 +22,14 @@ // THE SOFTWARE. // -#if canImport(sqlite3) +#if StandaloneSQLite import sqlite3 -#elseif canImport(SQLCipher) +#elseif SQLCipher import SQLCipher -#elseif canImport(SwiftToolchainCSQLite) +#elseif SwiftToolchainCSQLite import SwiftToolchainCSQLite #else -import SQLite3 +import SQLite3 // SystemSQLite #endif /// A single SQL statement. diff --git a/Sources/SQLite/Helpers.swift b/Sources/SQLite/Helpers.swift index 339a8792..d207382d 100644 --- a/Sources/SQLite/Helpers.swift +++ b/Sources/SQLite/Helpers.swift @@ -22,14 +22,14 @@ // THE SOFTWARE. // -#if canImport(sqlite3) +#if StandaloneSQLite import sqlite3 -#elseif canImport(SQLCipher) +#elseif SQLCipher import SQLCipher -#elseif canImport(SwiftToolchainCSQLite) +#elseif SwiftToolchainCSQLite import SwiftToolchainCSQLite #else -import SQLite3 +import SQLite3 // SystemSQLite #endif public typealias Star = (Expression?, Expression?) -> Expression diff --git a/Tests/SQLiteTests/Core/Connection+AttachTests.swift b/Tests/SQLiteTests/Core/Connection+AttachTests.swift index 3134340f..f00ecbee 100644 --- a/Tests/SQLiteTests/Core/Connection+AttachTests.swift +++ b/Tests/SQLiteTests/Core/Connection+AttachTests.swift @@ -2,14 +2,14 @@ import XCTest import Foundation @testable import SQLite -#if canImport(sqlite3) +#if StandaloneSQLite import sqlite3 -#elseif canImport(SQLCipher) +#elseif SQLCipher import SQLCipher -#elseif canImport(SwiftToolchainCSQLite) +#elseif SwiftToolchainCSQLite import SwiftToolchainCSQLite #else -import SQLite3 +import SQLite3 // SystemSQLite #endif class ConnectionAttachTests: SQLiteTestCase { diff --git a/Tests/SQLiteTests/Core/ConnectionTests.swift b/Tests/SQLiteTests/Core/ConnectionTests.swift index b267eba9..2384f921 100644 --- a/Tests/SQLiteTests/Core/ConnectionTests.swift +++ b/Tests/SQLiteTests/Core/ConnectionTests.swift @@ -3,14 +3,14 @@ import Foundation import Dispatch @testable import SQLite -#if canImport(sqlite3) +#if StandaloneSQLite import sqlite3 -#elseif canImport(SQLCipher) +#elseif SQLCipher import SQLCipher -#elseif canImport(SwiftToolchainCSQLite) +#elseif SwiftToolchainCSQLite import SwiftToolchainCSQLite #else -import SQLite3 +import SQLite3 // SystemSQLite #endif class ConnectionTests: SQLiteTestCase { @@ -445,12 +445,23 @@ class ConnectionTests: SQLiteTestCase { semaphores.forEach { $0.wait() } } - #if SQLITE_SWIFT_STANDALONE - func test_standalone_version_is_recent() throws { - // when building standalone (= pod), we should have a more recent version + func test_compiled_sqlite_version() throws { let conn = try Connection(.inMemory) let version = conn.sqliteVersion - XCTAssertGreaterThanOrEqual(version, .init(major: 3, minor: 51)) + + #if SystemSQLite + XCTAssertGreaterThanOrEqual(version, .init(major: 3, minor: 43, point: 2)) + #elseif SwiftToolchainCSQLite + // 1.0.7 uses SQLite 3.50.4 + XCTAssertGreaterThanOrEqual(version, .init(major: 3, minor: 50, point: 4)) + #elseif SQLCipher + // 4.12.0 uses SQLite 3.51.1 + // 4.10.0 uses SQLite 3.50.4 (last available pod) + XCTAssertGreaterThanOrEqual(version, .init(major: 3, minor: 50, point: 4)) + #elseif StandaloneSQLite + // when building standalone (= pod), we should have a more recent version + // https://github.com/clemensg/sqlite3pod + XCTAssertGreaterThanOrEqual(version, .init(major: 3, minor: 51, point: 1)) + #endif } - #endif } diff --git a/Tests/SQLiteTests/Core/ResultTests.swift b/Tests/SQLiteTests/Core/ResultTests.swift index ff0d51f3..735c13b3 100644 --- a/Tests/SQLiteTests/Core/ResultTests.swift +++ b/Tests/SQLiteTests/Core/ResultTests.swift @@ -2,14 +2,14 @@ import XCTest import Foundation @testable import SQLite -#if canImport(sqlite3) +#if StandaloneSQLite import sqlite3 -#elseif canImport(SQLCipher) +#elseif SQLCipher import SQLCipher -#elseif canImport(SwiftToolchainCSQLite) +#elseif SwiftToolchainCSQLite import SwiftToolchainCSQLite #else -import SQLite3 +import SQLite3 // SystemSQLite #endif class ResultTests: XCTestCase { diff --git a/Tests/SQLiteTests/Core/StatementTests.swift b/Tests/SQLiteTests/Core/StatementTests.swift index c4136091..f3980b89 100644 --- a/Tests/SQLiteTests/Core/StatementTests.swift +++ b/Tests/SQLiteTests/Core/StatementTests.swift @@ -1,14 +1,14 @@ import XCTest @testable import SQLite -#if canImport(sqlite3) +#if StandaloneSQLite import sqlite3 -#elseif canImport(SQLCipher) +#elseif SQLCipher import SQLCipher -#elseif canImport(SwiftToolchainCSQLite) +#elseif SwiftToolchainCSQLite import SwiftToolchainCSQLite #else -import SQLite3 +import SQLite3 // SystemSQLite #endif class StatementTests: SQLiteTestCase { diff --git a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift index 402498b4..2592b473 100644 --- a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift +++ b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift @@ -1,12 +1,12 @@ import XCTest -#if canImport(sqlite3) +#if StandaloneSQLite import sqlite3 -#elseif canImport(SQLCipher) +#elseif SQLCipher import SQLCipher -#elseif canImport(SwiftToolchainCSQLite) +#elseif SwiftToolchainCSQLite import SwiftToolchainCSQLite #else -import SQLite3 +import SQLite3 // SystemSQLite #endif @testable import SQLite From e2472270ab216fe73085b28c64f722a7103004bc Mon Sep 17 00:00:00 2001 From: Jan Berkel Date: Tue, 13 Jan 2026 20:59:43 +0100 Subject: [PATCH 06/14] Use traits for package test --- .github/workflows/build.yml | 4 ++-- Tests/SPM/Package.swift | 15 +++++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 402da31e..f4aedfb3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,7 +17,7 @@ jobs: runs-on: ${{ matrix.os }} env: IOS_SIMULATOR: ${{ matrix.os == 'macos-15' && 'iPhone 16' || 'iPhone 16e' }} - IOS_VERSION: ${{ matrix.os == 'macos-15' && '18.4' || '26.2' }} + IOS_VERSION: ${{ matrix.os == 'macos-15' && '18.4' || '26.0' }} steps: - uses: actions/checkout@v4 - name: "Lint" @@ -71,7 +71,7 @@ jobs: sudo apt-get update -qq sudo apt-get install -y libsqlite3-dev - name: Test - run: swift test + run: swift test --traits SwiftToolchainCSQLite - name: "Run tests (SPM integration test)" env: SPM: run diff --git a/Tests/SPM/Package.swift b/Tests/SPM/Package.swift index a5a4afc4..461cdc94 100644 --- a/Tests/SPM/Package.swift +++ b/Tests/SPM/Package.swift @@ -1,19 +1,26 @@ -// swift-tools-version:5.7 +// swift-tools-version:6.1 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription +let traits: Set +#if os(Linux) +traits = ["SwiftToolchainCSQLite"] +#else +traits = [.defaults] +#endif + let package = Package( name: "test", platforms: [ - .iOS(.v11), + .iOS(.v12), .macOS(.v10_13), .watchOS(.v4), - .tvOS(.v11) + .tvOS(.v12) ], dependencies: [ // for testing from same repository - .package(path: "../..") + .package(path: "../..", traits: traits) // normally this would be: // .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.4") ], From d238192010377dc4dac91948f157e631e9df1652 Mon Sep 17 00:00:00 2001 From: Jan Berkel Date: Tue, 13 Jan 2026 21:07:34 +0100 Subject: [PATCH 07/14] Specify traits for Android --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f4aedfb3..16814bec 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -85,3 +85,5 @@ jobs: with: # Ubuntu runners low on space causes the emulator to fail to install free-disk-space: true + swift-build-flags: --traits SwiftToolchainCSQLite + swift-test-flags: --traits SwiftToolchainCSQLite From 8803370f958dbc4326cc0026643a0853af19e330 Mon Sep 17 00:00:00 2001 From: Jan Berkel Date: Tue, 13 Jan 2026 21:08:42 +0100 Subject: [PATCH 08/14] Fix version --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 16814bec..9061626d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,7 +17,7 @@ jobs: runs-on: ${{ matrix.os }} env: IOS_SIMULATOR: ${{ matrix.os == 'macos-15' && 'iPhone 16' || 'iPhone 16e' }} - IOS_VERSION: ${{ matrix.os == 'macos-15' && '18.4' || '26.0' }} + IOS_VERSION: ${{ matrix.os == 'macos-15' && '18.4' || '26.0.1' }} steps: - uses: actions/checkout@v4 - name: "Lint" From 45b1379590e48ecc5f4b2eb09c098090f1137435 Mon Sep 17 00:00:00 2001 From: Jan Berkel Date: Tue, 13 Jan 2026 21:14:39 +0100 Subject: [PATCH 09/14] 18.4 no longer available --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9061626d..599df7e4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,7 +17,7 @@ jobs: runs-on: ${{ matrix.os }} env: IOS_SIMULATOR: ${{ matrix.os == 'macos-15' && 'iPhone 16' || 'iPhone 16e' }} - IOS_VERSION: ${{ matrix.os == 'macos-15' && '18.4' || '26.0.1' }} + IOS_VERSION: ${{ matrix.os == 'macos-15' && '18.5' || '26.0.1' }} steps: - uses: actions/checkout@v4 - name: "Lint" From 6a3eb3068a10c93a97cbddd5d02aafe01719965d Mon Sep 17 00:00:00 2001 From: Jan Berkel Date: Tue, 13 Jan 2026 21:23:51 +0100 Subject: [PATCH 10/14] Test flag not needed --- .github/workflows/build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 599df7e4..2090c571 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -86,4 +86,3 @@ jobs: # Ubuntu runners low on space causes the emulator to fail to install free-disk-space: true swift-build-flags: --traits SwiftToolchainCSQLite - swift-test-flags: --traits SwiftToolchainCSQLite From 68edecd1638e4896599155508af7d83ec61b0ff0 Mon Sep 17 00:00:00 2001 From: Jan Berkel Date: Tue, 13 Jan 2026 23:19:04 +0100 Subject: [PATCH 11/14] Print available simulators --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2090c571..36e34be2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,6 +20,8 @@ jobs: IOS_VERSION: ${{ matrix.os == 'macos-15' && '18.5' || '26.0.1' }} steps: - uses: actions/checkout@v4 + - name: "xcrun simctl list" + run: "xcrun simctl list" - name: "Lint" run: make lint - name: "Run tests (PACKAGE_MANAGER_COMMAND: test)" From 1af0c64242d60a7b9b4aa89c6c69def38f47f6e6 Mon Sep 17 00:00:00 2001 From: Jan Berkel Date: Tue, 13 Jan 2026 23:56:11 +0100 Subject: [PATCH 12/14] Document traits --- Documentation/Index.md | 23 +++++++++++++++++++++++ Documentation/Linux.md | 15 +++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/Documentation/Index.md b/Documentation/Index.md index f61ad1b0..27deb366 100644 --- a/Documentation/Index.md +++ b/Documentation/Index.md @@ -119,6 +119,29 @@ process of downloading, compiling, and linking dependencies. $ swift build ``` +#### Available traits + +The Swift package manager now supports [traits][], which can be used to configure +SQLite.swift for different use cases. + + ```swift + dependencies: [ + .package(url: "https://github.com/stephencelis/SQLite.swift.git", + from: "0.15.4", + traits: ["XXX"]) + ] + ``` + +| Trait | Description | +|--------------------------|---------------------------------------------------| +| `SystemSQLite` (default) | Uses the system SQLite (provided by Apple) | +| `SwiftToolchainCSQLite` | Embeds the SQLite provided by [swift-toolchain][] | +| `StandaloneSQLite` | Only used by CocoaPods | +| `SQLCipher` | Embeds [SQLCipher][] (see below) | + +[traits]: https://docs.swift.org/swiftpm/documentation/packagemanagerdocs/packagetraits/ +[swift-toolchain]: https://github.com/swiftlang/swift-toolchain-sqlite + #### Using SQLite.swift with SQLCipher If you want to use [SQLCipher][] with SQLite.swift you can specify the `SQLCipher` trait when consuming SQLite.swift. diff --git a/Documentation/Linux.md b/Documentation/Linux.md index 0c88ff5c..5f84fa13 100644 --- a/Documentation/Linux.md +++ b/Documentation/Linux.md @@ -5,6 +5,21 @@ * Custom functions/aggregations are currently not supported and crash, caused by a bug in Swift. See [#1071](https://github.com/stephencelis/SQLite.swift/issues/1071). +## Installation + +On Linux you should enable the `SwiftToolchainCSQLite` trait to automatically +embed SQLite: + + ```swift + dependencies: [ + .package(url: "https://github.com/stephencelis/SQLite.swift.git", + from: "0.15.4", + traits: ["SwiftToolchainCSQLite"]) + ] + ``` + +See the [main documentation](Index.md#available-traits) for a list of all available traits. + ## Debugging ### Create and launch docker container From ae132d186dc0f526a39e56d9ff81d656ed962294 Mon Sep 17 00:00:00 2001 From: Jan Berkel Date: Wed, 14 Jan 2026 00:10:34 +0100 Subject: [PATCH 13/14] Update pod repo --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 36e34be2..df31a619 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,6 +22,8 @@ jobs: - uses: actions/checkout@v4 - name: "xcrun simctl list" run: "xcrun simctl list" + - name: Update pod repo + run: pod repo update - name: "Lint" run: make lint - name: "Run tests (PACKAGE_MANAGER_COMMAND: test)" From 5ae282e785438a1797723e9946dd57b08184a6f7 Mon Sep 17 00:00:00 2001 From: Jan Berkel Date: Wed, 14 Jan 2026 01:02:37 +0100 Subject: [PATCH 14/14] The CI pulls an old version of SQLCipher --- Tests/SQLiteTests/Core/ConnectionTests.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tests/SQLiteTests/Core/ConnectionTests.swift b/Tests/SQLiteTests/Core/ConnectionTests.swift index 2384f921..ea0df2d0 100644 --- a/Tests/SQLiteTests/Core/ConnectionTests.swift +++ b/Tests/SQLiteTests/Core/ConnectionTests.swift @@ -457,7 +457,8 @@ class ConnectionTests: SQLiteTestCase { #elseif SQLCipher // 4.12.0 uses SQLite 3.51.1 // 4.10.0 uses SQLite 3.50.4 (last available pod) - XCTAssertGreaterThanOrEqual(version, .init(major: 3, minor: 50, point: 4)) + // ??? uses SQLite 3.39.4 + XCTAssertGreaterThanOrEqual(version, .init(major: 3, minor: 39, point: 4)) #elseif StandaloneSQLite // when building standalone (= pod), we should have a more recent version // https://github.com/clemensg/sqlite3pod