NOTE: This page is obsolete

Please use the Ubuntu Kernel CI Scripts as a reference

Package Your Own Kernel

You want a packaged verson of some random kernel but you have no clue how to go about it. You could ask jcrigby to do it for you but then you would have to ask him again next time you need another one.

You could read the Ubuntu Kernel team pages on the subject but chances are that when you are done you still won't have any idea how to package your kernel.

So give up now on understanding how to do this and just follow the instructions below and you will soon have a packaged kernel. Once you have done it a few times things will start to make sense and then going back and reading the Ubuntu Kernel team pages will make a lot more sense.

These instructions are short on why the steps work but if you follow them they should work. If they don't work please complain via email to or via irc to jcrigby on #linaro on (Freenode).

Preparing the Source

Ok, imagine that you want to have a kernel package that is based on an upstream vanilla Linus v2.6.39 and you want to build for the TI OMAP3 SOC flavour.

Preparing Your Kernel Source

Step 1) Do a git clone or git remote add or whatever to get a local copy of v2.6.39. (This is not a git tutorial so if the git stuff does not make sense to you then you have some homework to do. But you can just follow the steps for now.)

git remote add linus git://
git remote update
git checkout -b my-2.6.39-omap3-packaged-kernel v2.6.39

Get the Linaro Packaging Bits

Step 2) Add another remote pointing to a branch that has nothing in it but the generic package files for packaging a Ubuntu style Linaro kernel tree. Then cherry-pick it into your tree.

git remote add null-packaging git://
git remote update
git cherry-pick linaro-packaging

You should now have two directories you did not have before. These two new directories are debian and debian.linaro.

Modify the Linaro Packaging Bits For Your Platform

Step 3) You need to modify the debian.linaro directory to set it up for your vendor, flavour and release. However, before doing that you need to set up some variables that you will be using more than once.

Step 3.1) Set the KERNELVERSION variable. (This is easy because there is a target for it in the kernel Makefile.)

export KERNELVERSION=$(make EXTRAVERSION='' kernelversion) 

Step 3.2) Now you need a FLAVOUR name. A good choice is the same name used in arch/arm/mach-xxx. Hint: OMAP is special since multiple generations of omap use arch/arm/mach-omap2. Just pick omap3 or omap would also work.

export FLAVOUR=omap3

Step 3.3) You will also need an upper case definition of flavour.

export UCFLAVOUR=$(echo $FLAVOUR | tr '[:lower:]' '[:upper:]')

Step 3.4) And finally a VENDOR definition.

export VENDOR=TI

With these definitions, you can begin munging the generic packaging directory contents for your flavour.

The files in the debian.linaro subtree contain three patterns that need to be changed to represent your flavour and vendor combination. These patterns are %FLAVOUR%, %UCFLAVOUR% and %VENDOR%.

Step 3.5) Executing these commands will find all the files with these patterns and substitute the appropriate values.

cd debian.linaro
for f in $(git grep -l %FLAVOUR%); do sed -i s/%FLAVOUR%/$FLAVOUR/g $f; done
for f in $(git grep -l %UCFLAVOUR%); do sed -i s/%UCFLAVOUR%/$UCFLAVOUR/g $f; done
for f in $(git grep -l %VENDOR%); do sed -i s/%VENDOR%/$VENDOR/g $f; done
cd ..

Kernel Configuration

Step 4) Now you need a config file for your flavour. This is really just a stub that will be replaced with proper config file later.

Step 4.1) The prototype stub config file has %FLAVOUR% in the name, not just the content, so it needs to be moved.

git mv debian.linaro/config/armel/config.flavour.%FLAVOUR% \

Step 4.2) There is one other file that has flavour in the name. Rename it and change the TBD portion of the line "target="Targeted towards boards such as TBD"" to something more descriptive (e.g. Snowball or Panda etc).

git mv debian.linaro/control.d/vars.%FLAVOUR% \

Step 4.3) The kernel build system keeps track of the exported symbols and built modules. The combination is called the abi and when it changes the abi number must be incremented. However, for the first build you need to ignore this checking by creating a couple of "ignore files".

mkdir -p debian.linaro/abi/$KERNELVERSION-0.0/armel/
echo 1 > debian.linaro/abi/$KERNELVERSION-0.0/armel/$FLAVOUR.ignore.modules
echo 1 > debian.linaro/abi/$KERNELVERSION-0.0/armel/$FLAVOUR.ignore
git add debian.linaro/abi/$KERNELVERSION-0.0/armel/

