Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
0526853
Fixed some linker errors caused by WAL absence on Linux.
Oct 2, 2025
2d6fe17
Import Foundation for CGFloat on non-Darwin platforms
Oct 12, 2025
7477e1c
Removed the `#if !os(Linux)` compiler directive in the `Decimal` exte…
Oct 2, 2025
e758fde
Removed #if !os(Linux) in NSString.swift, NSData.swift and Date.swift.
Oct 2, 2025
14f60ad
Fixed fromDatabaseValue build under non-Darwin platforms
Oct 12, 2025
dc7d47c
Fixed databaseValue build for non-Darwin platforms.
Oct 12, 2025
8e5b9ca
Fixed UUID fromDatabaseValue for non-Darwin platforms
Oct 2, 2025
c7f1dd7
Fixed import in CGFloatTests.swift to work under non-Darwin platforms.
Oct 12, 2025
6912075
Ignore FailureTestCase.swift entirely on non-Darwin platforms for now.
Oct 12, 2025
dd90fe6
Ignore ValueObservationRecorderTests.swift on non-Darwin platforms.
Oct 12, 2025
2ad2d20
Fixed the unit tests in DatabasePoolConcurrencyTests.
Oct 12, 2025
5513eab
Fixed the tests in DatabaseQueueTests.swift
Oct 12, 2025
2f10850
Fixed DatabaseSnapshotTests on non-darwin platforms
Oct 12, 2025
6518610
Integrated upstream changes.
Oct 12, 2025
a212bf9
It should be canImport(Darwin) not os(Darwin)
Oct 2, 2025
389c3e0
Use #if !canImport(Combine) per test case (as done by @marcprux) and …
Oct 3, 2025
d7cf0f9
NSError bridging is not available, or doesn't work the same on non-Da…
Oct 12, 2025
3dd3bbf
vscode config
Oct 12, 2025
85d39e6
Merge remote-tracking branch 'upstream/development' into grdb_linux_c…
Nov 7, 2025
5db6c36
Added a ci for ubuntu
Nov 7, 2025
c3c0275
Added the grdb_linux_changes branch to test the github actions for ub…
Nov 7, 2025
7e3d68a
swift 6.2.0 is apparently not available for setup-swift@v2
Nov 7, 2025
46fdfa8
Added a batch for the linux build. Now for the grdb_linux_changes bra…
Nov 7, 2025
dd41816
Renamed Ubuntu Linux CI to Linux CI and point the badge to the correc…
Nov 7, 2025
7775237
See if we can install swift via swiftly
Nov 7, 2025
8aaf0a6
Small change
Nov 7, 2025
6a2c9b5
Check whether this works
Nov 7, 2025
e7850f9
Removed -v flag to silence the warnings a bit
Nov 7, 2025
be47b71
Added fail-fast false to see whether the linker completes
Nov 7, 2025
a5283f5
Try to silence swiftly prompt
Nov 7, 2025
1e39d94
Fixed caching path for swiftly
Nov 7, 2025
5ba2087
Use 6.1 instead of 6.1.0 to use the latest available 6.1 version with…
Nov 7, 2025
3c98b5f
Check if matrix.os helps in caching swiftly.
Nov 7, 2025
492dbeb
Changed cancel-in-progress to false based on a comment by @marcprux
Nov 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions .github/workflows/ubuntu-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md

name: "Linux CI"

on:
push:
branches:
- master
- development
- grdb_linux_changes
paths:
- 'GRDB/**'
- 'Tests/**'
- '.github/workflows/**'
- 'Makefile'
- 'Package.swift'
- 'SQLiteCustom/src'
pull_request:
paths:
- 'GRDB/**'
- 'Tests/**'
- '.github/workflows/**'
- 'Makefile'
- 'Package.swift'
- 'SQLiteCustom/src'

concurrency:
group: ${{ github.ref_name }}
cancel-in-progress: false
permissions:
contents: read

