-
-
Notifications
You must be signed in to change notification settings - Fork 791
Updated Fixes for the Linux version of GRDB #1825
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: development
Are you sure you want to change the base?
Updated Fixes for the Linux version of GRDB #1825
Conversation
…nsion, as it compiles fine under swift 6
…tforms. Fix this.
… code. This should be only Linux, because other platforms may provide a custom build. This should be fixed in another way later because we may want to add custom sqlite builds for Linux later.
…throw an XCTSkip for these test cases. This gives a better impression how many tests are skipped on Linux/non-Darwin platforms.
…rwin platforms. Skip testNSErrorBridging on these platforms.
…nsion, as it compiles fine under swift 6
@groue I found out there's some weird behaviour with my vscode. One time tabs are converted to spaces, and then another indentation which was 4 spaces gets converted back to a tab 😠 Will need to check how to solve this. Already changed my editor settings, so either I missed some setting or it's a bug in vscode.... Found it apparently there is something like |
@groue I have been updating some more files to reflect the original formatting and make it easier for me to see my changes. Before these changes would be synced to this PR, but now I'm not seeing them anymore. Is this something that sound familiar to you? I have already tried the solution mentioned here, i.e. updating the base to the same branch and saving it. So far, this hasn't helped, and if I try it again I'm getting an error saying the base is already being updated. I will check later if I can see the changes, but if they don't show up, do you have any tips? UPDATE some of my changes are starting to show up... so I guess I it's working again. Let's see if the other changes I made later will show up as well! |
@thinkpractice I have pushed on the groue:grdb_linux_changes branch all changes of your own branch, fully rebased on the latest development branch, with all code formatting removed. I took care that all commits are attributed to you. I had to heavily amend your initial changes, so I hope I haven't broken or forgotten anything. If this branch builds as well as yours on Linux, and if you agree, maybe you could force-push this branch to yours? That will make the review, and future changes, much easier. |
@groue did you see I spend some time cleaning up the code as well? Hope you could use that. Thanks for taking care of the rest! Will take care to format my code in the right way on any future changes. I am fine with force pushing the changes to my branch if that makes things easier. I am still traveling so I cannot really test your changes now (only brought my MacBook). I will be home next weekend so then I can test everything. Hope that’s ok! |
Yes, thanks for your efforts! Now starting over from the
I hope
If you look at the new commits, you can see that they perform minimal changes. They do indeed make things much easier. I just don't know if I faithfully reported all your changes. So please take your time, check this branch on your Linux system, and make sure I did not forget anything! 🙏 |
Fixes for the Linux version of GRDB
UPDATE this PR merges some upstream changes into my fork.
This PR contains some fixes for the Linux version of GRDB, mainly these fixes include:
Foundation
on Linux and Apple platformsCombine
orNSFileCoordinator
, etc.Some of these fixes are inspired by #1708 by @marcprux. This PR attemps to make these fixes in
a platform-agnostic way so that
GRDB
will build withSPM
on more platforms than Linux alone,for instance, on Android and Windows. These patches fix the build of
GRDB
onSwift 6.1
and later.There are still some issues building on
Swift 6.0
, which I will attempt to fix later.Fixing the GRDB Build
Most of GRDB actually builds on Linux just fine. The only change is that I needed to do to make it build was adding a
to handle non-Sendable protocol conformance in
GRDB/Core/DispatchQueueActor.swift
. Not sure if that's the right approach but it made everything build!Fixing GRDB linking on Linux
The main issue with
GRDB
on Linux is actually a linker error. The standardlibsqlite3-dev
installed withapt
ordnf
doesn't have WAL enabled and when trying to useGRDB
in another swift package or app in Linux, you get a linker error. Functions likesqlite3_snapshot_get
,sqlite3_snapshot_open
are not found by the linker,and therefore the package isn't usable.
There would be two ways around it I think, either:
sqlite
build forGRDB
on 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 is a quick fix, but it would be better to change the
SQLITE_ENABLE_SNAPSHOT
to returnfalse
on Linux.Note this should be better handled as a fix to
SQLITE_ENABLE_SNAPSHOT
as later on Linux may also providea custom sqlite build to enable WAL. In those cases, the code inside these blocks should be compiled.
This compiler directive is present (and updated) in the following files:
GRDB/Core/DatabasePool.swift
GRDB/Core/DatabaseSnapshotPool.swift
GRDB/Core/WALSnapshot.swift
GRDB/Core/WALSnapshotTransaction.swift
GRDB/ValueObservation/Observers/ValueConcurrentObserver.swift
Updating the compiler directive as above will fix the build with the standard
libsqlite3-dev
on Linux. If that's fine wecan 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 custom
sqlite
build forLinux with WAL enabled. I wonder why it is not included in the standard
libsqlite3-dev
though? Adding the changes abovewill fix linking of the
GRDB
code.Fixes for open source Foundation versions
Open source versions of
Foundation
are slightly different than theFoundation
Apple bundles withXCode
. Also, somepackages, like for instance
CoreGraphics
, are not available on non-Apple platforms. Some primitive types likeCGFloat
are available on non-Apple platforms and are defined in
Foundation
. In some cases, there are also differences where ainitializer is defined as
convenience init
in open sourceFoundation
and as a normalinit
in AppleFoundation
. Thiscauses some problems with Apple specific code in some cases; it will fail to build on open source
Foundation
. InGRDB
inmany cases this code is surrounded by a
#if !os(Linux)
compiler directive. The fixes below try to solve the build issues onLinux and try to get rid of these compiler directives. Also fixing the unit tests at the same time.
CGFloat.swift
CoreGraphics
is not available on Linux. ButCGFloat
is available viaFoundation
. Changed the compiler directive inCGFloat.swift
and its test from:#if canImport(CoreGraphics)
to:
The same fix should be added to
GRDBTests/CGFloatTests.swift
.Decimal.swift
Removed the
#if !os(Linux)
compiler directive in theDecimal
extension, as it compiles fine under swift 6. As discussedwith @groue the minimum version for
GRDB
isswift 6.0
. I tested these changes withswift 6.1
andswift 6.2
and they work fine.Note: swift 6.0 doesn't build, we should look into fixing the build for this version.
NSString, NSDate, Date
Some foundation
NS*
types (NSString, NSData, Date, etc.) were excluding theDatabaseValueConvertible
extensions on Linux but build fine onswift 6.1
andswift 6.2
.Removed
#if !os(Linux)
in:NSString.swift
NSData.swift
Date.swift
NSNumber
There's a problem with the following code in
NSNumber.swift
on Linux:both the
.int64
and.double
case above do not compile. The error is the following:The
NSNumber(value: Int64)
andNSNumber(value: Double)
are marked asconvenience
init on Linux. This may cause the build to fail. The issue with this approach is that it doesn't work forNSDecimalNumber
, which is a subclass ofNSNumber
.It looks like the main issue to begin with is that
NSNumber
definesNSNumber(value: Int64)
andNSNumber(value: Double
as convenience init, whereas theirNSDecimalNumber
equivalents are non-convenience. I could solve it by changing the codeabove like this:
This is a lot more verbose than the existing code. Also, this code may fail if there are other subclasses of
NSNumber
that need to be supported. For each of these classes we should add a case for
.int64
anddouble
. I think an alternativeapproach would be better, but I don't have one at the moment.
All tests in:
Tests/GRDBTests/FoundationNSNumberTests.swift
Tests/GRDBTests/FoundationNSDecimalNumberTests.swift
succeeded with these changes.
URL.swift
The
NSURL
is a specific case. Apparently, theNSURL
absoluteString
property is non-optional on Linux and optional on Apple platforms. The fix is the following:UUID.swift
UUID.swift
contains a compiler directive excluding theDatabaseValueConvertible
from buildingon Linux and Windows. On Linux the problem is the following:
The
NSUUID(uuidBytes:)
constructor takes an optionalUnsafePointer<UInt8>
, see here, whereas this constructor on Linux takes a non-optional.This could be fixed with a guard statement. However, similarly to the case for
NSNumber
in addition, theself.init(uuidString: string)
doesn't compile on Linux. The error is:Added the following fix:
This also makes all unittests succeed. It should be checked whethere we would want to support any subclass of
NSUUID
.If so, a similar solution as for
NSNumber
above can be used.Use of DispatchQueue private APIs
In some of the tests for the
DispatchQueue
APIs, some privateDispatchQueue
apis are used to get the label of thecurrent
DispatchQueue
. These APIs are unavailable on non-Darwin platforms. It's mainly about some tests in for exampleDatabasePoolConcurrencyTests.swift
. For instance, the following test:I understood from @groue that the goal of those tests is to make sure that the Xcode, LLDB, and crash reports mention the label of the current database in the name of the current DispatchQueue. This is a nicety that aims at helping debugging, and worth a test. The label of the current dispatch queue can only be tested with the private
__dispatch_queue_get_label
api, which is only available on Darwin systems.Those tests can be avoided on non-Darwin platforms, as @marcprux did in #1708:
I implemented this approach for:
Utils.swift
DatabasePoolConcurrencyTests.swift
DatabaseQueueTests.swift
DatabaseSnapshotTests.swift
NSError
Bridging of
DatabaseError
toNSError
does not seem to work on Linux. ThetestNSErrorBridging
thereforefails, we should probably ignore the test on non-Darwin platforms as NSError is mostly a left-over from
ObjectiveC
timesand APIs.
Fixing Unit tests
Tests using NSFileCoordinator
There are some tests using
NSFileCoordinator
which is not available on non-Darwin platforms. Most notablytestConcurrentOpening
inDatabasePoolConcurrencyTests.swift
contributes 400+ test failures when run onLinux.
testConcurrentOpening
, that runs about 500 tests (a for loop of 50 iterations runs 10 times some things in parallelwith
DispatchQueue.concurrentPerform
. The test uses theNSFileCoordinator
which isn't available on Linux.These tests are ignored because they test whether
NSFileCoordinator
works withGRDB
. This isDarwin
specific functionality:Arguably
DispatchQueue.concurrentPerform
could be replaced with any other modern technique that guarantees a minimum level of parallelism, such aswithTaskGroup
.We should check whether we need to test similar behaviour on Linux. For now we just ignore the test.
@marcprux solved it like this:
We solved it similarly.
Other Unit tests
XCTIssue
is not available on non-Darwin platforms, it's used in:GRDBTests/FailureTestCase.swift
ignored this test completely with#if os(Darwin)
on non-Darwin platformsGRDBTests/ValueObservationRecorderTests.swift
ignored this test also.Support.swift
actually needsCombine
, so all tests that use it needCombine
as well:DatabaseMigratorTests.swift
has several tests using theTest
class defined inSupport.swift
; used an#if !canImport(Combine)
clause to skip several tests in this test suite.ValueObservationTests.swift
also uses thisTest
classDatabaseRegionObservationTests.swift
tests someCombine
functionality intestAnyDatabaseWriter
; also wrapped them in a#if canImport(Combine)
DatabaseMigratorTests.swift
I tried to merge them but not sure everything went ok. I was struggling a bit integrating them. This file should be checked if all upstream changes have been merged in.TODOs
swift 6.0
XCTIssue
__dispatch_queue_get_label
on LinuxCI.yml
pipeline to build the Linux version of the package automatically and run the unit testsWith this we: