Shout out to Carthage and Bitrise
or how to reduce iOS build time twice

Aleksandr Pavliuk
3 min readMar 3, 2019

--

The problem

Me and my current team are working on one iOS project that use Swift 4.2 as main development language. For CI/CD we use Bitrise.io, it’s a great tool that makes mobile developers’ life a lot easier. CocoaPods has been the only dependency management tool so far. Project is quite large and it took about 2 minutes to build an app and 4 minutes to make build for unit tests after build folder cleanup.

We all know what CocoaPods becomes a bummer when your project has a list of massive 3rd-party libraries as it significantly increases time for compilation (and in most cases libraries are being compiled every single time the build folder gets all cleaned up). In real life devs usually do stuff like working on a few features at the same time, switching between the branches, trying to avoid XCode imperfections — all of it can be a valid reason to clean up build folder. In addition — just like devs our build machines also start with clean build folder at every pull request creation. And numbers there are much higher. It took like 30 minutes for build machine to run our unit tests and it was like that up until the moment builds started to fail because of the time out. Builds couldn’t fit in 45 minutes! Turned out that there was an issue with CPU allocation, but we decided to make an effort to reduce the build time.

Carthage

We’ve never tried Carthage before but it was pretty obvious that it may help us to reduce time costs quite effectively. Just moving Realm from CocoaPods to Carthage already gave a huge positive change in terms of speed.

Build test on local machine after cleanup (MacBook Pro 15-inch, 2018)

+----------------------+----------+
| Type | Time |
+----------------------+----------+
| CocoaPods | 4m 18.4s |
| CocoaPods & Carthage | 1m 54.8s |
+----------------------+----------+

Build machine

+-------------------------------------+---------+
| Type | Time |
+-------------------------------------+---------+
| CocoaPods | 32m |
| CocoaPods & Carthage(after caching) | 19m 23s |
+-------------------------------------+---------+

From development standpoint the effort itself is pretty easy: developer just needs to run `carthage bootstrap` once and then simply forget about it until `Cartfile` or `Cartfile.resolved` changes.
You can dig for more info on GitHub page.

Bitrise

Once Carthage has been introduced as a step to build routine — building machine itself started to download and build libs on every build and it wasn’t something we were happy about since build time stayed pretty much the same. Luckily Bitraise provides great opportunity to create cache. We added cache pull and push to take place before and after Carthage step. However turned out that Bitrise cache is not supposed to be shared between branches so the problem still remained with every new pull request. In order to avoid it we decided to go for little trick mentioned in Bitrise docs, namely:

If a build runs on a branch which doesn’t have a cache yet, it’ll get the cache of the main/default branch

We just ran our build on a default brunch once to create cache so that every new build would take default cache instead of generating its own.
One more “nice to know” kinda thing is a GitHub token that is better to be added to Carthage step as it speeds up downloading sources from GitHub. Carthage doesn’t have access to GitHub by SSH however Bitrise can store token and use it for you.

Conclusion

Once all the Carthage-related arrangements were done approximate tests build time become 15 minutes. It wasn’t that hard to both implement and maintain. No special scripts in CI workflow were added so it didn’t make our life more complicated. We are keen on going further with Carthage and Bitrise in a bundle and consider it to be a good practice.

--

--