Linux内核makefile使用Kbuild框架。尽管这些是由GNU make解释的,但Kbuild由大量具有特殊用法约定的宏组成,因此典型的makefile准则不适用。关于Kbuild的好处是,考虑到任务的复杂性,您几乎不需要样板。
Kbuild记录在内核源代码的Documentation/kbuild
。作为模块编写者,您应该特别阅读modules.txt
(并至少略读其他内容)。
您现在正在执行的操作无法正常工作,因为使用$(shell pwd)
该EXTRA_CFLAGS
变量时会扩展该功能。由于makefile是从内核源代码树而不是模块目录运行的(这是Kbuild的许多不明显的方面之一),因此它选择了错误的目录。
在树外模块中指定包含目录的官方惯用语在的第5.3节中modules.txt
。该src
变量设置为模块的顶级目录。因此:
EXTRA_CFLAGS := -I$(src)/src/inc
请注意,此声明应位于Kbuild
模块树根目录中的文件中。(您可能希望将src
目录视为模块树的根;如果是这样,请放在该目录中,Kbuild
并用替换上面的值-I$(src)/inc
)。也可以将它们放在中Makefile
,但是请注意,此定义(只要在构建内核模块时适用的任何其他条件)应在条件指令内ifeq ($(KERNELRELEASE),)
。参见的第4.1节modules.txt
。
如果您还没有Kbuild
文件,并且想要切换到一个文件,请阅读的§4.1 modules.txt
。拥有一个单独的Kbuild
文件会更清晰一些。除了要调用的规则外,不要在主makefile中放入任何适用于内核的内容make -C $(KERNELDIR) M=$(pwd)
。在中Kbuild
,您最少需要的是正在构建的模块列表(通常只是一个模块)和要包含在模块中的文件列表,以及一个依赖项声明:
EXTRA_CFLAGS := -I$(src)/inc
obj-m := mymod.o
mymod-y := $(src)/mod/mymod.o
$(src)/mod/mymod.o: $(src)/inc/mymod.h