Migrating from Cocoapods to Swift Package Manager



Cocoapods is considered the most popular dependency manager for iOS. In recent years, Apple has been working on the development of its native Swift Package Manager (SPM) dependency manager.

Initially, its use was only possible for server-side Swift or terminal applications. SPM was run and modified on such applications, the community got acquainted with its work, and the Apple team received beta testers.

With the release of Xcode 11, SPM began to come into the world of development for iOS. Now it is already a full-fledged tool that can be used, but so far with limitations.

In the current version, SPM does not support resources (we are waiting for SE-0271 ). In our country, each module is an atomic self-sufficient dependency that can be connected to the project, so resources are needed (localization, assets).

In the meantime, we can prepare for migration: to understand how difficult it is, whether it can be automated and what problems you may encounter.

Why migrate from Cocoapods to SPM?


  • Nativeness and integration into the ecosystem. Already, Xcode is proposing to create or add an SPM Package.
  • Unlike Cocoapods, it is no longer necessary to have a workspace to work on a dependency project.
  • After adding a new dependency, you do not need to do pod install and rebuild the entire project.
  • It is convenient to use local dependencies: the folder structure does not change, it is rebuilt faster.
  • SPM , Cocoapods, Ruby ( iOS-).
  • Cocoapods Xcode Swift.
  • Example : Xcode Package.swift .
  • abstract_target: SPM .
  • blame , .
  • Ruby, .

?


If your project has a lot of dependencies, then the migration process cannot be completed in one day. The number of dependencies in the Podfile is not equal to the total number of dependencies, since one dependency can come with ten more. Even if you do not have many dependencies, but you develop your dependencies, it is possible, even in private repositories, not to migrate quickly. Fortunately, SPM gets along well with Cocoapods, and the migration process can be iterated. The main thing is to take into account the nuances:

  • There should be no intersections between the SPM and Cocoapods dependencies.
  • Migration should be integrated into the component development process. If the component is developing, a version upgrade should be performed for both Cocoapods and SPM.
  • There should not be any difficulties for the team, which means that you need to implement the installation of all the dependencies through a single cli-command.
  • Migration must be built into the CI CD. The project must be built both locally and on CI agents, in all configurations.

Where to begin?


First of all, we collect a complete list of your dependencies - it is presented in Podfile.lock. You can use utilities such as SPMReady .



Next, we group them by relationship. For example, almost all components depend on SMENetwork, which means that we will not be able to migrate them to SPM until SMENetwork itself migrates.

Then we select one module, on which most of the modules depend - SMENetwork.
Finally, go to the repository of this module, check it into a folder and create a module in the root of this folder.

git clone ssh://.../smenetwork.git Developer/SMENetwork
cd Developer/SMENetwork
swift package init
Creating library package: SMENetwork
Creating Package.swift
Creating Sources/
Creating Sources/SMENetwork/SMENetwork.swift
Creating Tests/
Creating Tests/LinuxMain.swift
Creating Tests/SMENetworkTests/
Creating Tests/SMENetworkTests/SMENetworkTests.swift
Creating Tests/SMENetworkTests/XCTestManifests.swift

As a result, we get the main Package.swift file and the Sources and Tests folders. If you already had them, they will not grind. The files SMENetwork.swift, SMENetworkTests.swift, XCTestManifests.swift, LinuxMain.swift were created for the Package operation example, they can be deleted.

The Package.swift file looks like this:



Now let's look at the SMENetwork.podspec file:



As you can see, Sources and Tests are in other folders. Transfer the files and test the Cocoapods Example project.



We add the development platform to Package.swift and transfer the dependencies from the podspec file here. We make sure that they support SPM: just check that there is a Package.swift file in Github. If he is not there and there is not even a PR with him, we will do a PR and help the Open-Source community.





For SPM, you do not need to create an Example project: just open Package.swift in Xcode and it will download and connect the dependencies, create the targets according to our specification. We can only run.



In our case, almost everything worked out of the box, with the exception of one place where import Foundation forgot: iOS developers are used to the fact that UIKit and Foundation are optional, because it works without them. It's time to unlearn this habit.



Package compiles, tests compile, but fail.



And here we run into a limitation of the lack of resources in Package, the tests are based on the moks that lie in json, we are waiting for SE-0271 ...

Total


Switching from Cocoapods to SPM is easy. The steps are clear, but flow is monotonous and requires automation.

Without much effort, you can create a Package from the .podspec file and commit it to the repository. And most importantly - you can move with one project, and the other will remain on Cocoapods. If he wants, of course.

All Articles