Archive for November, 2007

Using Scratchbox to build complex ARM binaries for Android

Sunday, November 25th, 2007

Benno explains how to build simple native programs for Android. But any significant pre-existing Linux software package uses a complex array of libraries and a correspondingly complicated build process, typically based around GNU Autoconf. That build process usually involves a “configure” script whose purpose is to run tiny programs to experiment with the system, to find out its capabilities and set up the code appropriately.

Terrific, except it doesn’t work if, say, you’re building on an Intel x86 box, but trying to build for Android, which is based around Linux and an entirely different CPU. Fortunately, the Scratchbox project exists to solve this problem. It provides you with a special Linux universe, which uses the QEMU emulator to run ARM binaries. Hence: autoconf can run its experiments and all will be well.

It worked surprisingly well and surprisingly simply. Good work by the Scratchbox team.

Maybe this is how Benno produced his strace binary which he used to dig up some interesting stuff from Android. I’m not sure. Either way, I’m going to be building strace here as an example of how to get this stuff to work.

  1. You’re really going to need Linux. Specifically, it sounds like a Debian-based distribution is by far the most likely to work. Since I’ve got a Mac, I had to install Ubuntu Linux 7.10 within a Parallels virtual machine. This is easier said than done, in itself, but once the X-server problems were sorted out it was reliable.
  2. First we need to install Scratchbox. It’s available as Debian packages. You can install it either using command-line tools, or the GUI package manager. So naturally I chose half-and-half.
    1. Edit (as root) /etc/apt/sources.list, and add this line: deb stable main
    2. Use the Synaptics Package Manager (in the System menu) to look at the available packages. You’ll need:
      • scratchbox-core
      • scratchbox-libs
      • qemu (not 100% convinced this is really required; I think it may be provided with Scratchbox)
      • scratchbox-devkit-cputransp

      You’ll also need a toolchain. Which toolchain(s) to choose was a bit of a mystery. I’d like to have seen a package using CodeSourcery’s latest compiler, 2007q3. But it seems the Maemo platform, the main user of Scratchbox, is stuck on an older compiler. To be honest, more of an issue than the compiler is probably the version of libc in use within the Android platform. I haven’t figured that out yet, so I’ve been producing statically linked binaries for the moment. Anyway, for my toolchain, I chose scratchbox-toolchain-arm-linux-2006q3-27, which appeared to be the most recent.

    3. Wait for these to install…
  3. As per the Scratchbox install document and these Maemo-focussed instructions, add your user to scratchbox: sudo /scratchbox/bsin/sbox_adduser adrian
  4. Log out and log in again until the groups command reveals you’re in the sbox group
  5. Run scratchbox
  6. Run sb-menu
  7. Create a new target. Configure it thusly:
    1. Select the compiler you installed, arm-linux-2006q3-27
    2. Select cputransp devkit
    3. Select qemu-arm-0.8.2-sb2 emulation
    4. No to rootstrap
    5. Yes to files. Choose C-library, /etc, Devkits and fakeroot
  8. Scratchbox screenshot

  9. Exit sb-menu. You will be deposited back at the scratchbox shell, but this time the shell is able to run ARM binaries. So things like configure should work.
  10. Fetch your source. I built /scratchbox/packages/hello-world.tar.gz and also strace 4.5.15. In theory you ought to be able to build anything (so long as static linkage is OK, and so long as the configure script doesn’t do anything too wacky that qemu can’t emulate). For your first build, perhaps stick to the hello world example?
  11. Unzip it/install it/etc. into your scratchbox home. What appears to be /home/xyz is actually located at /scratchbox/users/xyz/home/xyz so that’s where to put the files. (The reasons scratchbox maintains a separate root is so that there’s no chance any of your important system files can be blatted whilst building things for a different architecture).
  12. ./configure LDFLAGS=--static (that’s minus-minus static, in case the blog software munges it)
  13. make
  14. That’s it! You now need to move the generated binary from here onto your Android emulator in the tried and trusted way, then execute it:
  15. MacBook:Desktop adriantaylor$ file hello
    hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.14, statically linked, for GNU/Linux 2.6.14, not stripped
    MacBook:Desktop adriantaylor$ cd android_sdk_darwin_m3-rc20a/tools/
    MacBook:tools adriantaylor$ ./adb push ../../hello /system/bin/hello
    2006 KB/s (563210 bytes in 0.274s)

    In my case, rinse and repeat for strace, then…

    MacBook:tools adriantaylor$ ./adb shell
    # /system/bin/hello
    Hello World!
    # /system/bin/strace /system/bin/hello
    execve("/system/bin/hello", ["/system/bin/hello"], [/* 8 vars */]) = 0
    uname({sys="Linux", node="(none)", ...}) = 0
    brk(0)                                  = 0x80000
    brk(0x80c70)                            = 0x80c70
    syscall_983045(0x80430, 0x7dd88, 0, 0x10, 0x80430, 0x7e734, 0x7ea38, 0xf0005, 0x28, 0x8, 0x4, 0x10, 0, 0xbe94cb08, 0x11da8, 0x8834, 0x60000010, 0x80430, 0, 0, 0, 0xc8c8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0
    brk(0xa1c70)                            = 0xa1c70
    brk(0xa2000)                            = 0xa2000
    fstat64(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 0), ...}) = 0
    mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40000000
    write(1, "Hello World!\n", 13Hello World!
    )          = 13
    munmap(0x40000000, 4096)                = 0
    exit_group(0)                           = ?
    Process 547 detached

Maybe I’ll eventually get some time to get dynamic linkage working, which shouldn’t be too hard, just a matter of working out which libc to use. Famous last words?

Update: yes, dynamic linkage may be too much to hope for. The libc is apparently derived from BSD rather than glibc. And I can’t get these tips to work.

IPC on Android

Monday, November 19th, 2007

A couple of links: some investigation and some more information on it.