How does JetBrains AppCode launch the iOS Simulator?
Asked Answered
M

6

18

I just looked at JetBrains's App Code IDE and it seems to be able to launch the iOS Simulator and run applications in it.

When I had to automate the deployment of my projects I had to resort to Applescript and GUI automation.

They seem to be using a closed tool called 'simlauncher'. I wonder what the magic behind it could be.

Update:

  1. On looking at Activity Monitor, I see that osascript gets launched from simlauncher before the simulator is launched. Could it be Applescript again? I thought iOS Simulator.app was not scriptable.
  2. iOS Simulator seems to be launched by launchd, so simlauncher is definitely not launching it by itself. Also, simlauncher stays only until the actual application is running in the simulator. They're polling for it perhaps?
  3. For device builds, they're using AMDeviceService, which is probably a version of Apple Mobile Device Service. Is this a technique from the jail broken SDK?

A little more info on the simulator from the output of 'ps':

plumenator 26404  12.9  1.3   290172  52772   ??  SX    8:56PM   0:03.62 /Users/plumenator/Library/Application Support/iPhone Simulator/4.3.2/Applications/817A280D-1F74-4755-B848-B04EC8A24ADA/xxx.app/xxx
plumenator 26395   2.3  0.3   444208  13560   ??  S     8:56PM   0:00.72 /Developer/Platforms/iPhoneSimulator.platform/Developer/Applications/iPhone Simulator.app/Contents/MacOS/iPhone Simulator -SessionOnLaunch NO
plumenator 26402   1.4  0.8   318320  33052   ??  Us    8:56PM   0:00.86 /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/System/Library/CoreServices/SpringBoard.app/SpringBoard -SBDisableAutoDim YES -SBAutoLockTime -1 -SBAutoDimTime -1 -SBDontLockAfterCrash YES -SBDidShowReorderText YES -SBFakeBars YES -SBDontAnimateAppleDown YES -SBEnableDoubleHeightToggling YES
plumenator 26406   0.0  0.4  2466496  15792   ??  Ss    8:56PM   0:00.16 /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/libexec/gdb/gdb-i386-apple-darwin --arch i386 --interp=mi1 -q
plumenator 26401   0.0  0.1   106584   5688   ??  S     8:56PM   0:00.30 /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/usr/libexec/lsd
plumenator 26400   0.0  0.1   105228   4204   ??  S     8:56PM   0:00.13 /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/usr/libexec/installd -t 30
plumenator 26399   0.0  0.3   223488  11464   ??  Ss    8:56PM   0:00.15 /Developer/Platforms/iPhoneSimulator.platform/Developer/Applications/iPhone Simulator.app/Contents/MacOS/SimulatorBridge 26395

Now I suppose it's just a matter of sorting the commands according to the pid and executing them. :-)

There's a problem, though. All these binaries refer to dylibs present in the simulator platform's root. When I run them directly, they look for those in '/'.

Is there a way to set the path for dylibs before running a command? This looks promising: http://sacredsoftware.net/svn/misc/StemLibProjects/eaglshell/tags/2.1.0/Makefile

https://github.com/BlueFrogGaming/icuke has good info too.

Muth answered 30/5, 2011 at 5:47 Comment(2)
Thanks CrazyCoder, I didn't have enough rep to add a new tag.Muth
Guys, I'll keep the bounty open until I get more info on the device side of the question.Muth
P
26

AppCode use a special wrapper to do this, that you noticed in its console :

/Applications/AppCode-108.379.app/bin/simlauncher 4.3 debug iphone <PATH_TO_APP> <STDOUT> <STDERR>

simlauncher is a non documented / not friendly mach-o binary... But here is a quick analysis of it:

  • To launch simulator it uses a private Apple framework (otool -L simlauncher) :

    /Applications/AppCode-108.379.app/bin/simlauncher:
    @rpath/iPhoneSimulatorRemoteClient.framework/Versions/A/iPhoneSimulatorRemoteClient (compatibility version 1.0.0, current version 12.0.0)
    
  • This framework is bundled with Xcode:

    <XCODE_PATH>/Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/iPhoneSimulatorRemoteClient.framework
    
  • And is used like that (class-dump simlauncher) (DTiPhoneSimulator* are from Apple Framework):

    @protocol DTiPhoneSimulatorSessionDelegate
    - (void)session:(id)arg1 didEndWithError:(id)arg2;
    - (void)session:(id)arg1 didStart:(BOOL)arg2 withError:(id)arg3;
    @end
    
    @interface Launcher : NSObject <DTiPhoneSimulatorSessionDelegate> {
        DTiPhoneSimulatorSession *mySession;
    }
    
    - (int)launch:(id)arg1 sdkVersion:(id)arg2 wait:(BOOL)arg3 device:(int)arg4 sout:(id)arg5 eout:(id)arg6 argument:(id)arg7 env:(id)arg8;
    - (void)session:(id)arg1 didEndWithError:(id)arg2;
    - (void)session:(id)arg1 didStart:(BOOL)arg2 withError:(id)arg3;
    
    @end
    

About the other binary AMDeviceService I just can say it uses ProtocolBuffers in order I guess to communicate with MobileDevice service... Once again, undocumented stuff...

