Streamlining Dependencies: How to support both CocoaPods and Swift Package Manager with iOS Tuist
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.
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
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.