假设我有一个包含源文件的模块,mymod
如下所示:
src/mod/mymod.c
src/inc/mymod.h
我尝试包含 mymod.h 如下
#include <mymod.h>
我的 makefile 包含EXTRA_CFLAGS= -I$(shell pwd)/../inc/
但当内核制作时,我收到一条错误消息:
找不到 mymod.h
原因似乎是当创建内核模块时,此命令从 makefile 运行:(使用make
V1):
make -C <path/to/linux/src> M=<path/to/mymod> modules
在其他作品中,我的内容$(shell pwd)
扩展到了<path/to/linux>
.这不是我想要的。如何指定-I
指向源树src/inc
的参数mymod
?
答案1
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
)。也可以将它们放在 a 中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
答案2
#include
传统上,获取具有相对于当前源代码目录的路径的文件的方法是使用引号而不是尖括号:
#include <stdio.h>
#include "mygreatfunctions.h"
在这种情况下,第一个#include
将引用编译器的包含搜索路径(在 gcc 的情况下,由-I
命令行开关控制),而第二个将在包含带有#include
.
这样的路径也可以是相对的。所以在 src/mod/mymod.c 中,你可以说:
#include "../inc/mymod.h"
它应该“正常工作”。
我不知道这在 Linux 内核树中是否是常见做法,但肯定比乱搞包含路径要好,后者可能会产生许多意想不到的副作用。