How to compile against kernel headers?
The Linux kernel has its own build system based on make
, which generates the correct gcc
options for a successful compilation of kernel components and modules.
The Kbuild
file included in external kernel modules is intended for use with that kernel build system. In addition, external kernel modules should also include a Makefile
which invokes the kernel build system. A minimal Makefile
for an external module might look like this:
obj-m = foo.o
KVERSION = $(shell uname -r)
all:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
As you can see, the main Makefile
of the kernel build system actually resides in the folder /lib/modules/$(KVERSION)/build
, where $(KVERSION)
is the version number of the kernel you're building for. If you're curious you can try to retrace what the mesh of Makefiles there does and which set of options it ends up calling gcc
with.
Related videos on Youtube
Dan
Updated on September 18, 2022Comments
-
Dan over 1 year
I'm trying to compile a 3rd-party proprietary driver module, and failing at it. I've installed the
linux-headers-5.4.0
package, but I don't know how to write a gcc command line that will successfully use it.As a minimal example, consider
test.c
, which does literally nothing but include kernel headers.#include <asm/linkage.h> #include <linux/module.h>
Because the kernel includes both of these files, and can itself be compiled, surely there must be some combination of GCC flags that will result in
test.c
compiling. The proprietary driver's.c
file includes both of these files among many others, but they're sufficient to demonstrate my problem.eyes=( -I/usr/src/linux-headers-5.4.0-21/include # for linux/module.h -I/usr/src/linux-headers-5.4.0-21/arch/x86/include # for asm/linkage.h ) gcc -c "${eyes[@]}" test.c
results in
In file included from /usr/src/linux-headers-5.4.0-21/include/linux/seqlock.h:36, from /usr/src/linux-headers-5.4.0-21/include/linux/time.h:6, from /usr/src/linux-headers-5.4.0-21/include/linux/stat.h:19, from /usr/src/linux-headers-5.4.0-21/include/linux/module.h:10, from test.c:2: /usr/src/linux-headers-5.4.0-21/include/linux/spinlock.h:60:10: fatal error: asm/mmiowb.h: No such file or directory 60 | #include <asm/mmiowb.h> | ^~~~~~~~~~~~~~
dpkg -L linux-headers-5.4.0-21 | grep mmiowb.h
shows this file ininclude/asm-generic
as well as inarch/{ia64,mips,powerpc,riscv,sh}/include/asm
. Adjusting my-I
further to include one of these and the error moves to:In file included from /usr/src/linux-headers-5.4.0-21/include/linux/mmzone.h:19, from /usr/src/linux-headers-5.4.0-21/include/linux/gfp.h:6, from /usr/src/linux-headers-5.4.0-21/include/linux/umh.h:4, from /usr/src/linux-headers-5.4.0-21/include/linux/kmod.h:9, from /usr/src/linux-headers-5.4.0-21/include/linux/module.h:13, from test.c:2: /usr/src/linux-headers-5.4.0-21/include/linux/page-flags-layout.h:6:10: fatal error: generated/bounds.h: No such file or directory 6 | #include <generated/bounds.h> | ^~~~~~~~~~~~~~~~~~~~
and this file simply does not exist on my system, but there is a file called
/usr/src/linux-headers-5.4.0-21/KBuild
which looks like a makefile that'd create it, although I cannot figure out how to invoke this makefile.How can I proceed here? Is there a command I need to run after installing
linux-headers-*
to populategenerated
folders? Is there a guide to this kind of thing online somewhere? -
Dan about 4 yearsThank you. The third-party code included a Makefile that had the
obj-m
line (but none of the rest) and manually runningmake -C /lib/modules/5.4.0-21-generic/build M=$(pwd) modules
from the shell has built a.ko
. For posterity, kbuild is documented here.