Vendor – Bringing Bundler to iOS

Using and sharing iOS libraries is tragically difficult given the maturity of the framework, the number of active developers, and the size of the open source community.  Compare with Rails which has RubyGems and Bundler, it’s no surprise that Rails/Ruby has a resource like The Ruby Toolbox, while iOS development has…nothing?

Are iOS developers fundamentally less collaborative than Rails developers?  When developing on Rails, if I ever find myself developing anything remotely reusable, I can almost always be certain that there is a gem for it (probably with an obnoxiously clever name).

I don’t think the spirit of collaboration is lacking in the iOS developer community; rather, there are a few fundamental challenges with iOS library development:

  • Libraries are hard to integrate into a project.  Granted, it’s not *that* hard to follow a brief set of instructions, but why can’t this process be more streamlined?
  • No standardized versioning standard.  Once a library is integrated into a project, there is no standard way of capturing which version of the library was used.
  • No dependency specification standard (this is a big problem).  Why does facebook-ios-sdk embed it’s own JSON library when there are better ones available?  So many libraries come embedded with common libraries that we all use – and worse than that, who knows what version they’re using!  Not only can this lead to duplicate symbols, but library developers essentially have to start from scratch instead of leveraging other existing libraries.

Of course, coming up with a naming, versioning, and dependency standard for iOS libraries and convincing everyone to adopt it is a daunting task.  One possible approach is follow the example of Homebrew, a popular package manager for OS X.  Homebrew turned installing and updating packages on OS X into a simple process.  Instead of convincing everyone to comply to some standard, Homebrew maintains a set of formulas that helps describe commonly used packages.  These formulas allow Homebrew to automate the installation process as well as enforce dependencies.  This works well for Homebrew, although it puts the burden of maintaining package specifications in one place, rather then distributed as it is with Ruby gems.

There seems to be a need for some type of solution here.  When we write Rails libraries, we write the readme first to help us understand what problem we’re trying to solve (Readme Driven Development).  Below is the readme for an iOS packaging system called Vendor.

Vendor – an iOS library management system

Vendor makes the process of using and managing libraries in iOS easy.  Vendor leverages the XCode Workspaces feature introduced with XCode 4 and is modeled after Bundler. Vendor streamlines the installation and update process for dependent libraries.  It also tracks versions and manages dependencies between libraries.

Step 1) Specify dependencies

Specify your dependencies in a Vendors file in your project’s root.

source ""
lib "facebook-ios-sdk"  # Formula specified at source above
lib "three20"
lib "asi-http-request", :git => ""
lib "JSONKit", :git => ""

Step 2) Install dependencies

vendor install
git add Vendors.lock

Installing a vendor library gets the latest version of the code, and adds the XCode project to the workspace.  As part of the installation process, the library is set up as a dependency of the main project, header search paths are modified, and required frameworks are added.  The installed version of the library is captured in the Vendors.lock file.

After a fresh check out of a project from source control, the XCode workspace may contain links to projects that don’t exist in the file system because vendor projects are not checked into source control. Run `vendor install` to restore the vendor projects.

Other commands

# Updating all dependencies will update all libraries to their latest versions.
vendor update
# Specifying the dependency will cause only the single library to be updated.
vendor update facebook-ios-sdk

Adding a library formula

If a library has no framework dependencies, has no required additional compiler/linker flags, and has an XCode project, it doesn’t require a Vendor formula. An example is JSONKit, which may be specified as below. However, if another Vendor library requires JSONKit, JSONKit must have a Vendor formula.

lib "JSONKit", :git => ""

However, if the library requires frameworks or has dependencies on other Vendor libraries, it must have a Vendor formula.  As with Brew, a Vendor formula is some declarative Ruby code that is open source and centrally managed.

An example Vendor formula might look like:

require 'formula'

class Three20 < Formula
  url ""
  libraries libThree20.a
  frameworks "CoreAnimation"
  header_path "three20/Build/Products/three20"
  linker_flags "ObjC", "all_load"
  vendors "JSONKit"


Using iOS libraries is way harder than it should be, which has negatively impacted the growth of the open source community for iOS.  Even if I was only developing libraries for myself, I would still want some kind of packaging system to help me manage the code.  Vendor essentially streamlines the flow described by Jonas Williams here.  Unfortunately, programmatically managing XCode projects isn’t supported natively, but people have implemented various solutions, such as Three20Victor Costan, and XCS.

Open Questions

  • Is there an existing solution for this?
  • Would this be a useful gem for your iOS development?
  • Why hasn’t anyone built something like this already? Impossible to build?

17 thoughts on “Vendor – Bringing Bundler to iOS

  1. Sounds like a good challenge.

    >Is there an existing solution for this?

    >Would this be a useful gem for your iOS development?
    of course

    >Why hasn’t anyone built something like this already? Impossible to build?
    I think that the main reasons are:
    1. everyone waiting solution from Apple that will become standard
    2. there is no specification for *.xcodeproject file format

    • Cool, thanks for the feedback. Yes, manipulation of the xcodeproject does seem to be at least one of the major pain points, although people have hacked ways around it. Three20 has reverse engineered the file format, while others have used Applescript to manipulate the project file. Personally, I’m leaning towards the Applescript approach.

  2. This would be brilliant. We’ve struggled with this exact problem for months now and have resorted to rake tasks for building up dependencies. A formal approach is something that is sorely lacking in the iOS world.

  3. I thought again and I think that the best way is:

    1. create analog of Ruby Gems and
    2. each vendor packackage will contain a static library compiled for ARM and iOS Simulator (x86) with all it header files
    3. format of vendor package will be similar to ruby gem with ability to specify version, author, dependencies, etc.
    4. in root of Xcode project will be located Vendor file with list of all frameworks and static libraries used in project
    5. `vendor install` will download all needed vendor packages and modify Xcode project to link with all frameworks, static libraries, add header search path for each vendor package

    What do You think about this? I’m very interested in development of this kind of system, would You participate?

  4. Hey Tim,
    I’ve almost finished an alpha of this project. I’ll drop you a line when I’ve got something working. I’ve actively developing this at the moment. Send me an email and I’ll show you what I’ve done so far.

    • @Tim if we include a .gemspec in each library’s root, bundler and rubygems should be able to build the library.

      We would create a Gemfile with the libraries we want to include and then just run bundle install. We can have a separate source and index for objective-c projects so we do not need to submit the libraries to

      There might be some hangups with doing it this way, but theoretically it should work.

Comments are closed.