Fixing the build of GRDB on Linux #1821
Replies: 6 comments 30 replies
-
|
Thank you @thinkpractice. I don't remember now why we do not use a plain |
Beta Was this translation helpful? Give feedback.
-
|
Small question: what |
Beta Was this translation helpful? Give feedback.
-
|
I've been working now on getting the tests to compile. It seems some compiler directives are not necessary any more on Linux or can easily be changed to make the tests compile and succeed on Linux. There are a couple of CGFloat
#if canImport(CoreGraphics)to: #if canImport(CoreGraphics)
import CoreGraphics
#elseif os(Linux)
import Foundation
#endifDecimal
I tested these changes with swift 6.1 and swift 6.2. Note: swift 6.0 doesn't build. Which versions would be relevant to support? NSString, NSDate, DateSome foundation Removed
NSNumberThere's a problem with the following code in public static func fromDatabaseValue(_ dbValue: DatabaseValue) -> Self? {
switch dbValue.storage {
case .int64(let int64):
return self.init(value: int64)
case .double(let double):
return self.init(value: double)
case let .string(string):
// Must match Decimal.fromDatabaseValue(_:)
guard let decimal = Decimal(string: string, locale: posixLocale) else { return nil }
return NSDecimalNumber(decimal: decimal) as? Self
default:
return nil
}
}both the not sure yet what to do here, tried replacing it by UPDATE I was able to fix the above by a kind of hackish approach like this: public static func fromDatabaseValue(_ dbValue: DatabaseValue) -> Self? {
switch dbValue.storage {
case .int64(let int64):
let number = NSNumber(value: int64)
return number as? Self
case .double(let double):
let number = NSNumber(value: double)
return number as? Self
case .string(let string):
// Must match Decimal.fromDatabaseValue(_:)
guard let decimal = Decimal(string: string, locale: posixLocale) else { return nil }
return NSDecimalNumber(decimal: decimal) as? Self
default:
return nil
}
}The It looks like the main issue to begin with is that All tests in
However, in:
There are several failures:
These fail because the
but then:
fail. The last assertion: XCTAssertTrue(try roundTrip(NSNumber(value: Double(10000000.01))))in both test cases then fails, due to a precision error ( UPDATE 2 Ok could solve it: 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):
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):
let number = NSNumber(value: double)
return number as? Self
case .string(let string):
// Must match Decimal.fromDatabaseValue(_:)
guard let decimal = Decimal(string: string, locale: posixLocale) else { return nil }
return NSDecimalNumber(decimal: decimal) as? Self
default:
return nil
}
}
}But now I feel like I need a shower 😉 NSURLThe /// Returns a TEXT database value containing the absolute URL.
public var databaseValue: DatabaseValue {
#if os(Linux)
absoluteString.databaseValue
#else
absoluteString?.databaseValue ?? .null
#endif
}UUID
public static func fromDatabaseValue(_ dbValue: DatabaseValue) -> Self? {
switch dbValue.storage {
case .blob(let data) where data.count == 16:
return data.withUnsafeBytes {
self.init(uuidBytes: $0.bindMemory(to: UInt8.self).baseAddress)
}
case .string(let string):
return self.init(uuidString: string)
default:
return nil
}
}The This could be fixed with a guard statement. However, similarly to the case for UPDATE 3 Fixed it and its unittests with: public static func fromDatabaseValue(_ dbValue: DatabaseValue) -> Self? {
switch dbValue.storage {
case .blob(let data) where data.count == 16:
return data.withUnsafeBytes {
#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 NSUUID(uuidString: string) as? Self
default:
return nil
}
}TODOs
With this we: |
Beta Was this translation helpful? Give feedback.
-
|
@groue I've been looking into the next issue with the tests on Linux and I found one that is harder to fix. Mostly, because I'm not very familiar with the func testDefaultLabel() throws {
let dbPool = try makeDatabasePool()
dbPool.writeWithoutTransaction { db in
XCTAssertEqual(db.configuration.label, nil)
XCTAssertEqual(db.description, "GRDB.DatabasePool.writer")
// This test CAN break in future releases: the dispatch queue labels
// are documented to be a debug-only tool.
let label = String(utf8String: __dispatch_queue_get_label(nil))
XCTAssertEqual(label, "GRDB.DatabasePool.writer")
Do I understand correctly that |
Beta Was this translation helpful? Give feedback.
-
NSErrorBridging of #if !os(Darwin)
func testNSErrorBridging() throws {
let dbQueue = try makeDatabaseQueue()
try dbQueue.inDatabase { db in
try db.create(table: "parents") { $0.column("id", .integer).primaryKey() }
try db.create(table: "children") { $0.belongsTo("parent") }
do {
try db.execute(sql: "INSERT INTO children (parentId) VALUES (1)")
} catch let error as NSError {
XCTAssertEqual(DatabaseError.errorDomain, "GRDB.DatabaseError")
XCTAssertEqual(error.domain, DatabaseError.errorDomain)
XCTAssertEqual(error.code, 787)
XCTAssertNotNil(error.localizedFailureReason)
}
}
}
#endif |
Beta Was this translation helpful? Give feedback.
-
|
@groue @marcprux Just a short update. I'm preparing a document with all the changes that I made so far. This will serve as the documentation for the PR I'm going to submit. I need to create a new fork as I think I didn't fork the code properly the first time. This will also allow me to check whether all changes I've made are properly documented. I hope to finish this before next week as I will be travelling the next two weeks (SwiftLeeds 🥳) @groue did you make any progress with adding a non-Darwin/Linux clause to @marcprux just a small question, when would you use |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi there,
I really like
GRDBand theSQLiteDatapackage PointFree has built on top of it and I would like to use them both on Linux. I had already made some quick changes to GRDB to make it work on Linux a while back, but now I'm looking into making these changes in a "proper" way so they can contributed back toGRDB.Most of
GRDBactually builds on Linux just fine. The only change is that I needed to do to make it build was adding ato handle non-Sendable protocol conformance in
GRDB/Core/DispatchQueueActor.swift. Not sure if that's the right approach but it made everything build!The problem after that is linking. The standard
libsqlite3-devinstalled withaptordnfdoesn't have WAL enabled and when trying to useGRDBin another swift package or app in Linux, you get a linker error. Functions likesqlite3_snapshot_get,sqlite3_snapshot_openare not found.There would be two ways around it I think, either:
GRDBon Linux, orI chose the latter for now as it is a more easy fix. I updated the following conditional compilation directive:
#if SQLITE_ENABLE_SNAPSHOT || (!GRDBCUSTOMSQLITE && !GRDBCIPHER)to:
#if (SQLITE_ENABLE_SNAPSHOT || (!GRDBCUSTOMSQLITE && !GRDBCIPHER)) && !os(Linux)This compiler directive is present (and updated) in the following files:
GRDB/Core/DatabasePool.swiftGRDB/Core/DatabaseSnapshotPool.swiftGRDB/Core/WALSnapshot.swiftGRDB/Core/WALSnapshotTransaction.swiftGRDB/ValueObservation/Observers/ValueConcurrentObserver.swiftUpdating the compiler directive as above will fix the build with the standard
libsqlite3-devon Linux. If that's fine we can keep it at that. I'm not completely sure yet what WAL does but if I understand correctly, using it is mostly a performance consideration. If it would be a nice to have on Linux too, I can research adding a customsqlitebuild for Linux with WAL enabled. I wonder why it is not included in the standardlibsqlite3-devthough?Adding the changes above will fix linking of the
GRDBcode. The build of the tests does fail however. I also fixed that build but now have a lot of failing tests. I will describe the details in a next posts in this thread.Beta Was this translation helpful? Give feedback.
All reactions