Compiling iOS applications on-device: Difference between revisions

From iPhone Development Wiki
No edit summary
(fix SDK link)
 
(42 intermediate revisions by 3 users not shown)
Line 1: Line 1:
This article will be useful to anyone that does not have a Mac to compile apps or does not want to pay the $100/year fee to run code on your own device.
This article will be useful to anyone that does not have or want to buy a Mac to compile apps or does not want to pay the $100/year fee to run code on your own device.


You don't even need a secondary desktop or a laptop to do this! However it is not recommended to actually code the app directly on-device, unless if you're a masochist or something.
You don't even need a secondary desktop or a laptop to do this! However it is not recommended to physically code the app directly on-device using the virtual keyboard and iFile/MobileTerminal, unless if you're a masochist or something.


= Prerequisites =
= Prerequisites =


Aquire an iOS device with iOS 5 or higher and jailbreak it.
Acquire an iOS device with iOS 5 or higher and jailbreak it.


This technically could work with lower iOS versions, but the available toolchain on Cydia was compiled for iOS 5.
This technically could work with lower iOS versions, but the available toolchain on Cydia was compiled for iOS 5.


= Install the toolchain =
= Creating an "app" on the homescreen =


Open Cydia and install these:
In order to draw you in, we'll start with the easy bit first. This will just put an icon on your homescreen. No coding required for this section.


* Tape archive
Run these commands (as <tt>root</tt>, default password <tt>alpine</tt>):
* iOS toolchain
* OpenSSH
* wget
 
Or just run <source lang="bash">apt-get install tar org.coolstar.iostoolchain openssh wget</source> as <tt>root</tt> (default password: <tt>alpine</tt>).
 
= Get the SDK =
 
They are found here: http://iphone.howett.net/sdks/
 
You can literally use any SDK you want as long as they have the frameworks you need, however it is recommended you use the iOS 7 SDK or higher as the lower ones do not support arm64 (optimized for iPhone 5s and higher).
 
Right click "Download" on one of the SDKs and copy the link.
 
SSH into your device (user: <tt>mobile</tt>, default password: <tt>alpine</tt>) and run these commands:
 
<source lang="bash">
cd /var/mobile
mkdir sdks
cd sdks
wget http://iphone.howett.net/sdks/dl/iPhoneOS8.1.sdk.tbz2 #or whatever SDK you wanted
tar xvf iPhoneOS8.1.sdk.tbz2
rm iPhoneOS8.1.sdk.tbz2
ln -s iPhoneOS8.1.sdk Latest.sdk
</source>
 
Boom. Your device can fully now compile iOS applications.
 
= Creating a vanilla app =
 
== Creating the app structure ==
 
Login as <tt>root</tt> (default password: <tt>alpine</tt>) and run these commands:


<source lang="bash">
<source lang="bash">
Line 72: Line 39:
</source>
</source>


Then switch back to <tt>mobile</tt> and run:
Then <tt>login</tt> as <tt>mobile</tt> (default password <tt>alpine</tt>) and run:


<source lang="bash">
<source lang="bash">
Line 83: Line 50:
(On iOS 6 and lower, there would be no lines in the white square)
(On iOS 6 and lower, there would be no lines in the white square)


When you try to open the app, it will crash! That's because you actually haven't written anything yet.
When you try to open the app, it will crash!
 
That's because your app doesn't have any actual code in it, it's just an empty file so it automatically exits. That's where installing the toolchain comes in, so we can actually write and compile code that runs on iOS.
 
= Install the toolchain =
 
Open Cydia and install these:
 
* Tape archive
* iOS toolchain
* OpenSSH
* wget


== Actually writing a working app ==
Or just run <source lang="bash">apt-get install tar org.coolstar.iostoolchain openssh wget</source> as <tt>root</tt> (default password: <tt>alpine</tt>). Make sure to change the root and mobile passwords after installing OpenSSH.


So let's make a simple application real quick. This will not be the best written app in the world but it will have enough explanation for you to understand what you need to do if you want multiple files.
= Get the SDK =


Make a folder in <tt>/var/mobile</tt> called <tt>test_app_src</tt>.
Choose the SDK you want from here: https://github.com/theos/sdks/archive/90da5632a2045275b9cc1295ad5a1bdb36f2dfca.zip
 
