What's your destination?
Few hands on tricks about -destination
option of xcodebuild
.
Destination option (-destination
) was a new addition to Xcode 5 release. It is documented on xcodebuild man page and you get the same by running man xcodebuild
. This option lets you be more verbose with your xcodebuild
commands. For example, if you have a physical device plugged in, running xcodebuild
with no destination specifier will build the project for this physical device. Using destination specifier you can explicitly tell xcodebuild
to build for simulator.
Allow me just to quote the man page here
The -destination option takes as its argument a destination specifier describing the device (or devices) to use as a destination. A destination specifier is a single argument consisting of a set of comma-separated key=value pairs. The -destination option may be specified multiple times to cause xcodebuild to perform the specified action on multiple destinations.
By the way, pay a closer attention to the last sentence. It’s a really nice feature, for example with single command you can run tests on multiple simulators.
One of the keys supported is “platform” and there are 3 options: “OS X”, “iOS” and “iOS Simulator”. Let’s get more details on the last two. iOS and iOS Simulator platforms both require a “name” and “OS” keys to specify device name and iOS version. The question is “How to get list of all names and OS versions?”. There are many ways to do that.
Instruments
The Xcode Instruments command line utility has an undocumented -s
option, which lists all devices and templates. By adding devices
to the invocation only devices are be listed.
instruments -s devices
# Or
xcrun instruments -s devices
Example output, note that it also includes your Mac as a device.
Known Devices:
R5003398 [5C25B8A6-EDF5-5856-B8B9-CB28DFBFADC4]
Maksym's iPhone (8.1.3) [5dc0e5a8a9f7c0af1feea4bfa13860c9e61350d6]
MyIPhone6 (8.1 Simulator) [9151073B-3B7D-441A-8069-E797FA5059CE]
Resizable iPad (8.1 Simulator) [15FC1628-B369-44DE-8CE0-756439D9AEBC]
Resizable iPhone (8.1 Simulator) [5E7A9E8C-D3A8-4E58-935F-8754B100E867]
iPad 2 (7.1 Simulator) [43DD0C31-685F-4FC8-941F-0BB9B305CD2D]
iPad 2 (8.1 Simulator) [8D722A9F-2DA9-45A2-BAFB-44075AA519D6]
iPad Air (7.1 Simulator) [2FB923E2-F0F4-49DE-8FC3-81960386B8CE]
iPad Air (8.1 Simulator) [6032BE94-1A62-4ADB-9013-50FAB2B088F6]
iPad Retina (7.1 Simulator) [F1967F38-BE03-430F-BFB1-AFF4E2E4511C]
iPad Retina (8.1 Simulator) [E8652514-3042-4958-9027-48A9A95392CE]
iPhone 4s (7.1 Simulator) [57DBC56E-1E04-4384-9A07-7B47C119BEAB]
iPhone 4s (8.1 Simulator) [DDF255C3-8BEF-4A97-8B3F-AD651BABF6CB]
iPhone 5 (7.1 Simulator) [BAF484D4-803C-478D-BAC1-916376C22C48]
iPhone 5 (8.1 Simulator) [45E5CE55-093D-48C0-AA26-AA4E5C569FDB]
iPhone 5s (7.1 Simulator) [6856CCCF-842E-48E8-897B-87BB1865CD10]
iPhone 5s (8.1 Simulator) [0AC6BB28-E860-4320-A532-272BE43C067C]
iPhone 6 (8.1 Simulator) [7953EE9F-19E8-4D0C-9219-268FB0BA6626]
iPhone 6 Plus (8.1 Simulator) [E574C367-1BAA-4F9F-BB92-BD5F6BAB1226]
simctl
Another option is to use xcrun simctl
, which is a new addition to Xcode 6. In fact, simctl
looks like a very promising tool that allows you to create, boot, launch and then shutdown and destroy iOS simulators on the fly, and provides commands to install and launch specific apps. If you ever used Genymotion you might have created Android simulators using VirtualBox command line utility, Apple works towards the same flexibility with simctl
.
In context of this article, to see a list of available devices, run this command
xcrun simctl list
You will get the list of device types, runtimes and devices. Device types and runtimes will be handy if you need to create new simulators. You can tell simctl
to filter output, for example, list devices only
xcrun simctl list devices
Sample output
== Devices ==
-- iOS 7.0 --
iPhone 4s (6CF0F409-F4F8-4BCD-AC4E-30E58947A3EB) (Shutdown) (unavailable)
iPhone 5 (1C08AA1B-9C0C-499B-9570-972EF52941D9) (Shutdown) (unavailable)
iPhone 5s (3DD4CAA5-6CD7-4DFB-AF95-6494EAE6E90F) (Shutdown) (unavailable)
iPad 2 (C4E52F2A-C1C0-408F-8177-5AAF7895D3B5) (Shutdown) (unavailable)
iPad Retina (D145A9C9-DFD0-4564-8A45-BF68A80426AC) (Shutdown) (unavailable)
iPad Air (091FC037-5C7F-45FC-9089-E424A9806D60) (Shutdown) (unavailable)
-- iOS 7.1 --
iPhone 4s (57DBC56E-1E04-4384-9A07-7B47C119BEAB) (Shutdown)
iPhone 5 (BAF484D4-803C-478D-BAC1-916376C22C48) (Shutdown)
iPhone 5s (6856CCCF-842E-48E8-897B-87BB1865CD10) (Shutdown)
iPad 2 (43DD0C31-685F-4FC8-941F-0BB9B305CD2D) (Shutdown)
iPad Retina (F1967F38-BE03-430F-BFB1-AFF4E2E4511C) (Shutdown)
iPad Air (2FB923E2-F0F4-49DE-8FC3-81960386B8CE) (Shutdown)
-- iOS 8.1 --
iPhone 4s (DDF255C3-8BEF-4A97-8B3F-AD651BABF6CB) (Shutdown)
iPhone 5 (45E5CE55-093D-48C0-AA26-AA4E5C569FDB) (Shutdown)
iPhone 5s (0AC6BB28-E860-4320-A532-272BE43C067C) (Shutdown)
iPhone 6 Plus (E574C367-1BAA-4F9F-BB92-BD5F6BAB1226) (Shutdown)
iPhone 6 (7953EE9F-19E8-4D0C-9219-268FB0BA6626) (Shutdown)
MyIPhone6 (9151073B-3B7D-441A-8069-E797FA5059CE) (Shutdown)
iPad 2 (8D722A9F-2DA9-45A2-BAFB-44075AA519D6) (Booted)
iPad Retina (E8652514-3042-4958-9027-48A9A95392CE) (Shutdown)
iPad Air (6032BE94-1A62-4ADB-9013-50FAB2B088F6) (Shutdown)
Resizable iPhone (5E7A9E8C-D3A8-4E58-935F-8754B100E867) (Shutdown)
Resizable iPad (15FC1628-B369-44DE-8CE0-756439D9AEBC) (Shutdown)
To get more details just run xcrun simctl list -h
to get help on list
command.
xcodebuild
Finally, to get the most detailed output, ask xcodebuild
itself. It is not really documented and doesn’t look like a proper approach, but it works. The idea is to give xcodebuild
invalid key-value pair in destination specifier and wait until it complains about it offering a list of valid options in return.
xcodebuild test -project MyProject.xcodeproj -scheme MyScheme \
-destination "name=NoSuchName" -destination-timeout 1
The output is
xcodebuild: error: Unable to find a destination matching the provided destination specifier:
{ name:NoSuchName }
Unsupported device specifier option.
The device “My Mac” does not support the following options: name
Please supply only supported device specifier options.
Available destinations for the "MyScheme" scheme:
{ platform:iOS Simulator, id:C4E52F2A-C1C0-408F-8177-5AAF7895D3B5, OS:7.0, name:iPad 2 }
{ platform:iOS Simulator, id:43DD0C31-685F-4FC8-941F-0BB9B305CD2D, OS:7.1, name:iPad 2 }
{ platform:iOS Simulator, id:8D722A9F-2DA9-45A2-BAFB-44075AA519D6, OS:8.1, name:iPad 2 }
{ platform:iOS Simulator, id:091FC037-5C7F-45FC-9089-E424A9806D60, OS:7.0, name:iPad Air }
{ platform:iOS Simulator, id:2FB923E2-F0F4-49DE-8FC3-81960386B8CE, OS:7.1, name:iPad Air }
{ platform:iOS Simulator, id:6032BE94-1A62-4ADB-9013-50FAB2B088F6, OS:8.1, name:iPad Air }
{ platform:iOS Simulator, id:D145A9C9-DFD0-4564-8A45-BF68A80426AC, OS:7.0, name:iPad Retina }
{ platform:iOS Simulator, id:F1967F38-BE03-430F-BFB1-AFF4E2E4511C, OS:7.1, name:iPad Retina }
{ platform:iOS Simulator, id:E8652514-3042-4958-9027-48A9A95392CE, OS:8.1, name:iPad Retina }
{ platform:iOS Simulator, id:6CF0F409-F4F8-4BCD-AC4E-30E58947A3EB, OS:7.0, name:iPhone 4s }
{ platform:iOS Simulator, id:57DBC56E-1E04-4384-9A07-7B47C119BEAB, OS:7.1, name:iPhone 4s }
{ platform:iOS Simulator, id:DDF255C3-8BEF-4A97-8B3F-AD651BABF6CB, OS:8.1, name:iPhone 4s }
{ platform:iOS Simulator, id:1C08AA1B-9C0C-499B-9570-972EF52941D9, OS:7.0, name:iPhone 5 }
{ platform:iOS Simulator, id:BAF484D4-803C-478D-BAC1-916376C22C48, OS:7.1, name:iPhone 5 }
{ platform:iOS Simulator, id:45E5CE55-093D-48C0-AA26-AA4E5C569FDB, OS:8.1, name:iPhone 5 }
{ platform:iOS Simulator, id:3DD4CAA5-6CD7-4DFB-AF95-6494EAE6E90F, OS:7.0, name:iPhone 5s }
{ platform:iOS Simulator, id:6856CCCF-842E-48E8-897B-87BB1865CD10, OS:7.1, name:iPhone 5s }
{ platform:iOS Simulator, id:0AC6BB28-E860-4320-A532-272BE43C067C, OS:8.1, name:iPhone 5s }
{ platform:iOS Simulator, id:E574C367-1BAA-4F9F-BB92-BD5F6BAB1226, OS:8.1, name:iPhone 6 Plus }
{ platform:iOS Simulator, id:7953EE9F-19E8-4D0C-9219-268FB0BA6626, OS:8.1, name:iPhone 6 }
{ platform:iOS Simulator, id:15FC1628-B369-44DE-8CE0-756439D9AEBC, OS:8.1, name:Resizable iPad }
{ platform:iOS Simulator, id:5E7A9E8C-D3A8-4E58-935F-8754B100E867, OS:8.1, name:Resizable iPhone }
{ platform:iOS Simulator, id:9151073B-3B7D-441A-8069-E797FA5059CE, OS:8.1, name:MyIPhone6 }
{ platform:iOS, id:5dc0e5a8a9f7c0af1feea4bfa13860c9e61350d6, name:Maksym's iPhone }
Thanks Tor Arne for pointing out -destination-timeout
option in the comments. Without this option xcodebuild
will take way too long to figure out that destination doesn’t exist.
Back to Destination
Now that last output from xcodebuild
is much better than anything else. It gives you all the key-value pairs as is, no additional guesswork involved. You get the “platform”, “OS” and “name” keys, and as a bonus you get an undocumented “id” key. Give it a try and see that it actually works.
xcodebuild test -project MyProject.xcodeproj -scheme MyScheme -destination "id=E574C367-1BAA-4F9F-BB92-BD5F6BAB1226"
You can adopt this approach as part of CI workflow automation and grep all key-value pairs from xcodebuild
output.