In my daily work (the one that pays the bills) I've been burdened with the
responsability to port two projects to the Android platform:
hop
, a programming language for the web
2.0/application server writen in Scheme
. For that I would need to also port
bigloo
, a Scheme
compiler. The
goal is to be able to run hop
apps in the phone itself.
I really didn't know much about the platform then, only that probably it would
be a fun platform to have in your phone, being GNU/Linux based, open source and
all. There was also the promise to play with these phones; being somewhat a
technophile, that was definetely a plus. With a smile in my face, I cracked may
hands, sat down and started... reading.
The first thing one learns when reading about developing for the platform is
that the language is Java
. There's a complete
SDK for developing them. If you
want to port some C/C++
library, you can do so with the
NDK, and that's pretty
much it. Now, from my point of view, this is very restricting: you cannot choose
your own programming language. Even if I like the language a bit (but not its
std library or the way that the language is driven), I prefer Python
or
whatever suits better the problem. But then, I understand Android/Google/OHA
needs to be control freaks with the apps running on the phone, because there are
limited resources and you cannot leave an application open forever. So, they
devised their component
lifecycle,
which reminds me of OSGi, made it in
Java
, made all the tools and that was it.
But in my case I needed a native port, and that's for two reasons. First, even
if bigloo
can produce Java
bytecode, and even when I've been told that
Dalvik
, their JVM
implementation, can run Java
bytecode, the result is not fast enough, being
a both bigloo
and the JVM in turn problem. Certainly bigloo
's Java
output
might not be the best, but also the JVMs we tried were too heavy. The second
and most important reason is that if we did a Java
port, we would be tied to
the component lifecycle I mentioned above. We need a hop
daemon running in
order to be able to run its apps. If this deamon goes off by the platform's
request, there's no way to awake it again when a (web) client tries to make a
request, so the request would fail and would make hop
useless. Hence, a
native port.
I have to say in everybody's defense that this is my first contact with
toolchains and cross compiling.
Given that native porting is not supported, I went off searching. The
first
posts talked about static
linking. This guy even pointed to a first
wrapper for the precompiled toolchain and gave some details on some CFLAGS
to
set. But static linking was not an option for us. hop
uses bigloo
's runtime
libs as dynlibs.
Then I
hit Rob Savoye's
efforts to port gnash
. There
I started to fully understand the Android platform: «while the C compiler is ok,
the C++ compiler is crippled. No iostream support in libstdc++, no locales,
etc... Then to make it more fun they use their own libc called Bionic, which is
trimmed down for embedded devices». He has more details on C++
compilation
because he needed it (we don't... yet).
So I turned to what I knew, if it only was its name:
emdebian
. I was till a litle hazy about what cross
compiling meant, so I started to make questions. Thing is, emdebian
is coupled
with Debian
(it only makes sense), so the first step would have been creating
a Bionic
package. Of course, this was way beyond my requirements and
abilities. In that channel I was also pointed to a post by Harald
Welte,
which in turn links to a talk called "Android
Mythbusters",
where we learn also that the linking is not standard [s.6], some hacks in
the device support [s.7], hardcoded hotplug [s.8], no
tslib
support [s.12], hardcoded limits [s.13], and
a lot more of calamities, including bad community support [s.18], and its peak,
the
CyanogenMod-gate.
All that analisys is nice, but I was still stuck with no porting system. My boss
suggested scratchbox
, but just like emdebian
it only has support for (e)glibc
and uClibc
. It is possible to add support
for other platforms, but their script didn't work and my feeble attempts led me
no closer to a solution.
Then with a strike of luck I found Joel Reymont's Android
Notes, who not only
explains a little more the platform, but also has a example Makefile
for
compiling executables for Android. And then, just a few minutes later, Takuya
Murakami's wrapper, which, together
with the prebuilt toolchain in Android's source
code, made most of it. I finally got a
simple Hello World!
dynamic executable running in the emulator.
From here all was mostly downhill. The last stone in the path was a linking
problem. bigloo
uses Boehm's
gc
, a renowed garbage
collector used by several proyects, including mono
and ocalm
. gc
needs a
symbol called __stack_base__
defined, which, from what I could find looking,
used to be defined in crt0.o
, one of the parts that the compiler normally
attaches to executables to make them so. The problem is that this file is not in
the SDK or Android's source code/prebuilt toolchain. To be fair, that file is
not to be found in a fairly new distro. What I found was a reverse engineered
crt0.S
, but it doesn't define the symbol I needed, and in any case I already got
running executables in the emulator. In the other hand,
naoya_t
seems to
have hit the same problem, but he writes in japanese and I couldn't get hold of
anyone to translate it for me.
Long story short, I made a
hack
to make the linking happy. bigloo
finished compiling, I pushed it to the
emulator and... it worked!
Some notes about this port: with a little bit of luck it will be officially
announced next week, even if it works with a hack. Ivan Maidanski assures
me
that it should not be nessesary, so probably there's an error on our side
when configuring gc
; but then again, I spent more that 2 weeks with that
problem alone and I followed all the suggestions they gave us, so I'm pretty
sure is something in the middle. Also, mono
has been ported to
Android, and even if I read references to
the NDK, I've been assured that it's a native port. If they could port it
without hacks, so should we.
Lastly, some notes about the crippled GNU/Linux running behing the Android
platform: besides all the low level stuff mentioned by others cited above, there
are no cp
or tee
; ls
does not support the -R
option, mkdir
does not
support the -p
option, and even when one of these tools don't recognize an
option, instead of barking, it happily accepts it as another file to treat. so,
mkdir -p bongs/bonga
creates a -p
dir and barfs on bongs/bonga
. What it is
there, yes, are dd
and strace
! Not very surprisingly, there's no
/etc/passwd
, but then the system somehow knows several others users besides
root
and shell
, so I guess they're hardcoded somewhere. It's really
impressive the effort they put to cripple this thing. Most probably they're
using a tool like BusyBox
, and if so, they are only saving some directory
entries in the case of cp
or tee
and wasting time in the other cases.
All in all, I'm dissapointed by the platform. I understand that what we're
trying to do is not supported, and that alone tells me that I don't want an
Android device until this has changed, if it ever does. Probably the fact that
Android is (now) open source and that the Cyanogengate led to the formation of
«the Open Android Alliance (not to be confused with the Open Handset Alliance)
an organization whose stated goal is to distribute "a Flavor of Android that
is fully customizable and does not rely on Google or other copyrights» gives the
platform some hope.
Meanwile I will prefer Maemo
(who at least looks more
open), specially now that Qt
will be the default toolkit. I'll also keep an
eye on Bada
, Samsung's new platform. There are not
many details about this last one, except that they have their own toolkit in
C++, and from the API's
documentation, it looks like it's a very thorough
one.