If the SDK you want isn't in there, you can extract the SDK from Xcode yourself. See [[Retrieving SDKs]].
 
You can use any SDK you want (like iOS 2) as long as they have the frameworks you need, however it is recommended you use the iOS 7 SDK or later as the lower ones do not support arm64 (optimized for iPhone 5s and higher).
 
Unzip the file, then copy iPhoneOS9.3.sdk to your device, I recommend creating a folder <tt>/var/sdks</tt> and putting it there.
 
Then SSH into your device (user: <tt>root</tt> or <tt>mobile</tt>, default password: <tt>alpine</tt> for both) and run these commands:
 
<source lang="bash">
cd /var/sdks
ln -s iPhoneOS9.3.sdk Latest.sdk
</source>
 
Boom. Your device can now compile iOS applications!
 
= Finally, writing an actual working app =
 
This will not be the best written app in the world, but it will have enough explanation for you to understand what you need to do if you want multiple files.
 
Make a folder in <tt>/var/mobile</tt> called <tt>code</tt> (or something), just somewhere to hold your code.


Change directory into this folder and make 3 files: <tt>main.m</tt>, <tt>TestLabel.h</tt>, and <tt>TestLabel.m</tt>.
Change directory into this folder and make 3 files: <tt>main.m</tt>, <tt>TestLabel.h</tt>, and <tt>TestLabel.m</tt>.


=== <tt>main.m</tt> ===
== <tt>main.m</tt> ==


<source lang="objc">
<source lang="objc">
Line 99: Line 98:
#import "TestLabel.h"
#import "TestLabel.h"


@interface LyAppDelegate : UIResponder <UIApplicationDelegate>
@interface TestAppDelegate : UIResponder <UIApplicationDelegate>
@property (nonatomic, strong) UIWindow *window;
@property (nonatomic, strong) UIWindow *window;
@end
@end
Line 107: Line 106:
     @autoreleasepool
     @autoreleasepool
     {
     {
         return UIApplicationMain(argc, argv, nil, NSStringFromClass(LyAppDelegate.class));
         return UIApplicationMain(argc, argv, nil, NSStringFromClass(TestAppDelegate.class));
     }
     }
    return 0;
}
}


@implementation LyAppDelegate
@implementation TestAppDelegate
@synthesize window=_window;
@synthesize window=_window;


Line 132: Line 130:
</source>
</source>


=== <tt>TestLabel.h</tt> ===
== <tt>TestLabel.h</tt> ==


<source lang="objc">
<source lang="objc">
Line 142: Line 140:
</source>
</source>


=== <tt>TestLabel.m</tt> ===
== <tt>TestLabel.m</tt> ==


<source lang="objc">
<source lang="objc">
Line 162: Line 160:
</source>
</source>


== Compiling ==
= Compiling the code =


Run these commands:
Run these commands:


<source lang="bash">
<source lang="bash">
clang -isysroot /var/mobile/sdks/Latest.sdk \
clang -isysroot /var/sdks/Latest.sdk \
       -c main.m
       -c main.m
clang -isysroot /var/mobile/sdks/Latest.sdk \
clang -isysroot /var/sdks/Latest.sdk \
       -c TestLabel.m
       -c TestLabel.m
clang -isysroot /var/mobile/sdks/Latest.sdk \
clang -isysroot /var/sdks/Latest.sdk \
       -framework Foundation \
       -framework Foundation \
       -framework UIKit \
       -framework UIKit \
Line 178: Line 176:
</source>
</source>


If you didn't get any errors, when you list the contents of the directory you should see this:
= Installing the app you compiled =
 
If you didn't get any errors, when you list the contents of the directory with your code in it you should see this:


<source lang="bash">
<source lang="bash">
Line 190: Line 190:
[[File:4fd0b2623ffbdcb5c19e5e959bb25344.png|200px]]
[[File:4fd0b2623ffbdcb5c19e5e959bb25344.png|200px]]


WAU, that AMAZING!!!
WAU, that AMAZING!!!1!
 
= Other details =
 
== Using other frameworks ==
 
For example, if you wanted to use AVFoundation, add the <tt>-framework AVFoundation</tt> flag during the last compile step (similar to how I used <tt>-framework UIKit</tt> and <tt>-framework Foundation</tt>).
 
