Skip to content

Best practices for kernel development with OpenEmbedded

A common question is how do you do kernel development with OpenEmbedded?  Typically, OpenEmbedded builds a kernel by checking the source out of a git repository, or by applying patch files to a released version of the kernel.  See the many recipes for examples.  This works very well for a Linux distribution build system, but is less than ideal for ongoing kernel development where you will have many iterations over a period of time. The OE work directory is considered transient, and should not be used for any ongoing development.  Fortunately, the kernel build system is self contained, so it is a very simple matter to reference the toolchain built by OpenEmbedded and work outside the OpenEmbedded build system.

Use Git

Trust me on this one, just use it!  It will make your life easier.  There is a learning curve to any powerful tool.  Another way to state this is if a tool does not do much, then it would be easy to learn.  So expect to spend a little time learning to use git.  With modern Linux kernel development, much of your time is spent integrating work that others are doing.  For example, if you are using the OMAP3 CPU, you might want to start with linux-omap branch, integrate some patches from the OE beagleboard build, merge the OMAP PM tree, and then merge some bits from the Linux-wireless tree.  This is the way embedded Linux development is done today.  Git makes it possible to have many parallel developments going at their own pace, including your own.  Even in your own development, you will find significant advantages to being able to quickly create and merge branches, revise commits, etc.  There are several articles about git on this site.

Importing an OE kernel into git

If you are starting with an existing OE kernel tree, then you typically need to set up an equivalent tree in your local git workspace.  Typically you just look at the recipe to see how to manually reconstruct it.  For example, lets consider the SRC_URI from the palm-omap1 recipe:

SRC_URI = "${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/linux-2.6.22.tar.bz2 \
           http://www.muru.com/linux/omap/patches/patch-2.6.22-omap1.bz2;patch=1 \
	   file://defconfig"

To set this kernel up in git, we might do the following:

  1. git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
  2. cd linux-2.6
  3. git checkout -b my_branch v2.6.22
  4. wget http://www.muru.com/linux/omap/patches/patch-2.6.22-omap1.bz2
  5. bzip2 -d patch-2.6.22-omap1.bz2
  6. git am patch-2.6.22-omap1

If the git am fails, then you might need to add a subject and author line to the patch in the following form and then retry git am.

From: Name <name@company.com>
Subject: omap1 patch

Now when you do a git log, you will see the above patch applied.  git apply can also be used to apply patches, but I prefer git-am as it automatically handles new files and fills in the commit message and author.

Setting up the toolchain

Now that you have a kernel, you must set up a toolchain so you can build it.  I typically set up my kernel directory next to my OE build directory in my project space, so I can then source the following script to set up the toolchain:

CROSS_COMPILER_PATH=`cd ../oe/build/angstrom-2008.1/tmp/cross/armv7a/bin; pwd`
BUILD_ARCH=`uname -m`
OE_STAGING_PATH=`cd ../oe/build/angstrom-2008.1/tmp/staging/${BUILD_ARCH}-linux/usr/bin; pwd`
STAGING_KERNEL_DIR=`cd linux-2.6; pwd`
export PATH=$PATH:$CROSS_COMPILER_PATH:$OE_STAGING_PATH
export ARCH=arm
export CROSS_COMPILE=arm-angstrom-linux-gnueabi-

Adjust to whatever you are building for.  Now you can simply type make.  The reason the OE_STAGING_PATH is added to the PATH in the above example is so that the uboot mkimage utility can be used directly from the OE build if your build target is make uImage.

Installing modules

Sometimes you need to re-install all modules on the target because you changed kernel version, etc.  Typically OE packages up all modules and adds the one you specify to the rootfs.  Because we are building the kernel outside the OE directory, OE can no longer do this.  However, its still very easy to install modules from your kernel development directory:

rm -rf modules_install; INSTALL_MOD_PATH=modules_install make modules_install
rsync -av modules_install/lib/modules/2.6.22 root@192.168.1.115:/lib/modules/

The first command installs the modules to a temporary directory, and the second command rsync’s the modules to your target system.

Creating a kernel recipe with your changes

Once you get to the point where you want to create a recipe with your changes, you can easily export a patch, or series of patches using git diff or git format-patch.  Simply add the patch files to your kernel recipe SRC_URI.  You can also teach bitbake to fetch your kernel source directly from a git repository, but I’ve generally found the patch mechanism to be adequate and easier in most cases.  As an example, you can create one large patch with all your changes that can be applied on the 2.6.22 released kernel:

git diff HEAD..v2.6.22 > my_kernel_changes.patch

Other ways …

This is just one flow and there are many variations.  There is also a new mechanism in OpenEmbedded called srctree that allows you to use OpenEmbedded in an external source tree.  srctree has the potential to further streamline this type of development.

As with any task, you want to use the tools that make sense for the task.  OpenEmbedded makes sense for building Linux distributions, but it is not a kernel development tool.  Git and the kernel build system make sense for kernel development.

2 thoughts on “Best practices for kernel development with OpenEmbedded”

Comments are closed.