For the entirety of this guide we'll assume your project's name is libfoo
.
To follow this tutorial exactly, you will need:
- Xcode 11.4 beta (
sudo xcode-select -s /Applications/Xcode-beta.app
); - Simject installed according to its readme; and
- an example AutoHook project set up and ready to go in Xcode.
-
Set your project's scheme to libfoo and target an iPhone simulator.
-
Build once with
cmd+B
. -
Open Terminal and enter
cd ~/Library/Developer/Xcode/DerivedData
. Depending on your shell and its configuration you can either press the TAB key or enter the commandls -la
to get a list of directories. Find a directory named something likelibfoo-qwertyuiopasdfghjkl
andcd
into it. -
Continue down the directory tree by
cd
ing intoBuild/Products/Debug-iphonesimulator
. If you don't seeDebug-iphonesimulator
then you did not complete step 2. If you only seeDebug-iphoneos
then your scheme was targeted to an actual iOS device or the generic iOS device. Either way, go back to step 2. -
Run
ls
to list the directory's files and ensure there is a file namedlibfoo.a
. -
Run clang:
xcrun --sdk iphonesimulator13.4 clang -arch x86_64 -shared -all_load libfoo.a -o libfoo.dylib
-
Run
ls
again and verify that a new file namedlibfoo.dylib
has appeared. -
Copy the dylib to simject with
cp libfoo.dylib /opt/simject
. -
Sign the library with
codesign -f -s - /opt/simject/libfoo.dylib
-
Next we have to create a bundle plist. Run
/usr/libexec/plistbuddy libfoo.plist
. The output should look something like this (where the_
indicates your cursor):❯ /usr/libexec/plistbuddy libtestobjagain.plist File Doesn't Exist, Will Create: libtestobjagain.plist Command: _
-
Type
add :Filter dict
and hit enter. Check to see if the dictionary was added correctly by typingprint
and hitting enter. The output should look like:Command: print Dict { Filter = Dict { } }
-
Run
add :Filter:Bundles array
, followed byadd :Filter:Bundles: string com.apple.springboard
. Finally, runprint
again to check your work:Command: print Dict { Filter = Dict { Bundles = Array { com.apple.springboard } } }
-
If you're satisfied, run
save
and thenctrl+c
to exit. DON'T FORGET TO SAVE! -
Copy your plist to simject by running
cp libfoo.plist /opt/simject
. You should also take this opportunity to copy it to your project directory. -
Run resim! For me, that's
~/git/simject/bin/resim
. The exact path depends on where you cloned the simject repository.
Phew, that was a lot, right? Thankfully this process can now be automated. Of course it's possible to automate the steps from the start, but I think it's important to grapple with the nitty-gritty so you better understand what we're doing and why we're doing it.
-
Choose "New Run Script Phase".
-
Copy and paste the following script into the text field. Don't forget to change the path in the first line and the
libfoo
s to match your project.cd ~/Library/Developer/Xcode/DerivedData/libfoo-qwertyuiop/Build/Products/Debug-iphonesimulator xcrun --sdk iphonesimulator13.4 clang -arch x86_64 -shared -all_load libfoo.a -o libfoo.dylib cp libfoo.dylib /opt/simject codesign -f -s - /opt/simject/libfoo.dylib ~/git/simject/bin/resim
-
Now whenever you build with Xcode, this script will take care of all the heavy lifting and respring any active simulators.
Happy devving!