Porting libGDX games to iOS, for Apple dummies (part 1/2)


Update (14 September 2016): A month after I wrote this, RoboVM announced that they were winding down. I already had a (free) license, which is good until April 2017, but if you need a new one, you’re out of luck.

The thing that comes closest is MobiDevelop’s RoboVM fork, but that is a stopgap at best, because it will probably never support bitcode (which Apple is pushing for). The alternative is Intel’s Multi-OS Engine (MOE), and with the future uncertain, both are actively being supported by libGDX right now. I recommend you read this post by Mario and make up your own mind about what to use.

Regardless of what happens in the long run, MobiDevelop’s RoboVM fork seems to be working fine for many people so far. If you want to use MOE instead, most of this article still applies anyway.


As regular readers of this blog will know, I’m working on a game for mobile devices, iOS and Android, so far known as Mystery Game No. 1. For portability, I use libGDX. So far, I’d done all my development for Android, since this is what I know best. But last week the time had come to face the Apple music.

Since I didn’t own any Apple devices, only ever used them superficially, and certainly never developed any software for them, it was an interesting journey. For those of you going down the same road, here’s a tutorial of sorts: How to get a libGDX game running on iOS from scratch?

Because this post grew rather long, I’ve split it into two parts. The second part will be published next Friday, one week from now. In this first half, we take a look at the necessary hardware and software, and get to the point of running our libGDX game on the iOS Simulator.

Since tutorials of this sort tend to get outdated pretty quickly, I’ll try to future-proof it by recording version numbers and dates wherever possible. This post is up to date as of March, 2016. Also note that it’s not a “click here, click there” type of tutorial; some independence and critical thinking is assumed. But since you’re a software developer, that should be fine, right?

1. Buy a MacDevice

Sadly, Apple makes it all but impossible to develop iOS applications on non-Apple hardware. That means you’ll need a Mac computer as well, so you can run Xcode, Apple’s IDE. If you use this machine just for porting, it doesn’t need to be the latest, fastest model, but you will want to make sure that it can run the latest version of OS X (at the time of writing, that’s 10.11, also known as El Capitan), because Xcode prefers this. Again, here is a useful table on Wikipedia. OS X upgrades are downloadable for free nowadays, and let you skip intermediate versions, so don’t worry if the machine you buy ships with an older version.

Pay attention to memory. RoboVM seems to be quite a beast, and recommends to create a 2 GB ramdisk just for its intermediate files. If your machine has only 2 GB, this may not make you happy. I recommend 4 GB at least, unless you enjoy looking at a beach ball for minutes while your machine is swapping.

An SSD is definitely nice for performance as well. You could consider getting a model with a regular HDD, and upgrading to an SSD if that becomes unbearable.

You may also need to pay attention to the graphics card. Some Macs have an on-board Intel chip, and I’m not entirely confident that it will support the OpenGL version that libGDX requires. Newer models have an NVIDIA GeForce 9400 chipset, which is certainly fine for this purpose.

For development, your options are basically a MacBook laptop, or a Mac Mini desktop. MacBooks are more expensive, and for development you’ll probably want the even more steeply priced MacBook Pro line. On the other hand, they do come with a screen, keyboard and touchpad included. If you go for the Mac Mini, you’ll either need to get these peripherals separately, buy a KVM switch, or be content with switching cables manually. (Come to think of it, some sort of remote control from your regular PC is probably also an option.) You do not need to buy an Apple keyboard or mouse; regular USB devices for PCs work fine. The “Windows” key then takes the function of the “Command” key, labelled ⌘.

Since I am already quite happy with my desktop peripherals, I opted to get a Mac Mini model from late 2009, with a 2.26 GHz Core 2 Duo CPU and 5 GB RAM. I found this on eBay for about €250.

2. Buy an iDevice

Apple offers an iPhone/iPad simulator that runs on OS X, but it’s slow, and of course not fully representative of a real device. So you’ll want to get some hardware to test on. There isn’t as much fragmentation as on Android, so unless you’re doing something special, a single device should suffice. This doesn’t need to be the very latest; in fact, it’s better if it isn’t, to make sure that any performance problems on previous-generation hardware will show up loud and clear.