== Removing the black letterboxing on 4-inch devices ==


That's pretty much all you need to know to get started. If you want to use more frameworks (like AVFoundation or something) add the `-framework AVFoundation` flag during the last compile step (kinda like how I used UIKit and Foundation).
To get the app to use the entire screen real-estate you need to add a file named <tt>[email protected]</tt> to <tt>/Applications/Test.app/</tt>. The file needs to be 640x1136 pixels. Instead of creating it yourself, you could just copy it in from another application (like <tt>/Applications/Cydia/Default-[email protected]</tt>).


=== Other details ===
You will also need to run <tt>uicache</tt> again as <tt>mobile</tt> in order to see these changes take effect.


==== Enabling automatic reference counting (ARC) ====
== Enabling automatic reference counting (ARC) ==


Add the <tt>-fobjc-arc</tt> flag when compiling.
Add the <tt>-fobjc-arc</tt> flag when compiling.


==== Icons, default backgrounds, entitlements, etc ====
== Icons, default backgrounds, entitlements, iPad compatibility, etc ==
 
Check out [https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Introduction/Introduction.html Apple's documentation] on the subject. You can also look in any of the other <tt>Info.plist</tt>s in the <tt>/Applications/</tt> directory on your device! <tt>Cydia.app</tt> would be a good place to start.
 
Every change to <tt>Info.plist</tt> or  the application's icons must be followed by the command <tt>uicache</tt> as <tt>mobile</tt> in order to see changes take effect.
 
== Uninstalling ==


Check out Apple's documentation on the subject. No need to write it twice. You can also look in any of the other <tt>Info.plist</tt>s in the <tt>/Applications/</tt> directory on your device! <tt>Cydia.app</tt> would be a good place to start.
Delete it from <tt>/Applications/</tt> and run <tt>uicache</tt> as <tt>mobile</tt> again. iOS thinks it's a system app, so you can't delete it like a normal iOS app.


==== Uninstalling ====
== Getting it on the App Store ==


Delete it from <tt>/Applications/</tt> and run <tt>uicache</tt> as mobile again. iOS thinks it's a system app, so you can't delete it like a normal iOS app.
lol

Latest revision as of 04:38, 11 May 2018

This article will be useful to anyone that does not have or want to buy a Mac to compile apps or does not want to pay the $100/year fee to run code on your own device.

You don't even need a secondary desktop or a laptop to do this! However it is not recommended to physically code the app directly on-device using the virtual keyboard and iFile/MobileTerminal, unless if you're a masochist or something.

Prerequisites

Acquire an iOS device with iOS 5 or higher and jailbreak it.

This technically could work with lower iOS versions, but the available toolchain on Cydia was compiled for iOS 5.

Creating an "app" on the homescreen

In order to draw you in, we'll start with the easy bit first. This will just put an icon on your homescreen. No coding required for this section.

Run these commands (as root, default password alpine):

cd /Applications
mkdir Test.app
cd Test.app
touch Test
chmod +x Test

Then create a file Info.plist in /Applications/Test.app/ with the following contents:

<dict>
    <key>CFBundleExecutable</key>
    <string>Test</string>

    <key>CFBundleIdentifier</key>
    <string>net.iphonedevwiki.test</string>

    <key>CFBundleName</key>
    <string>LOL</string>

</dict>

Then login as mobile (default password alpine) and run:

uicache

If you did everything right, once the command is done running you should see this on your homescreen:

32b04b5cf33cd6f4790d106e3defc533.png (On iOS 6 and lower, there would be no lines in the white square)

When you try to open the app, it will crash!

That's because your app doesn't have any actual code in it, it's just an empty file so it automatically exits. That's where installing the toolchain comes in, so we can actually write and compile code that runs on iOS.

Install the toolchain

Open Cydia and install these:

  • Tape archive
  • iOS toolchain
  • OpenSSH
  • wget

Or just run

apt-get install tar org.coolstar.iostoolchain openssh wget

as root (default password: alpine). Make sure to change the root and mobile passwords after installing OpenSSH.

Get the SDK

Choose the SDK you want from here: https://github.com/theos/sdks/archive/90da5632a2045275b9cc1295ad5a1bdb36f2dfca.zip

If the SDK you want isn't in there, you can extract the SDK from Xcode yourself. See Retrieving SDKs.

You can use any SDK you want (like iOS 2) as long as they have the frameworks you need, however it is recommended you use the iOS 7 SDK or later as the lower ones do not support arm64 (optimized for iPhone 5s and higher).

Unzip the file, then copy iPhoneOS9.3.sdk to your device, I recommend creating a folder /var/sdks and putting it there.

Then SSH into your device (user: root or mobile, default password: alpine for both) and run these commands:

cd /var/sdks
ln -s iPhoneOS9.3.sdk Latest.sdk

Boom. Your device can now compile iOS applications!

Finally, writing an actual working app

This will not be the best written app in the world, but it will have enough explanation for you to understand what you need to do if you want multiple files.

Make a folder in /var/mobile called code (or something), just somewhere to hold your code.

Change directory into this folder and make 3 files: main.m, TestLabel.h, and TestLabel.m.

main.m

#import <UIKit/UIKit.h>
#import "TestLabel.h"

@interface TestAppDelegate : UIResponder <UIApplicationDelegate>
@property (nonatomic, strong) UIWindow *window;
@end

int main(int argc, char *argv[])
{
    @autoreleasepool
    {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass(TestAppDelegate.class));
    }
}

