我正在尝试构建Linux内核模块:
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
但是它无法在相对路径中找到文件,例如像fatal error: some_header.h: No such file or directory
。当我使用绝对路径时,它可以很好地工作,但是我需要从该项目中的当前目录进行相对寻址。怎么了?
抱歉,很明显。
答案 0 :(得分:2)
Linux内核使用Kbuild来制作模块。该框架不同于常规的makefile约定,因此尽管它们都由GNU make解释,但需要注意它们之间的差异。 Documentation for Makefiles using Kbuild can be found here和documentation for building external kernel modules can be found here。
以下引用了文档中与您的问题相关的一些重要要点。
来自makefiles.txt
:
--- 3.10特殊规则
当kbuild基础结构未提供所需支持时,将使用特殊规则。一个典型的例子是头文件 在构建过程中生成。另一个例子是 需要特定规则准备的特定于体系结构的Makefile 引导映像等。特殊规则写为正常的Make规则。 Kbuild未在Makefile所在的目录中执行,因此所有 特殊规则应提供前提文件的相对路径 和目标文件。定义特殊规则时使用两个变量:
〜{
$(src)
〜
$(src)
是指向Makefile所在目录的相对路径。引用位于$(src)
树中的文件时,请始终使用src
。〜{
$(obj)
〜
$(obj)
是一个相对路径,指向目标保存目录。引用生成的文件时,请始终使用$(obj)
。
来自modules.txt
:
--- 4.3几个子目录
kbuild可以处理分布在多个目录中的文件。 考虑以下示例:
. |__ src | |__ complex_main.c | |__ hal | |__ hardwareif.c | |__ include | |__ hardwareif.h |__ include |__ complex.h
要构建模块complex.ko,我们需要以下kbuild 文件:
--> 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
如您所见,kbuild知道如何处理位于 其他目录。技巧是指定相对于的目录 kbuild文件的位置。话虽如此,不建议这样做 练习。
对于头文件,必须明确告知kbuild在哪里查找。 执行kbuild时,当前目录始终是 内核树(“ -C”的参数),因此绝对路径为 需要。
$(src)
通过指向 当前执行的kbuild文件所在的目录。
因此,您的Makefile应该如下所示:
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