Android is promising to become a developer-friendly embedded Linux distribution, with not only the obvious mobile applications, but also as an all-round embedded system with a nice GUI.
A port of Wt to this platform was (if we believe our customers) long overdue. And we didn’t expect it to be too difficult since Google releases a native development kit (NDK) with C and C++ compilers, and Wt uses boost as a portability layer. As with most not-so-mainstream targets, there are some pitfalls to overcome, but we discovered that Wt runs very well on Android !
After looking at the specs of Google’s Android NDK, it is clear that C++ development is fundamentally broken. The NDK has barely any support for the standard C++ library, does not support exceptions, and RTTI is disabled for some obscure reason. Luckily Android is an open platform, and the crystax version of the Android NDK is a fork of google’s NDK that enables all missing features. By linking the standard C++ library statically, binaries will happily run on a standard Android installation. Let’s hope that Google will in time realize that adding these features to the official NDK makes porting of C++ applications to the Android platform much less involved.
With the proper cross compiler in place, the next hurdle is compiling the dependencies. Wt’s only required dependency is Boost. You have to specify an amazing amount of compiler options to the NDK compiler, but Google packs the NDK with some samples where you can copy them from. Configuring bjam to build static boost libraries with the proper compilation options wasn’t too hard. Unfortunately, boost doesn’t compile and link out of the box when targeting Android. The first series of problems is caused by Android being an ARM platform, and some ARM assembly optimizations have small implementation problems, which are easy enough to fix. Other problems were caused by Android not using a 100% POSIX compliant C library. So we had to patch boost and add some defines to the command line to quick-fix this (but the patch is unlikely to make it through any tough boost community review process).
Wt itself uses CMake as build system. CMake doesn’t (yet) support Android targets out of the box, but after creating a toolchain file and a Platform file, we managed to generate a working set of Makefiles. Finally, even a bit to our own surprise, Wt itself didn’t require a single patch to compile on Android!
The venerable Hello World example worked perfectly after copying it to the emulator. One annoyance is that nothing is printed to stdout or stderr, but that is apparently a known bug in the crystax tools.
Note that Android officially does not support the deployment of native executables. Therefore you need to compile a shared library instead and use JNI to invoke your C code. The shared object and the java code are packed together in a .apk file, which can be installed through the appstore. We do not expect real problems there, and for the sake simplicity, we just copied the executable (adb push) to the emulator, which also works just fine.
When running the other examples we encountered two more slight problems. First, locale support is missing, and invocations of WString::narrow() and WString::widen() didn’t seem to behave as expected; in fact they generate pretty random strings. This causes the internal path API to fail for WMenu and other features that use narrow/widen. Secondly, the file names for temporary files are bogus. Wt assumes that it can put those in /tmp, but on android that directory does not exist. Temporary files are used only by WFileUpload and large incoming queries, so this won’t be a blocking issue for most applications until a workaround is found.
Statically linked against all dependencies, a stripped hello world is just under 1MB of size, and a stripped widget gallery is just under 2MB. With some extra effort (e.g. using UPX), you can probably further reduce this to around 250KB and 500KB respectively, which is more in line with the numbers we reported earlier for ARM.
For more information on the port, see Building Wt on Android instructions.