Using Scratchbox to build complex ARM binaries for Android

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 http://scratchbox.org/debian 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.

6 Responses to “Using Scratchbox to build complex ARM binaries for Android”

  1. […] Nadim S. Haque wrote an interesting post today onHere’s a quick excerptThis is easier said than done, in itself, but once the X-server problems were sorted out it was reliable. First we need to install Scratchbox. It’s available as Debian packages. … ROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0×40000000 write(1, “Hello World!n”, 13Hello World!… […]

  2. […] As soon as Android was released people got to work delving into the native side of things and now Macrobug has posted about how you can use Scratchpad to build ARM binaries for Android: […]

  3. […] built this using my Scratchbox as per my previous instructions. You’ll need to run automake first to rebuild the makefiles to include the extra source code […]

  4. pligg.com says:

    Using Scratchbox to build complex ARM binaries for Android…

    Benno explains how to build simple native programs for Android. … 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…

  5. Hans says:

    A very nice and very good tutorial … helped me a LOT! My question: Did you already dig deeper? For example: did you already try to put more tools into Android (e.g. bash, nmap, etc.)?

    If yes: Did you succeed? I’m still coping with the trouble that Google changed the filesystem layout drastically and that everything is at a different location :-(

    Would be nice if you have some ideas so we could exchange experiences …

  6. Hi Hans, thanks for the comment, but no, I didn’t try any other tools. I improved and expanded strace a bit to be able to look into OpenBinder interactions, see http://www.macrobug.com/opensource/, but I didn’t even finish that! Good luck :-)