Share Xcode Schemes
So you are facing one of these Xcode errors where it tells you that there’s no such scheme? This post could help to explain why Xcode does it and how to solve this problem.
Shared vs User Schemes
While setting up build server for iOS app I have faced this issue multitude of times. Xcode schemes can be either shared or not. By default schemes are not shared and are owned by a user that creates them.
Here’s how it looks in Xcode, note the last column with checkboxes.
If you look inside
kartoteka-reloaded.xcodeproj folder you will see how Xcode stores the schemes.
Here’s how it looks when
kartoteka-reloaded.xcscheme is not shared
Now let’s tick the “Shared” checkbox then list directory contents again
Notice how the
kartoteka-reloaded.xcscheme moved from user data folder to shared data folder. This is basically what makes scheme a shared one.
The general practice for Xcode projects
.gitignore file is to ignore user data
So when you check out source code on a build box, there won’t be any user schemes inside
.xcodeproj folder and
xcodebuild won’t be able to see the schemes and will fail to build them.
You can solve this problem either manually or automatically.
Of course you can just talk to devs and ask them to share the scheme. Done! You can even do this change yourself and create pull request with changes.
But this approach will not work in some cases. For example, if you want to run UI automation tests with Calabash, the steps are
- Duplicate existing Xcode target and name new test target with
- Add Calabash framework to test target
-caltest target and run tests
The first step is done with
calabash-ios setup command. When new target is created a scheme is created for it as well. This is the default setting for all Xcode projects and in this post we’ll assume that’s the way you have it configured as well.
Now the tricky part, it doesn’t matter if original scheme was shared, the new
-cal scheme will not be shared. That means you won’t be able to build it from command line.
Since it all happens on a build box as part of a build plan, you can’t push anything back to the repository, you have to find a way to make this new scheme shared right now.
The answer to your problems comes from Ruby world. In particular the xcodeproj Ruby gem. This is an incredibly handy library to work with Xcode projects and workspaces. You can do pretty much anything you need, create and modify targets and schemes, add new files to targets, modify build settings and other properties, and, of course, share schemes. By the way,
xcodeproj is used by CocoaPods and that says a lot.
Go ahead and install the gem
Now create a simple Ruby file, name it whatever you want
This is it! Put your Xcode project name in there, then run and the scheme will be shared.
It sounds to good to be true, right? There’s a number of situations where shaing a scheme via Ruby script will not work as expected.
If your Xcode project already has a shared scheme, then you will end up having one scheme from user’s data directory and another one form
xcshareddata. Xcode IDE will pick up both and that’s the reason why you see same scheme twice with project name in parentheses.
That’s not very bad and doesn’t normally cause any problems. Until that moment of time when you modify one scheme and forget about another. The best way to avoid this problem is to share schemes from day 1, Xcode will not create user schemes then.
The real trouble begins if you didn’t have any shared schemes and the scheme that you want to recreate and share is linked to a test target. That’s the default configuration for unit tests. So the problem is that
xcodeproj doesn’t recreate dependencies to test target. If you run a
xcodebuild test action you’ll be surprised to see it failing. Unfortunately there isn’t an easy workaround for this problem, so you’d better share those schemes manually and commit changes to source control system.
Surely the Ruby script can be improved, you’d want to pass Xcode project name as an argument or even look it up automatically.
As usual, in Summary I just provide file listing with a solution ready to copy-paste. Here’s more advanced Ruby script for your use. You can just get the file directly if you’d like, share-schemes.rb
Right, this is one of those cases where actual meaningful code is very small (just 4 lines), the rest is options parsing and error checking, but then it’s worth it in the end.
Finally run it
Related thread on StackOverflow.
blog comments powered by Disqus