Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Pull Request Checklist
TL;DR This PR makes distributing the SDK as a binary Swift package possible by not exporting the interfaces of depending Swift libraries (Realm, MatrixSDKCrypto, and SwiftyBeaver). This is necessary to solve #1497.
However, it comes with drawbacks. And to understand them, I wrote what follows.
Background
When you try building this repository and ship it as a Swift binary package, it first seems to work.
However, once you try to compile your dependent project, you get linking errors: built with a different Swift version.
This happens if you build on a different machine with a different compiler version. So I added
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
(explained in Swift Library Evolution), even for the depending Pods (by adding a new rowconfig.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
in thepost_install
phase of thePodfile
). I also added the Realm, MatrixSDKCrypto, and SwiftyBeaver dependencies to the Swift package, believing this would fix the issue.Turns out the error persists. As explained briefly at 38:10 in the Binary Frameworks in Swift video, Binary Frameworks Cannot Depend on Packages.
So what we need to achieve is linking everything statically into the SDK and thus hiding it from the client. But aren't we already doing this with
use_frameworks! :linkage => :static
in thePodfile
? Turns out, not quite.Because as explained in at the top of this thread:
And thus the emitted
.swiftinterface
still containsimport Realm
(and the others)!So what we need is a way to tell Swift that we want those dependencies not exposed. But here is where the drawbacks come in.
There is a way to do such things, but the name already reveals the first drawback:
@_implementationOnly
. More precisely, the underscore at the beginning of the name, which indicates that it is not a standard yet.The general limitations of this are discussed on this Swift Forum's Thread, but two of them impact this project the most:
@testable import
does not work in conjunction with@_implementationOnly
.@_implementationOnly
as well.The first one can be resolved with a little compiler control statement trickery (providing
-D IS_TEST_RUN
using the Other Swift Flags setting in Xcode):This solution again comes with drawbacks: it breaks with the idea that tested code should be compiled the same as code running in production (although
@testable
already breaks this in a sense), and Xcode complains with 'SwiftyBeaver' inconsistently imported as implementation-only warnings.Thus, I added it only for the
SwiftyBeaver
import inMXAnalyticsDestination.swift
, because its test is the only one that broke after adding@_implementationOnly
.For the second one I did not find a solution, at least not for the special case where an extension adds protocol conformance to a type, as is done in
RLMSupport.swift
:There might also be a way to solve this, but I did not find it.
However, there is only one occurrence in the SDK where it makes use of these extensions; which I quickly refactored. But this of course drops some comfort.
Sorry for long post, but I hope it helps understanding the issue a bit better!
Additions
I made a binary package using these changes and made it available here: https://github.com/Topheee/MatrixSDK.
It builds from the branch this PR requests to merge.
It may make sense to add the Swift package to this repository as well. In contrast to the original, my GitHub action does not build for Catalyst (because I was too stupid to get it to work). But it builds the different platforms in parallel and adds debug symbols on iOS and iOS Simulator.
We might be able to merge Nio's and my action into a sensible one for this project, possibly in a follow-up PR.
Signed-off-by: Christopher Kobusch [email protected]