Very often we wonder how to manage dependencies on our iOS projects. Historically it was very simple as the options were quite limited. Historically, we used Cocoapods as it was honestly the only meaningful choice, because you don’t want to manage them all by yourself nor by using git submodules.
Dependency management as it used to be
As time went on, we became aware that there are new options for managing our dependencies. When Carthage first appeared, we also gave it a shot, but it was still in its early development phase so it had a lot of drawbacks which were really annoying. It wasn’t possible to build dependencies for only a single platform, updating a single dependency without updating others was impossible, and adding a dependency without compiling others was also impossible. Such things were only slowing us down, so we decided to stick with Cocoapods. We also didn’t like the philosophy of Carthage because we liked the idea of running pod install and not dealing with anything else.
Since we began using Swift as our main programming language, we faced more and more trouble – increased compile time as well as frequent syntax highlight and SourceKit crashes. We began to wonder how to make our developer lives more pleasant. Our first idea was to take a look at our dependencies since they’re codes that don’t change and don’t need to be indexed and compiled by Xcode again and again. This is where Carthage showed its strengths – dependencies were built only once into a framework and that’s it, no more indexing, and no more compiling.
Carthage strikes back
We gave Carthage a try and it looked like all of the early development phase problems were resolved, so we used the platform option to build only for iOS, and the cache-builds option to skip the compilation of frameworks which were already compiled locally. The results were really cool – syntax highlight became much more reliable, and building time decreased by tens of percents.
This means that iOS development is more comfortable even on less powerful devices than a 15-inch Macbook Pro. This also means that we decided to start our new projects with Carthage as the primary dependency manager.
I say primary, though there are still some libraries which do not support it. Those might be older repositories which are no longer maintained or don’t matter to us since we try to use only maintained libraries. Some proprietary software however, uses static libs, which means that it cannot be managed by Carthage. In those cases we still use Cocoapods.
And yet, we still come across some problems. The initial compilation time for dependencies can be enormous, especially when dependencies contain several subspecs (in Cocoapods terminology) because then Carthage compiles them all (and all of their dependencies) even though the project doesn’t need them (for this there is a pull request on Carthage github which would reduce this inconvenience, but right now it is still not merged).
We’d also love some local caching among projects. On our machines we have more projects which use Carthage and very often they use the same versions of their dependencies. If we run carthage bootstrap in every project, its dependencies are built even though they might already have been built by a previous project which could save a lot of building time. Maybe sharing building artifacts with the team remotely would also be nice.
Carthage could also be a bit more space efficient, since a lot of our projects use the Realm database – its artifacts take around 1 GB of disk space. If you have more projects with it you lose a lot of space very quickly.
Still not at its best
Carthage has sped up our development a lot but it still has several problems which would be good to solve. Maybe some of them might be solved now by using the right set of parameters, while others might be solved by using the right tools (like Rome), but those mentioned weaknesses would be nice to solve centrally inside Carthage.