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.

  -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 in include/asm-generic as well as in arch/{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 populate generated folders? Is there a guide to this kind of thing online somewhere?


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)
        make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
        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.

  • Thank you. The third-party code included a Makefile that had the obj-m line (but none of the rest) and manually running make -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. – Dan Apr 7 '20 at 21:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.