jobs:
build-and-test-on-linux:
runs-on: ${{ matrix.os }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
swift: ["6.2", "6.1"]
steps:
- name: Checkout Repository
uses: actions/checkout@v5

- name: Install Swift Dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
binutils \
git \
gnupg2 \
libc6-dev \
libcurl4-openssl-dev \
libedit2 \
libgcc-13-dev \
libpython3-dev \
libsqlite3-0 \
libstdc++-13-dev \
libxml2-dev \
libz3-dev \
pkg-config \
python3-lldb \
tzdata \
unzip \
zip \
zlib1g-dev \
wget \
curl \
ca-certificates \
util-linux

- name: Cache Swiftly toolchains
id: cache-swiftly
uses: actions/cache@v4
with:
path: ${SWIFTLY_HOME_DIR:-$HOME/.local/share/swiftly}
key: swiftly-${{ matrix.os }}-${{ matrix.swift }}

- name: Install Swift Using Swiftly
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could alternatively just use uses: swift-actions/setup-swift@next as per swift-actions/setup-swift#710. I've been using it in other actions, and it seems quite stable.

Copy link
Author

@thinkpractice thinkpractice Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did use setup-swift@v2 before but that didn't support swift 6.2. Also, it threw some random errors with the gpg verification (?) of swift, which made the pipeline fail. UPDATE apparently this gpg issue is also mentioned here, i.e. "Investigate GPG issues on linux". That's why I decided to add the swiftly code myself. I agree it would be better to use the setup-swift action in the future. I guess then @next selects the latest v3 version that uses swiftly as well? I saw on its PR that it's not yet merged into main right?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh and I saw there's a possibility to cache the swiftly install but it seems with the current code it doesn't do anything. Not sure whether the path I added (${SWIFTLY_HOME_DIR:-$HOME/.local/share/swiftly}) is evaluated correctly or whether it's an issue with the cache action itself. @marcprux, @groue does any of you have some experience with this?

if: steps.cache-swiftly.outputs.cache-hit != 'true'
run: |
curl -O https://download.swift.org/swiftly/linux/swiftly-$(uname -m).tar.gz
tar zxf swiftly-$(uname -m).tar.gz
./swiftly init --quiet-shell-followup -y --skip-install
. "${SWIFTLY_HOME_DIR:-$HOME/.local/share/swiftly}/env.sh"
hash -r
swiftly install ${{ matrix.swift }} --assume-yes --use
. "${SWIFTLY_HOME_DIR:-$HOME/.local/share/swiftly}/env.sh"

- name: Build SPM Package
run: |
swift build -c release

- name: Run tests
run: |
swift test -c release
7 changes: 7 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might want to .gitignore this file, depending on whether @groue wants it added to the repo or not.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@groue I think we decided to keep this in the repo to prevent future issues with vscode formatting, didn't we? Otherwise I'm fine to .gitignore it.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, in that case, fine it leave it in. I wasn't following that thread closely.

"editor.formatOnSave": false,
"editor.insertSpaces": true,
"editor.tabSize": 4,
"editor.detectIndentation": false,
"editor.trimAutoWhitespace": false
}
4 changes: 4 additions & 0 deletions GRDB/Core/DispatchQueueActor.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
#if os(Linux)
@preconcurrency import Dispatch
#else
import Dispatch
#endif

/// An actor that runs in a DispatchQueue.
///
Expand Down
4 changes: 3 additions & 1 deletion GRDB/Core/Support/CoreGraphics/CGFloat.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#if canImport(CoreGraphics)
import CoreGraphics
#elseif !canImport(Darwin)
import Foundation
#endif

/// CGFloat adopts DatabaseValueConvertible
extension CGFloat: DatabaseValueConvertible {
Expand All @@ -15,4 +18,3 @@ extension CGFloat: DatabaseValueConvertible {
return CGFloat(double)
}
}
#endif
2 changes: 0 additions & 2 deletions GRDB/Core/Support/Foundation/Date.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import GRDBSQLite

import Foundation

#if !os(Linux)
/// NSDate is stored in the database using the format
/// "yyyy-MM-dd HH:mm:ss.SSS", in the UTC time zone.
extension NSDate: DatabaseValueConvertible {
Expand Down Expand Up @@ -41,7 +40,6 @@ extension NSDate: DatabaseValueConvertible {
return cast(date)
}
}
#endif

/// Date is stored in the database using the format
/// "yyyy-MM-dd HH:mm:ss.SSS", in the UTC time zone.
Expand Down
2 changes: 0 additions & 2 deletions GRDB/Core/Support/Foundation/Decimal.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#if !os(Linux)
// Import C SQLite functions
#if GRDBCIPHER // CocoaPods (SQLCipher subspec)
import SQLCipher
Expand Down Expand Up @@ -68,4 +67,3 @@ extension Decimal: StatementColumnConvertible {

@usableFromInline
let _posixLocale = Locale(identifier: "en_US_POSIX")
#endif
2 changes: 0 additions & 2 deletions GRDB/Core/Support/Foundation/NSData.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#if !os(Linux)
import Foundation

/// NSData is convertible to and from DatabaseValue.
Expand All @@ -24,4 +23,3 @@ extension NSData: DatabaseValueConvertible {
return cast(data)
}
}
#endif
14 changes: 11 additions & 3 deletions GRDB/Core/Support/Foundation/NSNumber.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#if !os(Linux) && !os(Windows)
#if !os(Windows)
import Foundation

