Reputation: 475
I'm trying to build Linux kernel module:
KBUILD_EXTRA_SYMBOLS := ../../Module.symvers
KBUILD_EXTRA_SYMBOLS := ../../dir0/Module.symvers
KDIR = ../../../../kernel/linux-4.9
INCLUDES = \
-I../dir1/dir2/dir3 \
-I../dir1/dir2 \
-I../dir1
EXTRA_CFLAGS += $(INCLUDES)
PWD = $(shell pwd)
TARGET = some_module
obj-m := $(TARGET).o
all: default clean
default:
make $(INCLUDES) -C $(KDIR) M=$(PWD) modules
clean:
@rm -f *.o .*.cmd .*.flags *.mod.c *.order
@rm -f .*.*.cmd *.symvers *~ *.*~ TODO.*
@rm -fR .tmp*
@rm -rf .tmp_versions
disclean: clean
@rm -f *.ko
But it can't locate files in relative paths e.g. like fatal error: some_header.h: No such file or directory
. When I use absolute paths it works well, but I need to do relative addressing from current directory in this project. What's wrong?
Sorry if obvious.
Upvotes: 4
Views: 1768
Reputation: 4411
The Linux kernel uses Kbuild to make modules. This framework differs from normal makefile conventions, so while they are both interpreted by GNU make, one needs to be aware of the differences. Documentation for Makefiles using Kbuild can be found here and documentation for building external kernel modules can be found here.
A few important points, relevant to your problem, from the documentation are quoted below.
From makefiles.txt
:
--- 3.10 Special Rules
Special rules are used when the kbuild infrastructure does not provide the required support. A typical example is header files generated during the build process. Another example are the architecture-specific Makefiles which need special rules to prepare boot images etc. Special rules are written as normal Make rules. Kbuild is not executing in the directory where the Makefile is located, so all special rules shall provide a relative path to prerequisite files and target files. Two variables are used when defining special rules:
~
$(src)
~
$(src)
is a relative path which points to the directory where the Makefile is located. Always use$(src)
when referring to files located in thesrc
tree.~
$(obj)
~
$(obj)
is a relative path which points to the directory where the target is saved. Always use$(obj)
when referring to generated files.
From modules.txt
:
--- 4.3 Several Subdirectories
kbuild can handle files that are spread over several directories. Consider the following example:
. |__ src | |__ complex_main.c | |__ hal | |__ hardwareif.c | |__ include | |__ hardwareif.h |__ include |__ complex.h
To build the module complex.ko, we then need the following kbuild file:
--> filename: Kbuild obj-m := complex.o complex-y := src/complex_main.o complex-y += src/hal/hardwareif.o ccflags-y := -I$(src)/include ccflags-y += -I$(src)/src/hal/include
As you can see, kbuild knows how to handle object files located in other directories. The trick is to specify the directory relative to the kbuild file's location. That being said, this is NOT recommended practice.
For the header files, kbuild must be explicitly told where to look. When kbuild executes, the current directory is always the root of the kernel tree (the argument to "-C") and therefore an absolute path is needed.
$(src)
provides the absolute path by pointing to the directory where the currently executing kbuild file is located.
Thus, your Makefile should look like the following:
KBUILD_EXTRA_SYMBOLS := $(src)/../../Module.symvers
KBUILD_EXTRA_SYMBOLS := $(src)/../../dir0/Module.symvers
KDIR = $(src)/../../../../kernel/linux-4.9
INCLUDES = \
-I$(src)/../dir1/dir2/dir3 \
-I$(src)/../dir1/dir2 \
-I$(src)/../dir1
EXTRA_CFLAGS += $(INCLUDES)
PWD = $(shell pwd)
TARGET = some_module
obj-m := $(TARGET).o
all: default clean
default:
make $(INCLUDES) -C $(KDIR) M=$(PWD) modules
clean:
@rm -f *.o .*.cmd .*.flags *.mod.c *.order
@rm -f .*.*.cmd *.symvers *~ *.*~ TODO.*
@rm -fR .tmp*
@rm -rf .tmp_versions
disclean: clean
@rm -f *.ko
Upvotes: 3