Creating and building a theos project within Xcode

Xcode is the go-to IDE for iOS development, with many great features. One feature that is missing however is the lack of support for building iOS projects that aren't iOS GUI applications

This is where Theos comes in.
Theos is a build system for iOS that allows a developer to easily target different types of iOS program. from command line tools to CydiaSubstrate tweaks; but you probably know that already if you clicked this post.

In the past, it has been well established that theos and Xcode provide completely different environments for building projects, and as such are (mostly) incompatible with each other. This however is not quite the case. it is indeed possible to compile a theos project from within Xcode, using Xcode's "External build system" template.

The steps

Step 0: Associate .xm files with Xcode (Optional)

Associating .xm (and other theos extensions) with Xcode allows it to treat the files as Objective-C(++) source code and provide syntax highlighting.
To do this, clone this repo by Sticktron, build and run the application once.
Thereafter .xm and .x files will be associated with Xcode and treated as Objective-C source files. This method isn't perfect as it doesn't provide highlighting for logos literals like %hook or %end, but it will do.

Step 1: Install theos

This may seem self-explanatory, but some people need reminding. For those of you without theos, follow the guide to installing it here.
For those of you with theos but an older version, it is highly recommended you install the latest version from the above repo.

Step 2: Creating a new Xcode project

To begin, create a new xcode project and select "Other"
Then choose the External Build System option.

Click next.

On the following screen, it should prompt you for the usual product name and other general data. It should also ask you to enter a build tool. Enter /usr/bin/make (or wherever make is installed on your system).

Create the project.

Step 3: Setting up the build system

Now that we have created the project, we have to change a few of the project settings for Xcode to be able to call theos.

Open the project's Build Settings. We need to add a new User-defined variable to the project.

Name the setting THEOS and the value /opt/theos (or wherever you installed theos).

You may also mess around with the clang settings if you like, but this is optional.

Step 4: Coding and compiling

Now that the build system is set up, it's time to start coding.
Before we do that however, we have to create a makefile for theos. Create a new file in the project and call it Makefile. Place it in the root of the project.
This makefile will contain the same content as a standard auto-generated makefile by theos. Therefore it will differ depending on which type of project you want to make. This tutorial assumes you are making a tweak.

Here is a standard makefile template for a tweak.

include $(THEOS)/makefiles/common.mk

TWEAK_NAME = YOURTWEAKNAME
YOURTWEAKNAME_FILES = Tweak.xm

include $(THEOS_MAKE_PATH)/tweak.mk

Remember to change YOURTWEAKNAME to the name of your project

Next we need to add a filter plist to the project. Add another new file and name it YOURTWEAKNAME.plist where YOURTWEAKNAME is exactly the same as that entered in the makefile.

Add the following code to it (you may need to use a text editor that's not xcode). Remember to change the Bundle from com.apple.springboard if you're targeting anything other than Springboard

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Filter</key>
	<dict>
		<key>Bundles</key>
		<array>
			<string>com.apple.springboard</string>
		</array>
	</dict>
</dict>
</plist>

Lastly, create another new file called Tweak.xm. I'm sure you know what this is for. Place it in the root of your project again.

Add all your code to the Tweak.xm, and when you're done you can build your project.
If you encounter any errors, see the section on possible errors below.

to build the project, just build it how you would any other xcode project. Product > Build

Your project should be laid out similar to this:

Errors

As with any hacky setup, there are likely to be problems with this. I will attempt to list all the errors I encountered making this tutorial, but be warned you may encounter problems not on this list.

ErrorSolution
ldid: command not foundEven if ldid is in /usr/bin, for me theos just couldn't find it. My solution was to copy ldid from /usr/bin to $THEOS/bin (where $THEOS is your theos install directory) ``sudo cp `which ldid` $THEOS/bin``
/makefiles/common.mk: No such file or directoryThis error indicates that either you forgot to add the THEOS variable to your project, or that the path you added is incorrect. Please check your path again
Architecture not supported errorsThese errors occur when theos incorrectly assumes you are building for OS X. Try updating theos to the latest version or running `make clean` on the project

Autocompletion and proper syntax highlighting

As it stands, your current project will have some very basic Objective-c syntax highlighting; not the full fat version offered by real Xcode projects. Your project will also not have any autocompletion.
There is an easy (but hacky) fix for this however.

Add a new target to your project. Choose something like a single view iOS app and call it dummy.
Assign all your source files to the app. Please note this won't work if your code has any logos literals like %hook or %end. You can wrap these literals in a block like so:

#ifdef THEOS
%hook SBDeckSwitcherViewController
#endif 

- (BOOL)isDisplayItemOfContainerRemovable:(id)arg1 {
    return YES;
}

#ifdef THEOS
%end
#endif 

This is perfectly fine because the dummy project is only being used to get Xcode to generate the required metadata for autocompletion to work.

Build the dummy project once, and if successful, your code should now be properly syntax-highlighted and autocompletion should work.

The future

I plan to make a collection of project templates for Xcode based off of this method. Hopefully they can be used to replace the outdated iOSOpenDev library. I still need to do more research into Xcode's template format however. If you know anything about these templates, please reply here or tweet me.

Hope this tutorial was helpful, and if you spotted a mistake in it leave a comment below

Oh, and follow me on twitter

-Satori