How to move from CocoaPods to Carthage? - ios

My project has linked with like 30 different libraries. Very few of them support Carthage.
Do I need to make a branch and make them support Carthage one by one?
Is there any better way to do so?

The carthage idea is based on frameworks. So if your dependencies do not support them, carthage is unable to build them for you. Simple as that.
But: You can use carthage also to manage dependencies only by using the param "--no-build". Then carthage will only fetch the dependencies into your Carthage/Checkouts folder.
There are some drawbacks:
depending on the project you have to add the projects of each dependency to your own project, if the projects only contain a sample app you have to add the code itself
if the projects have dependencies itself carthage is only able to find them if there is a cartfile in the projects, as an alternative you may add the dependent projects to your own cartfile to avoid forking them but then you have to update the versions for yourself
developers see the code itself while work but they should handle them as read-only
...
It's possible to use carthage like that, but I wouldn't recommend it. If you need more informations about this solution read here.
Note: If you fork the projects and make them support carthage the community might be grateful. ;-)

There is no problem in having both Carthage and Cocoapods running on the same project. You can try a hybrid approach and replace the libraries step by step.
You can check this post on it. There, I make my build time 9 times faster by replacing Cocoapods with Carthage, but I discuss how some libraries were hard or impossible to replace.

Related

Package.swift together with Xcode 11 Project, how to use Carthage and SPM alongside?

I feel caught between the Carthage world and the Swift Package Manager (SPM) world, like being stuck in purgatory.
I'm developing a Swift library/SDK, and up until now, I've been using Carthage for dependencies. But since SPM finally works with iOS, I feel it would be great for people who want to use this library to be able to include it via SPM.
However, I've hit a wall. One of my dependencies, namely BitcoinKit works with Carthage but SPM support is broken.
In order to distribute my library, I need to have a Package.swift file, and some other critteria (README, source files in Sources, and tests in Tests). I also need to declare my dependencies in said Package.swift file, so that SPM recursivley can resolve all dependencies (when people install my library via SPM). Here's where I get stuck...
Since I'm still using Carthage I need a Xcode Project file to set up this Carthage dependency. But now my source files cannot import the SPM dependencies. They aren't found. Seems like I MUST include the SPM package dependencies using Xcode and Add Package Dependency feature (Apple doc here). This is not what I want right, I want my Package.swift file to declare the same versions of the SPM packages my library uses. To make it clear, this problem arises due to the fact that I need a Xcode project, due to Carthage.
So I thought maybe I could build BitcoinKit with Carthage (as I'm doing now), and include the built binary (.Carthage/Build/iOS/BitcoinKit.framework) my library, referencing it in Package.swift, but that does not work since SPM does not (yet?) support binaries (relevant Swift Forum Thread).
So what are my options?
1) Wait until someone smart fixes the broken SPM support in BitcoinKit (I've tried myself and failed), and then remove my Xcode project file and complete the transition of to only SPM and for now stick with Carthage...
2) Try to use SPM packages internally in my library installed through Xcode Add Package Dependency feature and manually sync those versions with the ones I declare in my Package.swift. Will that even work? Ugh, terrible solution anyway.
3) Hope to include BitcoinKit.framework built through Carthage as a binary when SPM supports it? When? Might take a while?
4) BitcoinKit also works with Cocoapods, but I guess that gets me nowhere, even worse actually, since Cocoapods creates a .xcworkspace file.
5) Wait until Apple hopefully (does anyone know if there are any plans?) changes so that we include Swift Packages via Package.swift file even when used together with an Xcode project file? That we I could keep on using Bitcoinkit via Carthage and only declare my SPM packages in one place and I guess SPM/Xcode/Swift would be responsible for integrating the dependencies into my Xcode project, but updated and managed through the Package.swift file...?
6) Any other alternative, real solution?
Without looking into the whole 'making bitcoinkit work with SPM' bit I think the 'linking a carthage prebuilt binary' idea sounds best as an interim solution at the very least.
It's not possible to link a binary in the package manifest (yet) but you can link it when you're building:
When building an SPM package from the command line using swift build you can link the binary using -Xswiftc or -Xlinker to pass the args -F path/to/bitcoinkit if you're linking a framework. Keep in mind each argument must have a cross argument flag before it.
When building in Xcode you should be able to solve it with an .xcconfig with the contents:
FRAMEWORK_SEARCH_PATHS = path/to/bitcoinkit
You may have to tweak it a bit but I imagine this should work, worst case having a separate .xcodeproj generated by swift package generate-xcodeproj --xcconfig-overrides myconfig.xcconfig.
There is a WalletExample in yenom/BitcoinKit on GitHub. It comes with a workspace and project.
I was able to include yenom/BitcoinKit with SPM in my Package.swift and I don't use any projects/workspaces.

What to do if a library you want to use doesn't support Carthage yet

