readium / swift-toolkit

A toolkit for ebooks, audiobooks and comics written in Swift
https://readium.org/mobile/
BSD 3-Clause "New" or "Revised" License
263 stars 107 forks source link

Support for Swift Package Manager #223

Closed mickael-menu-mantano closed 3 years ago

mickael-menu-mantano commented 4 years ago

Xcode 11 finally brought native support for SPM, including iOS!

As the official package manager for iOS development, this should be the default choice used in Readium projects.

I think this could also simplify the build settings of the test app, that are right now split between Carthage and submodules. We could maybe use only SPM, setup either with a direct path to the submodules or with the URLs to the Git repositories.

mickael-menu-mantano commented 4 years ago

It might still be too early unfortunately... There's still no support for packaging resources, but a proposal is under discussion.

Readium relies on resources, for example localized strings in LCP and the navigator, and scripts in the navigator.

mickael-menu commented 4 years ago

Looks like resources in SPM are finally supported in Swift 5.3:

We might be able to deprecate CocoaPods and Carthage 🕺

jccr commented 4 years ago

@mickael-menu I've been patiently awaiting resource bundle equivalents in SPM. This is great news.

Truck3r commented 3 years ago

Any progress on support for SPM? 🤞

mickael-menu commented 3 years ago

@Truck3r Nope, personally I didn't have time to start with SPM. If you would like to help, I think we need to tackle these things:

  1. Go over all the dependencies of R2 modules and list the ones that are SPM-ready and the ones that aren't.
  2. Find a solution for the ones that aren't: forking is a possibility, or looking for an alternative that works with SPM.
  3. Integrate the SPM-ready dependencies and set up a Package.swift for each R2 module.
Truck3r commented 3 years ago

@mickael-menu I'd love to work on this, but being on a tight schedule I don't think I'll be able to put much time into it until Q3 this year.

stevenzeck commented 3 years ago

I went through the Cartfiles in all of the Swift modules and the results are below. Everything that is checked has a Package.swift file and supports iOS 10.0+, and the link goes directly to said Package.swift file.

There are two packages that are not SPM ready: edrlab/GCDWebServer and dexman/Minizip. For the latter, https://github.com/marmelroy/Zip might be a good option as it's also built on top of minizip

testapp

navigator

shared

streamer

opds

lcp

mickael-menu commented 3 years ago

@stevenzeck Outstanding, thanks!

GCDWebServer is already a fork under the EDRLab umbrella so we could make it SPM ready. There is this PR to get rid of the HTTP server but it requires iOS 11+. However, we could let apps needing to support iOS 10 manage the HTTP server themselves.

For marmelroy/Zip, that's a good lead. It doesn't expose the advanced functions we need in its Swift API, but if we can access the bundled minizip, we could reuse our own MinizipArchive.

There is also the private R2LCPClient.framework, but it's non-blocking for R2 modules since r2-lcp-swift doesn't depend on it anymore.

mickael-menu commented 3 years ago

The original GCDWebServer repo is currently working on SPM.

stevenzeck commented 3 years ago

I added marmelroy/Zip as a Swift package in place of dexman/Minizip, it worked without having to change a thing.

That just leaves edrlab/GCDWebServer. As @mickael-menu mentioned there is a PR in the original repository to support SPM that could be used. Another option is replacing it with something like https://github.com/apple/swift-nio.

mickael-menu commented 3 years ago

I added marmelroy/Zip as a Swift package in place of dexman/Minizip, it worked without having to change a thing.

Nice, great news!

That just leaves edrlab/GCDWebServer. As @mickael-menu mentioned there is a PR in the original repository to support SPM that could be used. Another option is replacing it with something like https://github.com/apple/swift-nio.

The GCDWebServer PR is small enough to be worth backporting into our fork to settle this quickly. Although down the line I think it would be interesting to replace it with swift-nio for iOS 10, since it's maintained by Apple AND written in Swift (GCDWebServer uses Objective-C).

stevenzeck commented 3 years ago

Yeah I think this is going to take a lot of trial and error. A "typical" Swift package doesn't have an workspace or proj at all, it relies completely on the Package.swift to know what it depends on. But in order to continue supporting Carthage and Cocoapods, I believe they require one or both of those.

Ultimately in the end, we want a standalone testapp that can add the individual modules as Swift packages rather than relying on Carthage or gitmodules (other than for development).

Questions to answer first

  1. What should be used for developer dependencies? Should we continue using Carthage (as in doing step 4 https://github.com/readium/r2-workspace-swift/tree/dev/testapp-with-lcp#setup-your-workspace) or switch to SPM? If we switch to SPM, we'll have to remove the .framework references out of Frameworks and Libraries and replace with each one's corresponding Swift package. I had tried this and had no issues whatsoever
  2. Should packages continue being distributed through Carthage? From what I've read, we seem to have a lot of issues with Carthage and building. Not to mention there are now 3 different package managers for iOS. If we don't, then we can consider removing the need for a xcodeproj for the submodules and making them "true" Swift packages. But I don't know how to integrate them that way for development purposes.

Brainstorming Steps

  1. For the testapp, shared, and streamer modules, replace dexman/Minizip with marmelroy/Zip (including Carfile and Pod). Since the former is not SPM ready, better to replace with one that is
  2. If we decide to switch to SPM for development, do what is described in step 1 above. Ensure those same dependencies are commented out in the testapp's Cartfile.
  3. Create a Package.swift file for each submodule. We can test this out by cloning the testapp outside of the workspace and add each of the submodules as Swift packages via file:///..path..to...submodule...with....swiftpackage.
mickael-menu commented 3 years ago

I would be in favor of switching from Carthage to SPM, as we get recurring issues with it.

I also noticed a few popular projects (like GRDB) dropped Carthage in favor of SPM because of issues integrating both.

So far I think SPM is a fine alternative to Carthage, but we will probably still need CocoaPods support because I believe it is used with React native and Flutter.

If we don't, then we can consider removing the need for a xcodeproj for the submodules and making them "true" Swift packages. But I don't know how to integrate them that way for development purposes.

You should be able to drag and drop the whole submodule folder in your xcworkspace to integrate it without a xcodeproj. But I think we might still need an xcodeproj for CocoaPods, not 100% sure.

mickael-menu commented 3 years ago

I think CocoaPods doesn't require an Xcode project since it generates a global one containing the sources declared in the Podspec.

Screenshot 2021-06-01 at 11 23 04

From there, could we have something like this?

From there, people could install the modules with SPM while still being able to integrate with Carthage since the dependencies declared in the xcodeproj will be the ones from the Cartfile.

The end goal should still be to deprecate Carthage, but leave some time for integrators to migrate and identify any issues with SPM.

I just tried with GEOSwift which has everything, and drag and dropping the repo folder ignores the Xcodeproj 👍

Screenshot 2021-06-01 at 11 29 43
mickael-menu commented 3 years ago

Our GCDWebServer fork is now SPM-ready with the new 3.7.0 release.

mickael-menu commented 3 years ago

SPM support is merged in all modules, under the develop branch. It will be part of the upcoming 2.1 release.

We still miss a sample integration in the test app (see https://github.com/readium/swift-toolkit/issues/188), but it's pretty straightforward. Just add the Swift Packages in Xcode using our Git repo URLs.

Thanks again to @stevenzeck who did an amazing job at clearing the path!