Noralf Trønnes edited this page Jul 28, 2017 · 23 revisions

There is a kernel-headers Raspbian package now:

rpi-source is helpful if you use rpi-update kernels or want to build an in-kernel module.

Pi1 and Pi2 Kernels are now supported.

rpi-source installs the kernel source used to build rpi-update kernels and the kernel on the Raspian image.
This makes it possible to build loadable kernel modules.
It is not possible to build modules that depend on missing parts that need to be built into the kernel proper (bool in Kconfig).

The script uses sudo internally when self-updating and when making the links /lib/modules/$(uname -r)/{build,source}

Note: rpi-source is supported from Linux version 3.10.37 (when Module.symvers appeared in the repo)

Examples on how to build various modules


sudo wget -O /usr/bin/rpi-source && sudo chmod +x /usr/bin/rpi-source && /usr/bin/rpi-source -q --tag-update



gcc version check

gcc version check: mismatch between gcc (4.6.3) and /proc/version (4.7.2)
Skip this check with --skip-gcc

rpi-source complains if the major.minor version of gcc differs from the one used to build the kernel.

Version used to build the kernel

$ cat /proc/version
Linux version 3.10.32+ (pi@raspi2) (gcc version 4.7.1 20120402 (prerelease) (crosstool-NG 1.15.2) ) #2 PREEMPT Fri Mar 7 01:33:27 CET 2014

Current gcc version

$ gcc --version | grep gcc
gcc (Debian 4.6.3-14+rpi1) 4.6.3

Install gcc 4.8

The latest kernels are built with gcc 4.8

Check if gcc 4.8.3 or higher is available:

sudo apt-get install gcc-4.8 g++-4.8

Note: If you don't use version 4.8.3 or higher, make prepare_modules will likely fail with this error:

#error Your compiler is too buggy; it is known to miscompile kernels

(bug filed here)

Before continuing with adding the jessie source to apt-get, read this, where the author demonstrates a nice way of prioritizing the wheezy repo over the jessie repo. People have discussed having issues after the jessie souce is added. FYI. (You can also upgrade the entire system to jessie, see this.)

To get gcc 4.8.3 or higher, add jessie (testing) source:

sudo nano /etc/apt/sources.list.d/jessie.list

Add this line:

deb jessie main contrib non-free rpi

Fetch package lists:

sudo apt-get update

Install 4.8

sudo apt-get install -y gcc-4.8 g++-4.8

# Package configuration
# Configuring libc6:armhf
# Restart services during package upgrades without asking?
# <Yes>

Setup gcc versions

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.6 20
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 50
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.6 20
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 50

Current gcc version

$ gcc --version
gcc (Raspbian 4.8.3-5) 4.8.3

gcc version can be changed with:

sudo update-alternatives --config gcc

Slightly different method:

Install gcc 4.7

Older kernels are built with 4.7

Install 4.7

$ sudo apt-get install gcc-4.7 g++-4.7

$ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.6 60 --slave /usr/bin/g++ g++ /usr/bin/g++-4.6
$ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.7 40 --slave /usr/bin/g++ g++ /usr/bin/g++-4.7

Choose 4.7

$ sudo update-alternatives --config gcc
There are 2 choices for the alternative gcc (providing /usr/bin/gcc).

  Selection    Path              Priority   Status
* 0            /usr/bin/gcc-4.6   60        auto mode
  1            /usr/bin/gcc-4.6   60        manual mode
  2            /usr/bin/gcc-4.7   40        manual mode

Press enter to keep the current choice[*], or type selection number: 2
update-alternatives: using /usr/bin/gcc-4.7 to provide /usr/bin/gcc (gcc) in manual mode

Current gcc version

$ gcc --version | grep gcc
gcc (Debian 4.7.2-5+rpi1) 4.7.2



This library is needed when running 'make menuconfig'

 *** ncurses-devel is NOT installed. Needed by 'make menuconfig'. On Debian: apt-get install ncurses-dev

Install prerequisites

$ sudo apt-get install libncurses5-dev


make prepare

Always run 'make prepare' after changing the kernel config

Show kernel config diff between current and previous config

$ scripts/diffconfig
 ENC28J60 n -> m

Show config diff against the running kernel

$ cd linux
$ zcat /proc/config.gz > .config.running
$ scripts/diffconfig .config.running .config


Module.symvers contains all the symbols the kernel and modules has exported, and was made during the kernel build process. This file is used later to find needed symbols when building modules. If it was missing (or empty) during building of a module, you might get a not very helpful error message when loading the module. But dmesg will help:

$ sudo modprobe elo
ERROR: could not insert 'elo': Exec format error
$ dmesg |tail -n 1
[19988.002342] elo: no symbol version for module_layout

But if we build a module that exports a symbol, and another module we build needs that symbol, we get warnings.
The build system can't find that symbol in ~/linux/Module.symvers.
We need to tell the build system where this symbol is. This can be done with KBUILD_EXTRA_SYMBOLS pointing to the needed Module.symvers in the build directory of the exporting module.
See mcp2515a for an example.

I had a situation after building several modules that loading the module failed with some format error. It turned out that ~/linux/Module.symvers had changed somehow.
If that happens, there is a backup file Module.symvers.backup. The timestamps will differ if it has changed.

Kernel taint

The kernel can be tainted in various ways. One of them is loading an out-of-tree module.

$ cat /proc/sys/kernel/tainted


4096 - An out-of-tree module has been loaded.
Clone this wiki locally
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.