Introduction
Golden Hammer Software took a trip earlier this year to New York to attend the Intel Android CodeFest. We updated Big Mountain Snowboarding, Trick Shot Bowling, and Scribble Worm to run natively on Intel Android devices during that weekend. All three of these games use C++ through the NDK.
Java-based apps don't require any extra work for Intel devices. C++ apps compiled for ARM will run on Intel devices thanks to a run-time interpreter. C++ apps that are more processor intensive would benefit from cross-compiling for ARM and x86. The native x86 code should be faster and more efficient on an x86 device. This article shows the steps involved in setting up an NDK project to compile for multiple target platforms.
Compiling C++ for Multiple Architectures
The first step is to edit the Application.mk file to add additional platforms under the APP_ABI flag. It’s possible to put “all” here in order to create a .so file for every architecture supported by Android, but compile times would get very long. Unless you are using special armv7 api calls, x86 and armeabi should be enough. This will create two .so files. Unfortunately, it also doubles the compile time.
Application.mk
APP_ABI := x86 armeabi
Linking the .so Files with the Java Project
The two .so files will be created in [ndk project dir]\libs\armabi and [ndk project dir]\libs\x86. They need to be copied into separate directories under your Android java project.
We use a simple bat file to copy the files for us every time we compile. This file lives in our NDK\[Project]\jni folder.
CMD /C ..\..\..\..\..\..\contrib\android-ndk-r9c\ndk-build
copy ..\libs\armeabi\libGHBowling.so ..\..\..\GHBowling\libs\armeabi\libGHBowling.so
copy ..\libs\x86\libGHBowling.so ..\..\..\GHBowling\libs\x86\libGHBowling.so
Supporting Multiple C++ Libraries
Our games use multiple C++ libraries. We have our game-independent code in one library and our game code in a second library. The game library needs to link with the game-independent library. We were able to add a concrete relative path from one project to another when supporting only ARM, but the Android.mk file has to be updated when dealing with multiple targets. The flag $(TARGET_ARCH_ABI) will grab the appropriate library during each compile pass.
Android.mk
include $(CLEAR_VARS)
LOCAL_MODULE := libGHEngine
LOCAL_SRC_FILES := ../../GHEngine/obj/local/$(TARGET_ARCH_ABI)/libGHEngine.a
include $(PREBUILT_STATIC_LIBRARY)
Compiler Differences
I highly recommend testing on an actual Intel Android device. There are subtle compiler differences. We had a null pointer crash that wasn't exposed until we compiled for x86. It was a real bug that existed on all platforms, but somehow the other compilers managed to create code that would function while touching out of bounds memory. When we ran the x86 Android code on a Samsung Intel Android tablet, the game crashed on startup until we found and fixed the bug.
Final Thoughts
Intel has created a series of tools to make Android development easier that can be found at https://software.intel.com/en-us/android/tools. These include an emulator, a graphics profiler, a cross-platform library, and a full game engine. We have also benefitted from Intel® Developer Zone programs like the Intel Android Showcase.
Supporting Intel Android in your C++ app is a fairly easy process. ARM C++ libraries are likely to work without modification, but a couple simple makefile changes will make them run more efficiently. Java apps don't require any changes to support the new hardware.
Related Articles and Resources
Author Bio
David Wingrove has four years of experience making Android applications and 14 years of experience making games. He is the co-founder of Golden Hammer Software, and has released games for Android, Wii, PC, iOS, Blackberry, and other platforms.