Carthage is a great dependency management tool for both Swift and Objective-C. However, finding the right workflow adopt when developing with carthage can be a bit tricky.
This is especially true if you are building your own frameworks and would like to use carthage to manage them in your application project.
Overview
The scenario
Suppose the following scenario.
You have a cat-names
framework and a dog-names
that you wrote yourself and
are building a iPuppyApp
application.
After hard days of work you have now reached version v0.1.0
of both Cat-names.framework
and
Dog-names.framework
. It’s now time to build you app, so in the app’s Cartfile
you specify
git "file:///Users/blender/Code/cat-names" ~> 0.1.0
git "file:///Users/blender/Code/dog-names" ~> 0.1.0
Nice! Now you carthage bootstrap
, link the framework, add the carthage copy-frameworks
(from now on referred as Carthage Copy Framework) phase and develop you app.
As you develop the iPuppyApp
application you find a bug in CatNames.framework
.
Unfortunately even if the sources are in Carthage/Checkouts
Xcode won’t Open Quickly
nor Jump to definition. No break points for you.
The Carthage/Checkouts way
You decide to add to your project the CatNames.xcodeproj
found in Carthage/Checkouts/cat-names
.
This involves:
- removing the old library from “Linked Libraries and Frameworks” (because that’s the one in
Carthage/Build/iOS
) - adding the new library auto-discovered from the products by Xcode after you dragged in
CatNames.xcodeproj
- changing the Carthage Copy Framework to copy
$(BUILT_PRODUCTS_DIR)/CatNames.framework
- adding
CatNames.framework
as a target dependency
I will call this the Linking Dance.
Great! You build, debug, find the bug and make the change to the library and surprise surprise… the
change you just made to the library is not under version control. You can’t even git diff
.
Depending on how used you are to this dance, you have now just wasted 3 to 5 minutes, and don’t even have your changes under version control. Imagine if you project had a longer list of in house dependencies. This can easily take half an hour so to set up and tear down afterwards.
The symbolic link way
The right thing do to here is actually to:
- turn the
Carthage/Checkouts/cat-names
directory in your app’s project directory into a symbolics link to where your sources under version control are. This will ensure that any change that you make is under version control. - turn the
Carthage/Build
directory in your framework into a symbolic link to your app’s projectCarthage/Build
director. This will ensure that both your framework and your app can access all other frameworks build with carthage.
then do the the Linking Dance.
At this point your productivity is below zero and you’re wondering what got you into software development in the first place.
But don’t despair, I’m here to help.
develop.rb
I have put together develop.rb a ruby script that will do and undo all of this for you without touching your project.
It will create another copy of you project called $YOUR_PROJECT Dev.xcodeproj
.
Assumptions
The script assumes that both the source of our frameworks and your app are in the same parent directory like the following:
.
..
|- cat-names
|- dog-names
|- iPuppyApp
The script uses a Romefile to read the names of the repos of your frameworks.
If you are no using Rome and don’t have a Romefile
just create one as follows:
[RepositoryMap]
cat-names = CatNames
dog-names = DogNames
Note that for the purpose of Rome this is not a valid Romefile, but it will do for the script
Usage
Run the script from the same directory where your Cartfile
is.
TARGET_NAME="iPuppyApp" ./develop.rb start cat-names dog-names
Get help by running
./develop.rb --help
The script
Final notes
I am not a ruby developer and this is the first time I use ruby so feel free to suggest improvements.
Thanks to @netbeatwork who inspired much of the Symbolic Link method