Debian.Linaro Changelog

Step 5) Now create a debian changelog file. This file is in the debian.linaro directory and not debian. Use the dch command to create the file and then invoke your editor so you can tweek it.

Step 5.1) The dch command relies on you having the following debian magical variables in your env:

export DEBEMAIL=''
export DEBFULLNAME='First Last'

dch --create --changelog debian.linaro/changelog --package linux-$FLAVOUR -v ${KERNELVERSION}-1000.0
git add debian.linaro/changelog

Step 5.2) Commit all these changes in case you mess something up and have to start over.

git commit -a -s -m "LINARO: initial debian.linaro dir for $VENDOR $FLAVOUR"

Debian Rules

Step 6.1) You are now ready to start using targets in the debian/rules file. You will always invoke debian/rules using fakeroot so make an alias to avoid some typing.

alias fdr='fakeroot ./debian/rules'

Step 6.2) You need to execute the clean target in debian/rules to be able to run some other useful targets. This is how debian/changelog and debian/control files get setup.

fdr clean

Update Your Kernel Config

The last thing you need in debian.linaro is a proper kernel config.

Step 7) For this example start with the omap3 defconfig in the kernel tree. (Hint: just type return to fill in all the defaults. )

cp arch/arm/configs/omap2plus_defconfig debian.linaro/config/armel/config.flavour.$FLAVOUR 
fdr updateconfigs

The build system has a config checker for enforcing certain required Ubuntu kernel options. The first time you create a new configure you are likely to get a lot of errors from the enforcer. (You will fix those in the next steps.)

Running config-check for all configurations ...

check-config: /tmp/tmp.io6ImEbcoM/CONFIGS/armel-config.flavour.omap3: loading config
check-config: /home/jcrigby/work/git-trees/linux-linaro/linux-linaro/debian.linaro/config/enforce: loading checks
check-config: FAIL: value CONFIG_COMPAT_BRK n
check-config: FAIL: value CONFIG_DEVKMEM n
check-config: FAIL: value CONFIG_LSM_MMAP_MIN_ADDR 0
check-config: FAIL: value CONFIG_SECURITY_SELINUX y
check-config: FAIL: value CONFIG_SECURITY_SMACK y
check-config: FAIL: value CONFIG_SECURITY_YAMA y
check-config: FAIL: value CONFIG_SYN_COOKIES y
check-config: FAIL: (( arch armel | arch sparc ) & value CONFIG_DEFAULT_MMAP_MIN_ADDR 32768 ) |         ( value CONFIG_DEFAULT_MMAP_MIN_ADDR 65536)
check-config: FAIL: value CONFIG_USB_DEVICEFS n
check-config: FAIL: value CONFIG_DEVTMPFS y
check-config: FAIL: value CONFIG_DEVTMPFS_MOUNT y
check-config: FAIL: value CONFIG_TMPFS_POSIX_ACL y
check-config: FAIL: value CONFIG_BLK_DEV_RAM_SIZE 65536
check-config: FAIL: value CONFIG_BLK_DEV_DM y
check-config: FAIL: value CONFIG_LOCALVERSION_AUTO n
check-config: 10/27 checks passed -- exit 1

*** ERROR: 1 config-check failures detected

Fix-up Your Kernel Config

Step 8) You can now use the editconfigs target to fix up your config.

fdr editconfigs

Step 8.1(optional)) You can also edit ./debian.linaro/config/armel/config.flavour.$FLAVOUR directly.

gvim ./debian.linaro/config/armel/config.flavour.$FLAVOUR

Bypass Remaining Config Errors

Step 9) After a few iterations of editconfigs and updateconfigs you will be able to get the number of failures down, but you will not be able to satisfy all the checks because your tree is missing some Ubuntu patches.

Step 9.1) Bypass these last few failures by turning off the check in debian.linaro/config/enforce.

gvim debian.linaro/config/enforce

Step 9.2) Run updateconfigs one last time to make sure there are no errors.

fdr updateconfigs

Commit Config Changes

Step 10) Check in the config and the modified enforce files.

git add debian.linaro/config
git commit -s -m 'LINARO: CONFIG: Initial kernel config and modified enforce file'

Building Your Kernel Package

Step 11) Now that you have a good kernel config you can try to actually build the kernel. The first few kernel builds are not likely to succeed. So if you install and setup ccache, the later build attempts will go much faster.