private let integerRoundingBehavior = NSDecimalNumberHandler(
Expand Down Expand Up @@ -81,10 +81,18 @@ extension NSNumber: DatabaseValueConvertible {
/// Otherwise, returns nil.
public static func fromDatabaseValue(_ dbValue: DatabaseValue) -> Self? {
switch dbValue.storage {
case .int64(let int64) where self is NSDecimalNumber.Type:
let number = NSDecimalNumber(value: int64)
return number as? Self
case .int64(let int64):
return self.init(value: int64)
let number = NSNumber(value: int64)
return number as? Self
case .double(let double) where self is NSDecimalNumber.Type:
let number = NSDecimalNumber(value: double)
return number as? Self
case .double(let double):
return self.init(value: double)
let number = NSNumber(value: double)
return number as? Self
case let .string(string):
// Must match Decimal.fromDatabaseValue(_:)
guard let decimal = Decimal(string: string, locale: posixLocale) else { return nil }
Expand Down
2 changes: 0 additions & 2 deletions GRDB/Core/Support/Foundation/NSString.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#if !os(Linux)
import Foundation

/// NSString adopts DatabaseValueConvertible
Expand All @@ -24,4 +23,3 @@ extension NSString: DatabaseValueConvertible {
return self.init(string: string)
}
}
#endif
8 changes: 6 additions & 2 deletions GRDB/Core/Support/Foundation/URL.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import Foundation

#if !os(Linux) && !os(Windows)
#if !os(Windows)
/// NSURL stores its absoluteString in the database.
extension NSURL: DatabaseValueConvertible {

/// Returns a TEXT database value containing the absolute URL.
public var databaseValue: DatabaseValue {
absoluteString?.databaseValue ?? .null
#if !canImport(Darwin)
absoluteString.databaseValue
#else
absoluteString?.databaseValue ?? .null
#endif
}

public static func fromDatabaseValue(_ dbValue: DatabaseValue) -> Self? {
Expand Down
17 changes: 12 additions & 5 deletions GRDB/Core/Support/Foundation/UUID.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import GRDBSQLite

import Foundation

#if !os(Linux) && !os(Windows)
#if !os(Windows)
/// NSUUID adopts DatabaseValueConvertible
extension NSUUID: DatabaseValueConvertible {
/// Returns a BLOB database value containing the uuid bytes.
Expand All @@ -36,10 +36,17 @@ extension NSUUID: DatabaseValueConvertible {
switch dbValue.storage {
case .blob(let data) where data.count == 16:
return data.withUnsafeBytes {
self.init(uuidBytes: $0.bindMemory(to: UInt8.self).baseAddress)
#if canImport(Darwin)
self.init(uuidBytes: $0.bindMemory(to: UInt8.self).baseAddress)
#else
guard let uuidBytes = $0.bindMemory(to: UInt8.self).baseAddress else {
return nil as Self?
}
return NSUUID(uuidBytes: uuidBytes) as? Self
#endif
}
case .string(let string):
return self.init(uuidString: string)
return NSUUID(uuidString: string) as? Self
default:
return nil
}
Expand Down Expand Up @@ -91,8 +98,8 @@ extension UUID: StatementColumnConvertible {
self.init(uuid: uuid.uuid)
case SQLITE_BLOB:
guard sqlite3_column_bytes(sqliteStatement, index) == 16,
let blob = sqlite3_column_blob(sqliteStatement, index) else
{
let blob = sqlite3_column_blob(sqliteStatement, index)
else {
return nil
}
self.init(uuid: blob.assumingMemoryBound(to: uuid_t.self).pointee)
Expand Down
2 changes: 2 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ let darwinPlatforms: [Platform] = [
var swiftSettings: [SwiftSetting] = [
.define("SQLITE_ENABLE_FTS5"),
.define("SQLITE_ENABLE_SNAPSHOT"),
// Not all Linux distributions have support for WAL snapshots.
.define("SQLITE_DISABLE_SNAPSHOT", .when(platforms: [.linux])),
]
var cSettings: [CSetting] = []
var dependencies: [PackageDescription.Package.Dependency] = []
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<a href="https://developer.apple.com/swift/"><img alt="Swift 6.1" src="https://img.shields.io/badge/swift-6.1-orange.svg?style=flat"></a>
<a href="https://github.com/groue/GRDB.swift/blob/master/LICENSE"><img alt="License" src="https://img.shields.io/github/license/groue/GRDB.swift.svg?maxAge=2592000"></a>
<a href="https://github.com/groue/GRDB.swift/actions/workflows/CI.yml"><img alt="CI Status" src="https://github.com/groue/GRDB.swift/actions/workflows/CI.yml/badge.svg?branch=master"></a>
<a href="https://github.com/groue/GRDB.swift/actions/workflows/ubuntu-ci.yml"><img alt="Linux Status" src="https://github.com/groue/GRDB.swift/actions/workflows/ubuntu-ci.yml/badge.svg?branch=master"></a>
</p>

---
Expand Down
7 changes: 6 additions & 1 deletion Tests/GRDBTests/CGFloatTests.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import XCTest
import CoreGraphics
import GRDB

#if canImport(CoreGraphics)
import CoreGraphics
#elseif !canImport(Darwin)
import Foundation
#endif

class CGFloatTests: GRDBTestCase {

func testCGFLoat() throws {
Expand Down
4 changes: 4 additions & 0 deletions Tests/GRDBTests/DatabaseErrorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ class DatabaseErrorTests: GRDBTestCase {
}

func testNSErrorBridging() throws {
#if !canImport(Darwin)
throw XCTSkip("NSError bridging not available on non-Darwin platforms")
#else
let dbQueue = try makeDatabaseQueue()
try dbQueue.inDatabase { db in
try db.create(table: "parents") { $0.column("id", .integer).primaryKey() }
Expand All @@ -229,5 +232,6 @@ class DatabaseErrorTests: GRDBTestCase {
XCTAssertNotNil(error.localizedFailureReason)
}
}
#endif
}
}
Loading