Carthage: Dependency management made git-like

Nicholas Maccharoli

April 01st, 2016

Why do I need another dependency manager?

Carthage is a decentralized dependency manager for the iOS and OS X frameworks. Unlike CocoaPods, Carthage has no central location for hosting repository information (like pod specs). It dictates nothing as to what kind of project structure you should have, aside from optionally having a Carthage/ folder in your project's root folder, and housing built frameworks in Build/ and optionally source files in Checkouts/ if you are building directly from source.This folder hierarchy is automatically generated after running the command, bash carthage bootstrap. Carthage leaves it open to the end user to decide how they want to manage third-party libraries, either by having both the Cartfile and Carthage/* folders checked in under source control or just the Cartfile that lists the frameworks that you wish to use in your project under source control. Since there is no centralized source of information, project discovery is more difficult with carthage, but other than that, normal operation is simpler and less error prone when compared to other package managers.

The Setup of Champions

The best way to install and manage carthage, in my opinion, is through HomeBrew. Just run the following command and you should be in business in no time:

brew install carthage

If for some reason you don't want to go the homebrew route, you are still in luck! Just download the latest and greatest carthage.pkg from the Releases Page.

Common Carthage Work-flow

Create a cart file with dependencies listed, and optionally, branch or version info.

Cartfile grammar notes:

  • The first keyword is either 'git' for a repository not hosted on github, or 'github' for a repository hosted on github.
  • Next is the location of the repository. If the prefix is 'git', then this will be the same as the address you type when running git clone.
  • The third piece is either the branch you wish to pull the latest from, or the version number of a release with one of the following operators: ==, >= or ~>.
github "ReactiveCocoa/ReactiveCocoa" "master" #Latest version of the master branch of reactive cocoa
github "rs/SDWebImage" ~> 3.7 # Version 3.7 and versions compatible with 3.7
github "realm/realm-cocoa" == 0.96.2 #Only use version 0.96.2

Basic Commands

Assuming that all went well with the installation step, you should now be able to run carthage bootstrap and watch carthage go through the Cartfile one by one and fetch the frameworks (or build them after fetching from source, if using --no-use-binaries) Given that this goes without a hitch, all that is left to do is add a new run script phase to your target. To do this, simply click on your target in XCode, and under the 'Build Phases' tab, click the '+' button and select "New Run Script Phase"

Type this in the script section:

/usr/local/bin/carthage copy-frameworks

And then, below the box where you just typed the last line, add the input files of all the frameworks you wish to include and their dependencies.

Last but not least

Once again, click on your target and navigate to the General tab, and then go to the section Linked Frameworks and Libraries and add the frameworks from [Project Root]/Carthage/Build/[iOS or Mac ]/* to your project.

At this point, everything should build and run just fine. As the project requirements change and you wish to add, remove, or upgrade framework versions, just edit the Cartfile, run the command carthage update, and if needed add new or remove unused frameworks from your project settings.

It's that simple!

A Note Source Control with Carthage

Given that all of your project's third party source and frameworks are located under the Carthage/ folder, in my experience, it is much easier to just simply place this entire folder under source control. The merits of doing so are simple: when cloning the project or switching branches, there is no need to run carthage bootstrap or carthage update. This saves a considerable amount of time, and the only expense for doing so is an increase in the size of the repository.

About the author

Nick Maccharoli is an iOS / Backend developer and Open Source enthusiast working with a startup in Tokyo, enjoying the current development scene. You can see what he is up to at @din0sr or github.com/nirma.