While most Ubuntu users are using so called x86/x86-64 hardware, Ubuntu also targets other architectures, such as PowerPC, or ARM. How does development differ on these architectures? It's mostly the same, except slower and with scarce hardware; there are however alternate ways to speed up development or to work around lack of hardware. Here we will be looking at which options you have for development.

Native development

The most straightforward way to do development if you have sufficiently fast hardware -- with enough memory and storage -- is probably on your device itself. The usual development tools and packages described in UbuntuDevelopment apply.

QEMU

QEMU is a processor emulator and supports emulation of ARM, PowerPC, SPARC, x86, x86-64 and more.

QEMU has two operating modes:

User mode emulation: QEMU can launch Linux processes compiled for one CPU on another CPU, translating syscalls on the fly.

Full system emulation: QEMU emulates a full system (virtual machine), including a processor and various peripherals such as disk, ethernet controller etc.

User mode emulation and binfmt_misc

This QEMU mode is faster than full system emulation, but is not a perfect abstraction. For instance, if a program reads /proc/cpuinfo, the contents will be returned by the host kernel and so will describe the host CPU instead of the emulated CPU. Also, QEMU's emulation does not cover all syscalls so it might result in debug output like:

qemu: Unsupported syscall: 335

Which means that QEMU does not know how to emulate the guest syscall 335 (sys_pselect6). Worse, QEMU might emulate syscalls which are actually unimplemented in the target architecture, causing the emulated program to believe the target architecture is more capable than it really is.

To use QEMU syscall emulation, you can invoke qemu-''cpu'' binaries followed by the command you'd like to run, e.g. qemu-arm; unfortunately, this is quite limited because you may only run static binaries like this, as the shared binaries/shared libraries would be under a different path than the ones these were compiled with. For instance, in this interactive session we are at the top of an armel rootfs and we try running bin/ls with qemu-arm on an amd64 host:

This makes it impractical to call qemu-arm by hand. However, thanks to a Linux module called binfmt_misc, it's possible to run any executable file with a specific filename or specific contents with a configurable interpreter. The qemu-kvm-extras-static package in Ubuntu 10.04 and later registers QEMU interpreter for the binary patterns of binaries it can emulate with binfmt_misc; this means it's not needed to prefix commands with qemu-arm anymore:

But the qemu-kvm-extras-static package, as it name implies, provides static versions of qemu-''cpu'' interpreters, for instance qemu-arm-static. These work exactly like their shared equivalents, but as soon as they are copied in a rootfs tree, it becomes possible to chroot into it (without the need for a host ld-linux dynamic loader, or the host shared libraries):

Such a chroot can be created with the qemu-debootstrap command (from the qemu-kvm-extras-static package) which behaves like debootstrap, but copies a static qemu interpreter in the chroot as well.

This chroot should behave mostly like a regular chroot, with the associated drawbacks (no isolation as in virtual machines) and the limitations of qemu syscall emulation.

One may combine syscall emulation with some tools like pbuilder or sbuild; read on for specific instructions for each tool.

In summary, user mode emulation is a nice mode when it works and should be preferred when speed matters, but full system emulation mode should be used for a more complete emulation.

Full system emulation

This QEMU mode emulates a virtual machine with a configurable CPU, video card, memory size and mode. It is much slower than user mode emulation since the target kernel is emulated, as well as device input/output, interrupts etc. However, it provides a much better emulation for guest programs and isolates from the host. It should not be considered a secure sandbox though.

Full system emulation should be preferred to run programs like gdb, or to test a real installed system perhaps with graphical apps, or running an OpenSSH server.

There are various ways to create a QEMU virtual machine.

For ARM, the currently supported methods are:

using the "versatile" netboot images of the alternate installer; see below

Cross-compilation

Specific software such as the kernel or bootloaders are easily cross-compiled; this works as expected under Ubuntu, it's a matter of making sure the relevant cross-compiler is in the $PATH, either by installing it from packages which ship it in /usr/bin, or by installing it to /usr/local/bin, or by installing it in one's $HOME/bin directory and appending ~/bin to the $PATH.

Some build systems will autodetect cross-compilation when passed host and target architectures, but others might expect the cross-compiler to be set in the CC, LD etc. environment variables.

Kernel cross-compilation

The Linux kernel is of course cross-compilation friendly; you can cross-compile the Linux kernel by setting the architecture and cross-tools prefix when invoking make, for instance if your cross-tools are named arm-linux-gnueabi-gcc, arm-linux-gnueabi-ld etc. use: