Major 1.0 changes TL:DR
- You now have to define targets. Previously there was an available implicit target.
targethas to represent an Xcode target.
- When you want to represent a collection of pods that go to multiple targets, use an
abstract_targetthen add targets inside that. Pod dependencies are inherited by nested targets.
- Targets that want to know about the pods for a target but don't need linking (for example, Test targets) can define that they inherit pods via their search paths (
:exclusive => trueand
link_withhave been removed in favour of the above.
projectto make the DSL vocabulary consistent.
- We've removed the ability to declare
pod—you can either use the
:podspecoption or point directly to the upstream repo (via
- You can now declare installation options inside the
install! 'cocoapods', :deterministic_uuids => false, :integrate_targets => false).
- We've removed all DSL attributes that were classed as deprecated.
pod trunk deleteand
pod trunk deprecatehave been introduced.
pod searchimprovements (this is great because it searches all your private spec repos too).
pod lib lintand
pod spec lintwill verify that your pod can actually be imported.
A large fraction of the bug reports we receive is due to ambiguity in the
Podfile. It gave a lot of freedom to create all kinds of CocoaPods setups that would work by luck of implementation details, or work but are significantly more complex than they needed to be.
In the 0.x branches the name of a target could be anything. If it was the name of a matching target then it would automatically link to the target, but if not it would create a
Pods-[Name] target and you could use
link_to to connect it to targets.
In 1.0+ a target has to correspond to a real Xcode target. In order to support use cases where Pods can be shared among multiple targets we added
abstract_target. For example:
# Note: There are no targets called "Shows" in any Xcode projects abstract_target 'Shows' do pod 'ShowsKit' pod 'Fabric' # Has its own copy of ShowsKit + ShowWebAuth target 'ShowsiOS' do pod 'ShowWebAuth' end # Has its own copy of ShowsKit + ShowTVAuth target 'ShowsTV' do pod 'ShowTVAuth' end end
Note: In this example, it would be simpler to just not use the
abstract_targetat all, but it's an example, so let me off.
This change enforces a much stronger connection between the CocoaPods target, and makes it impossible to make a
Podfile like this:
due to it having ambiguous behavior. However, the following is possible, as it declares what target to link to:
pod 'ShowsKit' target 'ShowsiOS'
This works because the root level is classed as an unnamed
Let's take a look at a really common example that is shipped as the 0.x
pod lib create.
source 'https://github.com/CocoaPods/Specs.git' use_frameworks! target 'ORStackView_Example', :exclusive => true do pod 'ORStackView', :path => '../' end target 'ORStackView_Tests', :exclusive => true do pod 'ORStackView', :path => '../' pod 'Quick' end
This sets up two completely independent CocoaPods targets that are exclusive to each other. Both have a copy of the library ORStackView. There is a lot going on in this
Podfile; contrast that to the simpler 1.0 version.
source 'https://github.com/CocoaPods/Specs.git' use_frameworks! target 'ORStackView_Example' do pod "ORStackView", :path => "../" target 'ORStackView_Tests' do inherit! :search_paths pod 'Quick' end end
It has an obvious hierarchy, so you can see that Pods included in
ORStackView_Example will be included in the
ORStackView_Tests target. The only new thing is
inherit! :search_paths which means "don't link Pods into here, but let this target know they exist." This
Podfile is easier to read, simpler and has less redundant information.
:head to a
pod nearly always worked, except when it didn't. It is documented as this:
Finally, instead of a version, you can specify the :head flag. This will use the pod’s latest version spec version, but force the download of the ‘bleeding edge’ version. Use this with caution, as the spec might not be compatible with the source material anymore.
It was a tool that was really useful back when CocoaPods was small and it was hard to persuade people it was worth supporting any dependency manager for their projects. That time has long passed and now the flexibility that this attribute originally offered has fallen onto the side of "not worth keeping around." It would introduce extremely hard-to-debug issues for developers expecting it to mean "use the latest version of their code repo." You can either use the
:podspec option or point directly to the upstream repo (via
In the past when we have had to support configuration options for CocoaPods we have used environment variables. These act like NSUserDefaults in that someone who knows the key can make a change, but otherwise they remain quite hidden. Though, sometimes they could be command line APIs too like
--no-integrate. While these were conscious choices they eventually added up to being inconsistent over time, and we've opted to move in favour of centralizing the information in the Podfile. You can see all the available options in the guides.
This means that every developer on your team will have the same output on
pod install regardless of their environment, whether in CocoaPods.app or in the command line. We've left the DSL attribute
install! quite open so that future features can be built with this attribute.
Building for stability
A lot of the work for 1.0 has been around trying to simplify CocoaPods in order to provide long-lasting infrastructure. This is especially important given that the foundations that CocoaPods builds upon often shifts every June and the project is run by a handful of people in their spare time.
We also understand that running CocoaPods is about dealing with humans. With our default CocoaPods Specs repo, for example, we've had a policy of it being read-only since it was introduced CocoaPods Trunk. In reality though we've had to support editing and deleting Pods by hand on a relatively regular basis with the CocoaPods dev team being the ones having to make those decisions. With 1.0.0 we've built the infrastructure to support deleting and deprecating a CocoaPod and a CocoaPod version. We don't recommend it, but it's now there, and it's up to library owners to make the decisions around whether it's fine for their users to remove dependencies.
Finally, and probably the most important point. Once the betas are finished, I can get rid of this FAQ entry:
"CocoaPods is not ready for prime-time yet.”
Correct. Version 1.0.0 will be the milestone where we feel confident that all the basic requirements of a Cocoa dependency manager are fulfilled.
Once we reach the 1.0.0 milestone we will –for the first time ever– contact the community at large through mailing-lists such as cocoa-dev.
Which has been annoying me for as long as I've been working on CocoaPods' infrastructure / design.