Development With Ubuntu

Here is a collection of tips which can be useful for people developing root filesystems or applications with Ubuntu.

Boot Ubuntu desktop / netbook on NFS
At least if you boot your root filesystem directly (without going through a standard Ubuntu initramfs), you probably noticed:
 * that you can boot a minimal or server Ubuntu rootfs through NFS
 * that you cannot boot a desktop type of Ubuntu rootfs (Ubuntu Desktop, Ubuntu Desktop Edition...)

The system hangs during the boot sequence. It's because of  that reinitializes the network interface that you used for NFS.

A quick workaround is just to disable, for example by renaming the corresponding upstart configuration file:

sudo mv /etc/init/network-manager.conf /etc/init/network-manager.conf.disabled

Of course, this is shouldn't be done in a user environment, because users will need  (to connect to their wired and wireless networks). However, this can make your life easier if you are involved in product test or development.

Extract the contents of a uInitrd file
This can be useful to study boot scripts and analyze the early boot process in Ubuntu:

First, remove the U-boot header:

dd if=uInitrd of=initrd skip=64 bs=1

The initrd is a compressed cpio archive. Let's extract this archive...

On Maverick and beyond, it is compressed with lzma:

lzcat initrd | cpio -id

On Lucid and earlier versions, it is compressed with gzip

zcat initrd | cpio -id

Note: the U-boot header added to the initrd file is currently 64 bytes. This could change, and this can be different in other U-boot files. Here's a tip to find the actually U-boot header size. You can find the original image size with:

> mkimage -l uInitrd Image Name:  Ubuntu Initrd Created:     Wed Oct  6 05:09:47 2010 Image Type:  ARM Linux RAMDisk Image (gzip compressed) Data Size:   5978226 Bytes = 5838.11 kB = 5.70 MB Load Address: 0x00000000 Entry Point: 0x00000000

The header size is the uInitrd file size minus the data size listed by mkimage.

Modify an existing uInitrd file
First, extract the contents of the uInitrd file to an initrd directory by following the above instructions.

Then, run the following commands:

cd initrd <make changes: for example by adding "set -x" in some scripts to debug them> find. | cpio -H newc -o | lzma -c > ../initrdnew.lzma cd .. mkimage -A arm -O linux -T ramdisk -C none -a 0 -e 0 -n initramfs -d ./initrdnew.lzma ./uInitrdnew

Replace lzma</tt> by gzip</tt> if your initramdisk was initially compressed with gzip</tt> (in Ubuntu Lucid and earlier versions, for example).

Note that the newc</tt> format for cpio</tt> is mandatory. If you don't use it, Linux won't be able to extract this archive.

Use ccache</tt> for your builds
Using ccache</tt> during your builds on Ubuntu is simple; just install ccache</tt> on your machine:

$ sudo apt-get install ccache

...and add it first to your $PATH</tt>:

$ export PATH="/usr/lib/ccache:$PATH"

OR alternatively, if you want to use ccache for all compilations, you can softlink the desired binaries:

$ sudo cp ccache /usr/local/bin/ $ sudo ln -s /usr/local/bin/ccache /usr/local/bin/gcc $ sudo ln -s /usr/local/bin/ccache /usr/local/bin/g++ $ sudo ln -s /usr/local/bin/ccache /usr/local/bin/cc $ sudo ln -s /usr/local/bin/ccache /usr/local/bin/arm-none-linux-gnueabi-gcc $ sudo ln -s /usr/local/bin/ccache /usr/local/bin/arm-none-linux-gnueabi-g++ $ sudo ln -s /usr/local/bin/ccache /usr/local/bin/arm-none-linux-gnueabi-cc

This will  work as long as /usr/local/bin comes before the path to gcc (which is usually in /usr/bin). After installing you may wish  to  run "which gcc" to make sure that the correct link is being used.

Create a cross chroot environment
There are many wikis/blogs about this already, but I often find it cumbersome to get the exact instructions that work... and since I am using that often I am putting my own instructions here. At least I won't need to search them anymore, and at best it will be useful for others.

So basically here the purpose is to create an ARM root FS and be able to 'start' it from a desktop/laptop (x86) using QEMU user emulation. Clearly reading the following links will provide information about what this is all about:
 * http://wiki.debian.org/EmDebian/CrossDebootstrap
 * https://help.ubuntu.com/community/DebootstrapChroot
 * http://wiki.debian.org/QemuUserEmulation

So here are the exact instructions that worked like a charm for me.

First install the required packages:

sudo apt-get install debootstrap schroot binfmt-support qemu qemu-user-static

then create the 'foreign' root fs with:

sudo debootstrap --arch armel --variant buildd --foreign oneiric /var/chroot/oneiric_armel or if you prefer to go with armhf... sudo debootstrap --arch armhf --variant buildd --foreign precise /var/chroot/precise_armhf

This will take a few minutes, it will download all the .deb files that need to be install and unpack them.

Now, we need to finalize the packages installation in the target root FS.

First, copy the QEMU binary in the chroot (this is what will make sure that you can run an ARM executable on your desktop using emulation):

sudo cp /usr/bin/qemu-arm-static / /usr/bin/

Now you can enter your chroot and run the 'second stage deboostrap' that will finalize the packages installation and configuration.

sudo chroot / / /debootstrap/debootstrap --second-stage exit

Now you need to create a valide 'sources.list' file in your chroot / /etc/apt/sources.list and add something like this (customize it as you want, and make sure that you use the right ubuntu release name) deb http://ports.ubuntu.com/ oneiric main restricted universe multiverse deb-src http://fr.archive.ubuntu.com/ubuntu/ oneiric main restricted universe multiverse

Now you are all set! You can chroot in your ARM root FS and install packages, or do anything you want (like doing 'native' compilation). To enter the chroot, just run: sudo chroot / / apt-get update apt-get install

As you will notice you would be identfied as 'root', that can be fine most of the time. However if you plan to use the chroot as a 'working' environment, you might prefer to create standard users. You can do it with 'adduser' command and manage users/groups in the chroot as if you were on a 'different' computer. But there is a better mechanism...based on 'schroot'. You can read http://www.debian-administration.org/articles/566 to get more information, but basically it allows to seemlessly chroot using privileges from the current computer. And as a convenience, 'schroot' will also mount your regular '$HOME' folder so that you get all your 'stuff', including things like SSH or PGP keys...

In order to use schroot, you need to create a configuration file, e.g. sudo /etc/schroot/chroot.d/arm.conf   # it can be any file with .conf extension and add something like that [ ] description=Ubuntu ARM chroot directory=/ / root-users= type=directory users=

What this does is:
 * allow to log as 'root' in the chroot
 * allow to log as in the chroot, and it would mount your $HOME as well.

So now to log as 'root' you can run: schroot -c -u root And to log as standard user, you can run: schroot -c -u

Using you should find this very convenient to build/develop from your PC as if you were on a real ARM device!

Other notes for developers

 * Building your own apps with CMake and making a Debian package
 * Add packages to Ubuntu pre-installed images