17

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?

Caleb
  • 70,105

2 Answers2

20

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
1

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.

user
  • 28,901
  • 1
    Good advice in general, however Linux kernel makefiles are very peculiar. They call on a fairly complex set of macros called Kbuild; it's often best to treat Kbuild as a language that is almost, but not quite, entirely unlike make. – Gilles 'SO- stop being evil' Aug 05 '11 at 22:52
  • 1
    Sure enough, but the C compiler behaviour of looking for 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. – vonbrand Jan 16 '13 at 16:09