@implementation TestAppDelegate
@synthesize window=_window;

-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [UIWindow.alloc initWithFrame:UIScreen.mainScreen.bounds];
    self.window.backgroundColor = UIColor.redColor;

    UILabel *label = [[TestLabel alloc] initWithBackgroundColor:self.window.backgroundColor];
    [self.window addSubview:label];
    [label release];

    [self.window makeKeyAndVisible];

    return true;
}

@end

TestLabel.h

#import <UIKit/UIKit.h>

@interface TestLabel : UILabel
-(instancetype)initWithBackgroundColor:(UIColor *)backgroundColor;
@end

TestLabel.m

#import "TestLabel.h"

@implementation TestLabel
-(instancetype)initWithBackgroundColor:(UIColor *)backgroundColor
{
    if(self == [self init])
    {
        self.backgroundColor = backgroundColor;
        self.textColor = UIColor.whiteColor;
        self.text = @"rofl";
        self.frame = CGRectMake(20,20,300,300);
    }
    return self;
}
@end

Compiling the code

Run these commands:

clang -isysroot /var/sdks/Latest.sdk \
      -c main.m
clang -isysroot /var/sdks/Latest.sdk \
      -c TestLabel.m
clang -isysroot /var/sdks/Latest.sdk \
       -framework Foundation \
       -framework UIKit \
       main.o TestLabel.o \
       -o Test

Installing the app you compiled

If you didn't get any errors, when you list the contents of the directory with your code in it you should see this:

main.m TestLabel.m TestLabel.h main.o TestLabel.o Test

Copy Test into /Applications/Test.app/ and overwrite the old empty Test file you created earlier.

Then, go ahead and open the app again and you should see this:

Error creating thumbnail: File missing

WAU, that AMAZING!!!1!

Other details

Using other frameworks

For example, if you wanted to use AVFoundation, add the -framework AVFoundation flag during the last compile step (similar to how I used -framework UIKit and -framework Foundation).

Removing the black letterboxing on 4-inch devices

To get the app to use the entire screen real-estate you need to add a file named [email protected] to /Applications/Test.app/. The file needs to be 640x1136 pixels. Instead of creating it yourself, you could just copy it in from another application (like /Applications/Cydia/[email protected]).

You will also need to run uicache again as mobile in order to see these changes take effect.

Enabling automatic reference counting (ARC)

Add the -fobjc-arc flag when compiling.

Icons, default backgrounds, entitlements, iPad compatibility, etc

Check out Apple's documentation on the subject. You can also look in any of the other Info.plists in the /Applications/ directory on your device! Cydia.app would be a good place to start.

Every change to Info.plist or the application's icons must be followed by the command uicache as mobile in order to see changes take effect.

Uninstalling

Delete it from /Applications/ and run uicache as mobile again. iOS thinks it's a system app, so you can't delete it like a normal iOS app.

Getting it on the App Store

lol