Apple users are good at upgrading their iOS version, so unlike on Android, you don’t need to worry about a wide range of versions. However, you will want to make sure that your device supports the latest iOS version for testing, and maybe make an educated guess that it’ll support the next future version as well. There is a nice table on Wikipedia that I found very useful.

You will also want to get a device with a Retina display. Retina is Apple’s word for high-resolution, and any device marked Retina will do upscaling tricks in legacy apps. So this is useful for testing that your game deals properly with that, or better, that it has the high-resolution assets to be rendered in a 1:1 virtual-to-real pixel ratio.

At the time of writing (February 2016), the cheapest device that met these requirements is the iPad mini 2. (The “mini” series are similar to their large counterparts, except smaller.) I got one off eBay for €180.

3. Upgrade OS X

The Mac Mini came with the ancient OS X 10.6 (Snow Leopard) preinstalled. Upgrading to El Capitan is painless; see the instructions here. I had to install all OS updates before I was able to install the El Capitan upgrade from the App Store; without these updates, the El Capitan downloader would just hang without progress. YMMV.

During the upgrade, take some time to get acquainted with OS X. Some pointers for those from a PC world (be it Windows or some Linux GUI):

  • Most keyboard shortcuts are similar to other operating systems if you replace Ctrl by Cmd (⌘).
  • Home and End don’t take you to the beginning/end of the line, but to the beginning/end of the document. Use ⌘← and ⌘→ instead. This still trips me up about once every 10 seconds.
  • Use Alt+← and Alt+→ (instead of Ctrl) to navigate between words. Similarly, Alt+Backspace and Alt+Delete erase the word before and after the cursor.
  • Window management is surprisingly primitive, for an OS that pretty much invented it. I’m sometimes unsure whether my clicks got through (they don’t if the window doesn’t have focus), maximising windows is hard (unlike my limited OS X experiences in the past, the green button makes them go fullscreen instead), multiple windows from the same app are grouped in the Dock, and the menu bar appears at the top of the window in compliance with Fitts’s Law but entirely out of context. Maybe I just need to get used to it, but I’ve seen experienced Apple users flounder with window management as well.
  • Mouse cursor movement is super slow, which also seems surprising for such a mouse-driven OS. You can fix this to some extent in System Preferences, but I recommend SmoothMouse in addition to that. Still not a panacea, but much better than the default.

4. Install software

Once you have upgraded to the latest OS X version, it’s time to install the required software. There are some interdependencies here, as well as some hefty downloads, so I suggest doing things in the following order.

Note on installing software: unlike Linux, OS X does not have a real package manager. Some apps are available through the App Store, but most need to be downloaded from their respective websites directly, like on Windows. This results in a .dmg or .zip file, which you can double-click to reveal its contents. Typically, the contents are a directory with a .app extension, which you install simply by dragging (copying) it to your /Applications folder. Some .dmg files seem to contain some magic which will suggestively display a drag-n-drop arrow to a symlink to /Applications (at least, that’s what I think it is).

4a. Install Xcode

Xcode is Apple’s development environment, the equivalent of Visual Studio from Microsoft. Unlike most apps mentioned here, this one does come from the App Store. The download is free, but several gigabytes in size, and (especially if you don’t have an SSD) takes a long time (half an hour?) to install. Be patient.

Note that you don’t actually need to develop your game in Xcode; you can still use IntelliJ for that. You need Xcode for the compiler toolchain it provides, and certain packaging actions need to be done through its UI.

I got Xcode 7; if you are coming from the future and get a later version, some stuff might be different.

4b. Install iTerm2 (optional)

OS X is a Unix, and comes with its own built-in terminal emulator, called Terminal. It is very basic, and if you expect to spend even a few minutes in the terminal, you want iTerm2 instead. Set this up while you’re waiting for Xcode to download and install.

4c. Install homebrew (optional)

If you want a more complete command-line experience, look into homebrew, “the missing package manager for OS X”. It requires Xcode to be installed.

After installing homebrew, you need to run this in a terminal:

sudo chown -R $USER /usr/local

