Streamlining Dependencies: How to support both CocoaPods and Swift Package Manager with iOS Tuist

iOS Jun 7, 2024

At Halodoc, our objective is to uphold clean and comprehensible code while minimizing the complexity of managing dependencies. Last year, we migrated our project from Cocoapods to SPM using Tuist. However, one of our vendor's libraries does not support SPM. Consequently, we enabled Cocoapods alongside SPM to accommodate this requirement.

Why we should not keep multiple dependency manager in our project

We should avoid using multiple dependency managers in an iOS project because it simplifies development, ensures consistency, reduces conflict risks, improves performance, eases onboarding, streamlines CI/CD pipelines, and enhances security. Relying on a single dependency manager makes the project more efficient and easier to maintain.

Challenges and Options

We encountered a situation where we needed to use a Vendor SDK that supported CocoaPods only due to certain limitations. Since Tuist environment doesn't directly support CocoaPods, we had the following options:

Option 1: Carthage

Carthage When one of our vendor's libraries didn't support SPM, our initial inclination was to opt for Carthage since Tuist environment inherently supports Carthage over CocoaPods. However, this particular library didn't support Carthage either.

Option 2:  Add dependency manually

Integrate the SDK manually into the code. Carthage facilitates this process by building the library and offering a compiled framework. However, we couldn't directly use the SDK because our vendor provided separate SDKs for the simulator and device. Consequently, with this option, we had to add two SDKs, resulting in a doubling of the SDK's size.

Option 3: Enable Cocoapods with Tuist

This was the optimal and sole option available to us with this library. After carefully assessing all alternatives, we concluded that employing CocoaPods alongside SPM was the most suitable approach.

What is Tuist

Tuist is a well-known Xcode project generation tool. It provides basic features such as Xcode project generation, dependency graph, pre- and post-actions, and many more benefits like manifest file linting and build time improvement via caching. Previously, Tuist natively supported SPM, Carthage, and Cocoapods. However, they dropped Cocoapods support starting from version 3.

Challenges of Tuist with Cocoapods

CocoaPods and SPM utilize different FRAMEWORK_SEARCH_PATHS, HEADER_SEARCH_PATHS, and LD_RUNPATH_SEARCH_PATHS. Therefore, when we added dependencies via SPM and CocoaPods, we encountered difficulties importing libraries added via CocoaPods. This discrepancy is the primary reason why supporting both CocoaPods and the Swift Package Manager was not straightforward and necessitated some adjustments.

How to enable both SPM and Cocoapods

As agreed, our project initially utilized SPM as the dependency manager. Now, let's delve into how we enabled CocoaPods alongside SPM.

Main Idea:  tuist install -> tuist generate --no-open -> pod install

Step 1: Create a Podfile

Open a terminal and navigate to the project repository. Then, execute the command pod init. This will generate a text file named Podfile in the Xcode project directory.

Step 2: Add dependencies in Podfile

Step 3: Install SPM dependencies then install Cocoapods dependencies

Following that, we utilized Tuist to generate the project and subsequently ran pod install to integrate the dependencies. This action created a workspace containing both our project and the Pods dependencies. To streamline this process, we encapsulated these steps in a script within the Makefile, which we executed prior to generating the project.

NOTE: We are using V4 for Tuist.

Makefile

tuist install For resolving and fetching dependencies.

tuist generate For doing Build setting and generating a workspace.

pod install For installing Cocoapods dependencies.

When we opened the workspace, we were still unable to import the library into the class. Therefore, we updated the FRAMEWORK_SEARCH_PATHS and HEADER_SEARCH_PATHS in configuration file.

Step 4: Add Header and Framework search paths.

Tuist offers xcconfig support, enabling us to specify build settings parameters for each environment. We incorporated FRAMEWORK_SEARCH_PATHS, OTHER_LDFLAGS, and HEADER_SEARCH_PATHS in the xcconfig file for this purpose.

You can find these paths in ProjectDir -> Pods -> Target Support Files -> Pods-PROJECT_NAME -> Pods-PROJECT_NAME.debug.xcconfig

Step 5: BUILD AND TEST

Open the workspace, and now we can import the library into our class. Build the project, and it works fine. We’ve successfully set up our project to support both CocoaPods and the Swift Package Manager! 🎉

Conclusion

Even though we aimed to maintain a single dependency manager, there are cases where using CocoaPods is unavoidable. This is because not all iOS libraries support SPM or Carthage. Now that we have enabled CocoaPods, we are pleased with the results, as it provides greater flexibility in managing dependencies. SPM integrates seamlessly with Swift, offering native support and improved performance, whereas CocoaPods boasts a vast library of existing packages and a well-established ecosystem.

References

Dependencies | Tuist
Learn how to declare dependencies in your Tuist project.
How to Successfully Migrate Complex Projects from Cocoapods to SwiftPM
CocoaPods can be slow and can have some problems with compatibility. So we migrated to SwiftPM. This blog details the challenges we faced during the migration from Cocoapods to SwiftPM and how we overcame them.
What is Tuist? | Tuist
Learn about Tuist, a tool that simplifies the complexities of modularization, optimizes workflows, and democratizes the evolution of Xcode projects.

Join us

Scalability, reliability and maintainability are the three pillars that govern what we build at Halodoc Tech. We are actively looking for engineers at all levels and  if solving hard problems with challenging requirements is your forte, please reach out to us with your resumé at careers.india@halodoc.com

About Halodoc

Halodoc is the number 1 all around Healthcare application in Indonesia. Our mission is to simplify and bring quality healthcare across Indonesia, from Sabang to Merauke. We connect 20,000+ doctors with patients in need through our Tele-consultation service. We partner with 3500+ pharmacies in 100+ cities to bring medicine to your doorstep. We've also partnered with Indonesia's largest lab provider to provide lab home services, and to top it off we have recently launched a premium appointment service that partners with 500+ hospitals that allow patients to book a doctor appointment inside our application. We are extremely fortunate to be trusted by our investors, such as the Bill & Melinda Gates Foundation, Singtel, UOB Ventures, Allianz, GoJek, Astra, Temasek, and many more. We recently closed our Series D round and In total have raised around USD$100+ million for our mission. Our team works tirelessly to make sure that we create the best healthcare solution personalised for all of our patient's needs, and are continuously on a path to simplify healthcare for Indonesia.

Download Halodoc app via iOS and Android.

Sakshi Bala

Swift enthusiasts with 7+ years of experience in iOS.