I'm in the middle of assessing whether Carthage would be a good fit for my project and one of the questions I want to find out answers for is what to do when a library/framework I want to use doesn't have support for Carthage yet.
Have any of you had this issue and found a solution for it before?
Thanks
The main thing that Carthage needs is a Framework and for that Framework's scheme to be a "shared" scheme.
So one way to get a project to support Carthage is to fork it on GitHub and then share the scheme in Xcode and check that into your fork, then use that fork's address in your Cartfile. If you're successful at this then maybe do a Pull Request with the author of the original so your Carthage support can be grafted back into the main repository.
If the project you're wanting to use doesn't use a Framework, then you have some more work to do since the project will need refactoring but it's possible. Here's an old PDF viewer project and the Carthage support someone grafted into a fork by refactoring things into a Framework (there was some reason it wasn't accepted as a PR and now the main repo is deprecated but it'll give you some idea of what's expected)

Cocoa Touch Framework Swift with embed libraries

I am working on a suite of applications that contain common modules.
 
I want to store the common modules in a Cocoa Touch Framework.
This framework may also contain the libraries and Alamofire and SwiftyJSON because they are widely used in the modules.
 
Currently, despite the many tutorials, articles, etc. read on the internet, I cannot get a stable solution.
Is it possible to integrate the frameworks Alamofire and SwiftyJSON within the framework custom or is it better to integrate them in the different projects consuming the framework (they will also need individually) ?
 
Is it possible to generate a framework running on the simulator and on the phone (whatever methods: subproject or not, dynamic or static library, fat library) ?
You can absolutely do this. You currently have three options for setting this up for development and two options for deployment.
Development
Git Submodules
Git submodules are a great way to bring additional libraries into your project's repository to embed in your project. All you need to do is add the submodule, then drag the Xcode project of that library into your Xcode project so it's nested inside your project. Then you need to add the framework as a link target to your library.
Carthage
Carthage also supports git submodules through the --use-submodules flag. All you need to do is install carthage through homebrew, then create a Cartfile that adds Alamofire and SwiftyJSON using the following command.
carthage update --use-submodules
CocoaPods
CocoaPods is a dependency management system that allows you to easily pull in and deploy different versions of a given library. Since both Alamofire and SwiftyJSON support CocoaPods, you could create a Podfile, and run pod install to pull the pods into your library. I would not recommend this though as this is a pretty heavy weight approach. Instead, I would recommend using either Git Submodules or Carthage for development.
Deployment
Deployment is a MUCH different situation. Currently, there are two fairly robust deployment mechanisms for iOS and OSX that are in wide use in the OSS community (including Alamofire and Carthage).
Carthage
If you imported your git submodules using Carthage, then you may already be completely supporting Carthage deployments. It depends on whether you used a Cartfile.private file to pull in your dependencies. Given what you're trying to do, I doubt that you would use a private Cartfile and would instead use the public one. This means that you should be good to go right out of the box. Awesome!
CocoaPods
CocoaPods is much different than Carthage and has some big advantages over Carthage, at a cost. You need to create a podspec file and push that into a public or private spec repo. Then anyone can pull your pod into their project using a Podfile.
Summary
As you can see, there are MANY options here. I would highly recommend using Carthage to pull in your git submodules, then supporting both Carthage and CocoaPods for deployment. I know that's a lot of effort though, so you may want to focus on one or the other. Sorry for the massive amount of links and information, but you question leads me to believe that you would greatly benefit from all these various sources.
Hopefully that helps get you on your way to becoming a dependency development and deployment ninja.

Combine Cocoapods and Carthage

I'm creating a Swift framework that is dependent on several other third party frameworks. Both these other frameworks support Carthage and Cocoapods.
Is there any way I can make my own framework support installing using both Carhage and Cocoapods? Or is just not achievable and should I just pick one?
You can definitely make your framework available with both CocoaPods and Carthage. This is the path that I would recommend to allow your users to use whatever solution they prefer. Also note that setting a framework up to work with Carthage also makes it much easier for users who want to use your library without either of these solutions.
On a high level, for CocoaPods you'll want to create a podspec that lists your dependencies there. This way CocoaPods will manage downloading and configuring them along with resolving them against other user dependencies. See more here.
For Carthage you'll want to configure your project with framework targets for the platforms you support and add your dependencies in your Cartfile. More on that here
Combining both is actually not difficult. With my framework I have started with CocoaPods template containing Example and Pod directories. In the example project I created a new Cocoa Touch Framework target, made sure this target is Shared (in Product - Schemes - Managed Schemes) and dragged content of my Pod/Classes directory to the project (with unchecked Copy items if needed and added Target Membership only to this newly created framework).
This should be enough, Carthage should find this shared scheme and use it. Just keep in mind you have to commit changes and create a new git tag before using your framework from Carthage.

How to install projects without cocoa pods?

I have seen various libraries on GitHub that look useful, but only list CocoaPods as an install method. I'm not sure I want to be dependent on CocoaPods, because I'm wary of Apple breaking it in some future OS X/Xcode update. Is there a way to get these libraries into my Xcode project without using CocoaPods?
Role of CocoaPods is to automate and simplify the process, but you don't need to use CocoaPods if you don't want to.
In case of "manual installation", usually it would be:
download the project from GitHub
add the files to Xcode
import headers
But there is no universal recipe for every project, it may slightly differ from case to case, but usually it boils down to previously mentioned.
The best way if you don't want to use CocoaPods is to read the project documentation, and study examples if there are any.
Of course there is. Basically you need to download the library project, drag the project into your own project, do some library dependency setup and you're done.
For details, check out https://github.com/Alamofire/Alamofire for manually adding a Swift library. And https://github.com/jverkoey/ObjQREncoder for manually adding a Objective-C library to your project.
The only way to install things without Cocoapods is to just drag the source code of other projects into your class. For example, most Github projects can be installed via Cocoapods, or you can just drag the relevant source code into your projects. You don't need to drag in all of the project resources, all you need is usually class files

Resources