Quick conclusion, sorry, there is no easy way to launch iPhoneSimulator using the JetBrains way, unless reversing Apple privates/not documented APIs... like Jetbrains folks did, I love their tools, they are top guns, can't wait appcode to be gold, already working on it everyday :)

EDIT: See answer below from a JetBrains employee... @JetBrains, would be great to have some sort of AMDeviceService documented to automate some stuff... ;)

Prearrange answered 10/6, 2011 at 12:23 Comment(2)
+1 Great analysis! Where can I learn to reverse engineer like this? Also, is it good idea for AppCode to rely on this in the long term? Apple can change it anytime.Muth
Thanks :) just search Google for otool and classdump you will find tons of useful resources. About your second point, maybe jetbrains works with apple, like they do with Microsoft. But that would be surprising. In any case be sure there is at least one person working full-time on this to ensure Xcode versions compatibilities. I have been working with jetbrains tools for something like 8 years now, on java, dotnet, now obj-c and others. Always great quality and great support :)Prearrange
O
11

What exactly do you want to automate? Installing app and launching it in simulator or device?

About "3":

AMDeviceService is just some daemon which is responsible for any interaction with device. It uses only /System/Library/PrivateFrameworks/MobileDevice.framework library(it's private). It doesn't know about any /Developer stuff (of course if you are not going to debug on device).

This service deploys app on device, mounts developer image, browses apps on device and starts debugserver.

It uses Google Protocol Buffers based protocol to communicate with AppCode. Not Apple-stuff.

Osmosis answered 10/6, 2011 at 16:21 Comment(1)
It really would be great if some of this was documented to help those of us wanting to automate testing on actual devices.Jaco
F
4

Not 100% sure this is what your question is about, but I'm able to run an arbitrary Simulator-compiled app whose folder I have on the Desktop (for instance) in the Simulator with the following line in the terminal (all one line, substituting appropriate values for your system):

/Developer/Platforms/iPhoneSimulator.platform/Developer/Applications/iPhone\ Simulator.app/Contents/MacOS/iPhone\ Simulator -SimulateApplication 
/Users/myusername/Desktop/[the alphanumeric app directory name]/MyCompiledAppProject.app/MyCompiledAppProject

Where that last "MyCompiledAppProject" file is the actual binary that is inside of the package which ends with .app (you'll have to control-click on the .app file and select "Show Package Contents" to see it). This will launch the Simulator if it isn't already open. It could easily be packaged in an AppleScript that takes the newly-compiled app location as a file argument and doesn't require Xcode to be open or xcodebuild to be used.

Furan answered 10/6, 2011 at 12:16 Comment(9)
+1 This is SO awesome. How did you find this out? From 'ps'? There's one problem, though. I can't select the version, hardware, etc.Muth
Looking back through my history, I think I saw this gist while searching for something similar: gist.github.com/999779. It actually starts with an xcodebuild call that sets the target, wonder if that would help you target the preferred simulator version. I'm guessing probably not though, since it's unlikely they are aware of each other.Furan
OK, I just tried a couple arguments out and discovered that you can add -SimulateDevice iPad to the end of the line and it will launch it in the iPad simulator instead of the iPhone simulator. I'll see if there is anything similar for the SDK version. Oh, just checked your link and they have also already found several of them. Can you use currentSDKRoot to target the version?Furan
Yes! you have to point to /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.2.sdk for 3.2 for example. How did you find the command SimulateDevice btw?Muth
Another limitation with this is that it doesn't launch SpringBoard.Muth
I first tried "TargetDevice" but when it didn't work I figured it was worth trying an argument with the same basic nomenclature as the argument that was working. Looking at the other SO link, they've found a bunch more -- it's hard to imagine that there is that much precise control over how to run an app in the Simulator from the command line without there also being an argument for installing it and running Springboard...Furan
SimulateDevice understands "iPhone (Retina)"!Muth
I don't know if this is going to get us any closer to launching in SpringBoard, but you can of course use the same technique to launch SpringBoard: /Developer/Platforms/iPhoneSimulator.platform/Developer/Applications/iPhone\ Simulator.app/Contents/MacOS/iPhone\ Simulator -SimulateApplication /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/System/Library/CoreServices/SpringBoard.app/SpringBoardFuran
Regarding your question "is there a way to set the path for dylibs before running a command?", I was just looking at this run script from GHUnit: github.com/gabriel/gh-unit/blob/master/Scripts/RunTests.sh which shows setting and later unsetting DYLD_ROOT_PATH, DYLD_FRAMEWORK_PATH, and IPHONE_SIMULATOR_ROOT explicitly before and after directly running a simulator build product.Furan
P
4

The iphonesim project gives you a command-line launcher for iOS apps. I believe it packages up what you want.

Pilaf answered 7/2, 2012 at 0:59 Comment(0)
U
0

I think I read somewhere that they rely on Xcode to do this sort of thing for them. But it wasn't very specific, and I don't know where I read it. Maybe they're scripting Xcode to launch and deploy, instead of the simulator directly?

Untie answered 30/5, 2011 at 7:10 Comment(1)
They only rely on the Xcode/Developer tools platform (for xcodebuild), and of course the simulator itself. They don't launch Xcode, so they're not scripting it.Muth
U
0

Similar project by phone gap is at https://github.com/phonegap/ios-sim.

Uprear answered 12/6, 2013 at 19:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.