Om *_*han 17 linux compiling kernel make
假设我有一个mymod包含源文件的模块,如下所示:
src/mod/mymod.c
src/inc/mymod.h
我尝试包含 mymod.h 如下
#include <mymod.h>
Run Code Online (Sandbox Code Playgroud)
我的 makefile 包含EXTRA_CFLAGS= -I$(shell pwd)/../inc/但在制作内核时,我收到一条错误消息:
未找到 mymod.h
原因似乎是在制作内核模块时,此命令从 makefile 运行:(使用makeV1):
make -C <path/to/linux/src> M=<path/to/mymod> modules
Run Code Online (Sandbox Code Playgroud)
在其他作品中,我$(shell pwd)扩展到<path/to/linux>. 这不是我想要的。如何指定-I要指向src/inc我的mymod源树的参数?
Gil*_*il' 19
Linux 内核 makefile 使用 Kbuild 框架。尽管这些是由 GNU make 解释的,但 Kbuild 由大量具有特殊使用约定的宏组成,因此典型的 makefile 指南不适用。Kbuild 的好处是,考虑到任务的复杂性,您只需要很少的样板文件。
Kbuild 记录在内核源代码中,在Documentation/kbuild. 作为模块编写者,您应该特别阅读modules.txt(并至少浏览其他部分)。
您现在所做的不起作用,因为$(shell pwd)在使用EXTRA_CFLAGS变量时会被扩展。由于 makefile 从内核源代码树运行,而不是从您的模块目录运行(这是 Kbuild 的许多不明显的方面之一),因此它选择了错误的目录。
在树外模块中指定包含目录的官方习惯用法在modules.txt. 该src变量设置为模块的顶级目录。所以:
EXTRA_CFLAGS := -I$(src)/src/inc
Run Code Online (Sandbox Code Playgroud)
请注意,此声明应位于Kbuild在模块树根部调用的文件中。(您可能希望将该src目录视为模块树的根目录;如果是这样,请将其放在Kbuild那里并将上面的值替换为-I$(src)/inc)。也可以将它们放在 a 中Makefile,但请注意,此定义(只要其他任何仅在构建内核模块时适用的内容)应该在条件指令中ifeq ($(KERNELRELEASE),)。见 §4.1 modules.txt。
如果您还没有Kbuild文件并想切换到拥有一个文件,请阅读 §4.1 of modules.txt. 有一个单独的Kbuild文件会稍微清晰一些。除了调用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
Run Code Online (Sandbox Code Playgroud)
传统上,获取具有相对于当前源代码目录的路径的文件的方法#include是使用引号而不是尖括号:
#include <stdio.h>
#include "mygreatfunctions.h"
Run Code Online (Sandbox Code Playgroud)
在这种情况下,第一个#include将引用编译器的包含搜索路径(在 gcc 的情况下,由-I命令行开关控制),而第二个将在包含带有#include.
这样的路径也可以是相对的。所以在 src/mod/mymod.c 中,你可以说:
#include "../inc/mymod.h"
Run Code Online (Sandbox Code Playgroud)
它应该“正常工作”。
我不知道这在 Linux 内核树中是否是常见做法,但肯定比乱搞包含路径要好,后者可能会产生许多意想不到的副作用。