Step 11.1 (Optional)) Edit the kernel Makefile and change the CC and HOSTCC settings:

--- Makefile    2010-09-08 18:04:12.077361168 -0600
+++ foo 2010-09-08 18:04:01.347099435 -0600
@@ -225,8 +225,8 @@
          else if [ -x /bin/bash ]; then echo /bin/bash; \
          else echo sh; fi ; fi)
-HOSTCC       = gcc
-HOSTCXX      = g++
+HOSTCC       = ccache gcc
+HOSTCXX      = ccache g++
 HOSTCFLAGS   = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer
@@ -312,7 +312,7 @@
 AS             = $(CROSS_COMPILE)as
 LD             = $(CROSS_COMPILE)ld
-CC             = $(CROSS_COMPILE)gcc
+CC             = ccache $(CROSS_COMPILE)gcc
 CPP            = $(CC) -E
 AR             = $(CROSS_COMPILE)ar
 NM             = $(CROSS_COMPILE)nm

Step 11.2) Now actually build a kernel. Where YOURGPGKEY is your gpg public key. You can list your gpg keys with gpg --list-keys. The -k argument in the debuild command just takes the part after the /, not the whole key 1024D/.

gpg --list-keys
pub   1024D/YOURGPGKEY 2010-04-19

debuild  -eCROSS_COMPILE=arm-linux-gnueabi- -kYOURGPGKEY -b -aarmel 

Step 11.3 (Optional)) If you are looking for more information about GPG keys, go to

Quieting kernel-wedge Errors

Just when you think the build is going to finish, some command called kernel-wedge will start complaining.

find: `debian/nic-modules-2.6.39-1000-omap3-di': No such file or directory
nic-modules-2.6.39-1000-omap3-di will be empty
find: `debian/nic-shared-modules-2.6.39-1000-omap3-di': No such file or directory
nic-shared-modules-2.6.39-1000-omap3-di will be empty
find: `debian/ppp-modules-2.6.39-1000-omap3-di': No such file or directory
ppp-modules-2.6.39-1000-omap3-di will be empty
find: `debian/scsi-modules-2.6.39-1000-omap3-di': No such file or directory

There are two ways to fix this.

Step 12.1 (Optional)) The "right way" is to exclude certain modules, in this case it's the nic-modules module.

echo nic-modules > debian.linaro/d-i/exclude-modules.armel-linaro-$FLAVOUR 

Step 12.2) However, since there are bajillion missing modules just hack the script that runs kernel-wedge (debian/rules.d/

          kernel-wedge install-files && \
-         kernel-wedge check
+         kernel-wedge check || \
+         true

Step 12.3) And check the hack in.

git commit debian/rules.d/ -s -m 'LINARO: HACK to ignore kernel-wedge errors'

Step 12.4) Now the build should actually complete without errors.

debuild  -eCROSS_COMPILE=arm-linux-gnueabi-   -kYOURGPGKEY    -b -aarmel 

Build a Source Package

Step 13) Once it works then edit debian.linaro/changelog to reflect that this is a release check it in and then build a source package for uploading to a ppa.

Step 13.1) First make sure you don't have any cruft lying around that will sneek into the source package.

git reset --hard HEAD
git clean -d -f -x 

Step 13.2) Then run debuild -S to build the source package.

fdr clean
debuild   -kYOURGPGKEY    -S -i -I 

Hint1: Don't forget the -i -I or you will end up with extra cruft like your entire .git subtree in your source package.

Hint2: You will see some complaints about no original source tar archive but you can ignore that for now

Step 13.3) You should see the following four files in the root directory.

cd ..


Upload to the PPA

Step 14) Upload to the ppa with dput.

dput ppa:ppaname *.changes

Hint: Make sure this is a de-virtualized ppa otherwise the armel build will fail.

Create a Meta Package

Step 15) Now you need a kernel meta package. The meta package requires the latest image and header packages.

Step 15.1) An easy way to create a meta package is just clone the linux-meta-linaro package and modify it.

git clone git://
# remove all platforms but the one you care about
git rm meta-source/debian/control.d/mx51
git rm meta-source/debian/control.d/u8500
git rm meta-source/debian/control.d/s5pv310
git rm meta-source/debian/control.d/vexpress

Step 15.2) Now change the meta-source/debian/changelog and meta-source/debian/control.common files. We are starting with an omap version so all we need to change is the linaro to linaro-lt to show that this meta package is for a landing team kernel.

