How to include local header files in linux kernel module

42,442

Solution 1

The Linux kernel makefiles use the Kbuild framework. Although these are interpreted by GNU make, Kbuild consists of a large set of macros with peculiar usage conventions, so typical makefile guidelines do not apply. The nice thing about Kbuild is that you need very little boilerplate considering the complexity of the task.

Kbuild is documented in the kernel source, in Documentation/kbuild. As a module writer, you should especially read modules.txt (and at least skim through the others).

What you're doing now isn't working because $(shell pwd) is expanded when the EXTRA_CFLAGS variable is used. Since the makefile runs from the kernel source tree rather than from your module's directory (this is one of Kbuild's many nonobvious aspects), it's picking up the wrong directory.

The official idiom for specifying include directories in an out-of-tree module is in §5.3 of modules.txt. The src variable is set to your module's toplevel directory. Therefore:

EXTRA_CFLAGS := -I$(src)/src/inc

Note that this declaration should be in a file called Kbuild at the root of your module tree. (You may want to consider the src directory to be the root of your module tree; if so, put Kbuild there and replace the value above by -I$(src)/inc). It's also possible to put them in a Makefile, but mind that this definition (as long as anything else that applies only when building a kernel module) should be within a conditional directive ifeq ($(KERNELRELEASE),). See §4.1 of modules.txt.

If you don't have a Kbuild file already and want to switch to having one, read §4.1 of modules.txt. Having a separate Kbuild file is slightly clearer. Don't put anything that applies to the kernel in your main makefile, other than a rule to call make -C $(KERNELDIR) M=$(pwd). In Kbuild, the minimum you need is the list of modules you're building (often just the one) and a list of files to include in your module, plus a dependency declaration:

EXTRA_CFLAGS := -I$(src)/inc
obj-m := mymod.o
mymod-y := $(src)/mod/mymod.o
$(src)/mod/mymod.o: $(src)/inc/mymod.h

Solution 2

Traditionally the way to #include files with paths relative to the current source code's directory is to use quotation marks rather than angle brackets:

#include <stdio.h>
#include "mygreatfunctions.h"

In this case, the first #include will reference the compiler's include search path (which, in the case of gcc, is controlled by the -I command line switch), whereas the second will look in the directory that contains the source file with the #include.

Such paths can be relative, too. So in src/mod/mymod.c, you can say:

#include "../inc/mymod.h"

and it should "just work".

I don't know if this is common practice in the Linux kernel tree, but surely it's better than mucking around with the include path, which could have any number of unintended side effects.

Share:
42,442

Related videos on Youtube

Om Narasimhan
Author by

Om Narasimhan

Updated on September 18, 2022

Comments

  • Om Narasimhan
    Om Narasimhan over 1 year

    Say I have a module mymod with source files as follows:

    src/mod/mymod.c
    src/inc/mymod.h

    I try to include mymod.h as follows

    #include <mymod.h>
    

    My makefile contains EXTRA_CFLAGS= -I$(shell pwd)/../inc/ but when the kernel is made, I get an error stating:

    mymod.h not found

    The reason seems to be that when kernel modules are made this command gets run from the makefile: (using make V1):

    make -C <path/to/linux/src> M=<path/to/mymod> modules
    

    In other works my $(shell pwd) got expanded to <path/to/linux>. This is not what I want. How can I specify the -I parameter to point to src/inc of my mymod source tree?

  • Om Narasimhan
    Om Narasimhan almost 13 years
    I could not update the post because I did not have enough reputation.
  • user
    user almost 13 years
    @Om Narasimhan: If this helped you figure out the solution, you should mark the answer as accepted.
  • vonbrand
    vonbrand over 11 years
    Sure enough, but the C compiler behaviour of looking for <foo> in some configured set of directories, and for "bar" looking first at the current directory and then falling back to the path mentioned before won't change by what bizarre means called the compiler in the first place.