If you’re from a Linux or other Unix background, this should scare you. But apparently this is the way it’s supposed to be done; homebrew does not want to run as root. Deal with it.

After fixing this permission error, I used homebrew to install command-line Git like so:

brew install git

4d. Install Android SDK (optional?)

I got prompted to install the Android SDK (ADK for short) when launching IntelliJ IDEA for the first time, but with hindsight, I think it was because I chose to install the Android plugin for IntelliJ, which is not actually required for iOS development. Still, here’s how to do it.

Download the Android SDK. You just need the SDK, not the full Android Studio (we’re using vanilla IntelliJ IDEA with the Android plugin). Unpack it wherever you like; mine is in /Applications/ADK.

Run the tools/android executable (which is the Android SDK’s own package manager) to install some necessities, documented here.

For IntelliJ and other tools to find the Android SDK, you need to set the environment variable ANDROID_HOME. This is done for the current session (except already running applications) with this command:

launchctl setenv ANDROID_HOME /Applications/ADK

To persist this setting, create a file named /Library/LaunchDaemons/setenv.ANDROID_HOME.plist with the following content (be sure to use the correct ADK path):

<?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>Label</key>
    <string>setenv.ANDROID_HOME</string>
    <key>ProgramArguments</key>
    <array>
      <string>/bin/launchctl</string>
      <string>setenv</string>
      <string>ANDROID_HOME</string>
      <string>/Applications/ADK</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>ServiceIPC</key>
    <false/>
  </dict>
</plist>

Yep, OS X may be a Unix, but /etc/profile was too much to expect…

4e. Install Java

IntelliJ IDEA 15 comes with a bundled JVM, but this is Java 1.6, whereas the RoboVM plugin requires 1.7. Just install the latest Java from Oracle and IntelliJ will pick it up (check the About screen to make sure). I got Java 1.8.0u74.

4f. Install and configure IntelliJ IDEA

Download and install the latest IntelliJ IDEA (15 at the time of writing). (Aside: this IDE is technically called “IDEA”, IntelliJ being the former name of the company, but I’m going with the popular vote here and referring to the software product as “IntelliJ”.)

Before you dive in, we need to make some configuration changes for the sake of the RoboVM plugin. I used this excellent guide. It’s a bit dated because you no longer need to change the JVM version, but you do still need to increase memory. Do this as follows:

  • Right-click the IntelliJ app in Finder, and choose “Show Package Contents”. Browse to Contents/bin, then open idea.vmoptions with TextEdit. Change the -Xmx line to at least 1 GB (I used 2 GB):

    -Xms128m
    -Xmx2048m
    -XX:MaxPermSize=350m
    -XX:ReservedCodeCacheSize=240m
    -XX:+UseCompressedOops
    

Save and exit.

Launch IntelliJ. If asked about the Android SDK, you should have the option to use the existing SDK. If that doesn’t appear, make sure ANDROID_HOME is properly configured.

4g. Install the RoboVM plugin

In IntelliJ, install the RoboVM plugin. You need to supply it with a license key, which you can get for free if you use libGDX; see the process documented here.

You can speed up RoboVM compilation by supplying it with a ramdisk for its temporary files:

SIZE=2048 ; diskutil erasevolume HFS+ 'RoboVM RAM Disk' `hdiutil attach -nomount ram://$((SIZE * 2048))`

If you forget this, a console message will scroll by to warn you, but things will still work. I’m not entirely convinced that the gain of not writing temporary files to disk is greater than the loss of having to swap out more memory. YMMV.

5. Run your game in the simulator

If all went well, you should now be able to open your root build.gradle file in IntelliJ. Wait for it to do its gradle and indexing stuff, and notice that an iOS RoboVM launch configuration has appeared. For starters, configure it to use the simulator rather than a real device. Then run it! Compilation takes about 10 minutes on my system.

If all went well, you should see a fake iPhone appear, running your game. If there are any exceptions, they’ll show up in the console in IntelliJ. If not, congratulations!

That’s it for part one of this series. In part two, we’ll take a look at running the game on a real device, doing some polishing to integrate it better with iOS, build a production release, and upload it to the App Store!