$ git diff HEAD^
diff --git a/meta-source/debian/changelog b/meta-source/debian/changelog
index 54dee89..ad3d04f 100644
--- a/meta-source/debian/changelog
+++ b/meta-source/debian/changelog
@@ -1,3 +1,9 @@
+linux-meta-linaro-lt ( natty; urgency=low
+  * Linaro LT Natty ABI 1000 (2.6.39-1000.0) 
+ -- John Rigby <>  Fri, 25 Mar 2011 09:38:14 -0600
 linux-meta-linaro ( natty; urgency=low
   * Linaro Natty ABI 1001 (2.6.39-1001.2)
diff --git a/meta-source/debian/control.common b/meta-source/debian/control.common
index 9ab41f5..8050536 100644
--- a/meta-source/debian/control.common
+++ b/meta-source/debian/control.common
@@ -1,4 +1,4 @@
-Source: linux-meta-linaro
+Source: linux-meta-linaro-lt
 Section: devel
 Priority: optional
 Maintainer: Ubuntu Kernel Team <>
diff --git a/meta-source/debian/control.d/omap b/meta-source/debian/control.d/omap
index eb55a4c..7ca2a93 100644
--- a/meta-source/debian/control.d/omap
+++ b/meta-source/debian/control.d/omap
@@ -1,17 +1,17 @@
-Package: linux-headers-linaro-omap
+Package: linux-headers-linaro-lt-omap
 Architecture: armel
 Section: devel
 Priority: optional
-Depends: ${misc:Depends}, linux-headers-${kernel-abi-version}-linaro-omap 
+Depends: ${misc:Depends}, linux-headers-${kernel-abi-version}-linaro-lt-omap 
 Description: Linux kernel headers for the TI omap architecture.
  This package will always depend on the latest kernel headers available
  for TI omap based systems.
-Package: linux-image-linaro-omap
+Package: linux-image-linaro-lt-omap
 Architecture: armel
 Section: metapackages
 Priority: optional
-Depends: ${misc:Depends}, linux-image-${kernel-abi-version}-linaro-omap, linux-firmware
+Depends: ${misc:Depends}, linux-image-${kernel-abi-version}-linaro-lt-omap, linux-firmware
 Description: Linux kernel image for the TI omap architecture.
  This package will always depend on the latest kernel image available
  for TI omap systems.

Step 15.3) Making the meta source package is as easy as typing make source.

$ make source
cd meta-source && fakeroot debian/rules clean
make[1]: Entering directory `/home/jcrigby/work/git-trees/linux-meta-linaro/linux-meta-linaro/meta-source'
rm -f debian/control.tmp
for i in debian/control.common debian/control.d/omap; do \
                sed 's/RELEASE_NAME/maverick/g' $i >> debian/control.tmp; \
                echo >> debian/control.tmp; \


You need a passphrase to unlock the secret key for
user: "John Rigby <>"
1024-bit DSA key, ID B4ECD88A, created 2010-04-19

 dpkg-genchanges -S -sa >../linux-meta-lt_2.6.39.1000.0_source.changes
dpkg-genchanges: warning: the current version ( is earlier than the previous one (
dpkg-genchanges: including full source code in upload
 signfile linux-meta-lt_2.6.39.1000.0_source.changes

You need a passphrase to unlock the secret key for
user: "John Rigby <>"
1024-bit DSA key, ID B4ECD88A, created 2010-04-19

 dpkg-source -I -i --after-build meta-source
dpkg-buildpackage: source only upload: Debian-native package

Hint: If you get an error about your gpg key being skipped it probably means there is a mismatch between the ids in the key and in the changelog. Thanks to james_w for pointing out this page: Search for DEBSIGN_KEYID.


Angus Ainslie pointed out a common error. The kernel version (the part after the last -) in debian.linaro/changelog must be of the form major.minor. The build system actually treats these as ABINUM.UPLOADNUM. Kernel modules compiled against a certain ABINUM should continue to work with a new kernel as long as ABINUM is does not change. The UPLOADNUM gets incremented with each new kernel upload. When the packaging system is looking for the latest kernel it will choose the largest ABINUM.UPLOADNUM.

This is ok:

linux-linaro-fred (2.6.38-1007.10) natty; urgency=low

This is NOT ok:

linux-linaro-fred (2.6.38-1007.10.rc9) natty; urgency=low


Resources/HowTo/PackageYourOwnKernel (last modified 2015-03-30 20:06:39)