无法在内核模块 makefile 中使用通配符

Posted

技术标签:

【中文标题】无法在内核模块 makefile 中使用通配符【英文标题】:Cannot use wildcard in kernel module makefile 【发布时间】:2021-01-26 05:13:07 【问题描述】:

我对 Makefile 和内核模块非常熟悉,但最近我在 Makefile 中遇到了一个没有任何意义的问题——关于使用通配符。 为了证明这一点,我从头开始编译一个 hello world 内核模块。 目录结构是这样的:

hello_mod/
   | 
   --- hello.c
   |
   --- Makefile

这是实际的生成文件:

CFILES := $(wildcard hello.c*)
#CFILES := hello.c
OBJS := $(CFILES:.c=.o)

KSRC := /lib/modules/$(shell uname -r)/build

obj-m += hello_world.o
hello_world-y := $(OBJS)

all:    
        @echo $(CFILES)
        $(MAKE) -C $(KSRC) M=$$PWD modules

clean:
        $(MAKE) -C $(KSRC) M=$$PWD clean

.PHONY: clean

问题在于,即使注释的 $(CFILES) 和未注释的 $(CFILES) 完全相同,使用第一个 $(CFILES) 构建失败并出现以下错误:

*** No rule to make target `/home/test/hello_mod/hello_world.c', needed by
/home/test/hello_mod/hello_world.o'.  Stop.

如果使用注释的 $(CFILES) ,它可以完美地工作。

如果有人想对此进行测试,我将包含 hello world 的源代码,即 hello.c:

#include <linux/kernel.h>
#include <linux/module.h>

static int mod_init()

        printk("Hello\n");
        return 0;


static void mod_exit()

        printk("Bye world\n");    


module_init(mod_init);
module_exit(mod_exit);

有谁知道它为什么会这样?而且我需要在makefile中使用通配符。任何帮助将不胜感激。

【问题讨论】:

你可能想看到这个答案***.com/questions/6577176/makefiles-and-wildcards 这个问题与我无关,他/她在规则中使用“*”。我正在使用通配符运算符将源列出到变量中。 为什么在CFILES 定义中使用$(dir)?您是否使用remake -x 调试您的Makefile $(dir)foreach 的一部分。我认为没有其他方法可以做到这一点。 remake -x 并没有真正给我任何有用的东西,它一直在指出没有这样的规则。 wildcard函数恰好被执行时,你确定当前目录是正确的吗?最好使用绝对路径。 【参考方案1】:

这里发生了两种情况。第一个实际上只依赖于 KSRC 变量和递归调用。第二个 make 只需要 CFILESOBJSobj-mhello_world-y 变量,并且不使用 all: 目标。因此,您的调试显示 CFILES 为第一个 Make 设置正确,它没有被使用,并且没有在第二个 Make 中显示它,它在哪里。

您正在从不同的目录扩展通配符,而不是选择正确的文件。试试这个 CFILES:

CFILES := $(notdir $(wildcard $M/hello.c*))

【讨论】:

好吧,这行得通!澄清一下,$(CFLAGS) 是一个简单的扩展变量,根据 make 手册 it contains their values as of the time this variable was defined.,为什么它又被扩展了? 如果你使用 :=,右侧会立即展开,并保留用于当前 MAKE 过程的其余部分。在这种情况下,kbuild 系统涉及make 的第二次调用。在第二次调用中,一切都从头开始。从第一个 make 传递到第二个的唯一信息是在命令行上,如 M=$$PWD。这就是为什么我在第二个 make 过程中使用 $M 来扩展目录的原因。【参考方案2】:
 SRCDIRS := subdir1 subdir2
 CFILES := $(strip $(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.c)))

应该是(见foreachexample in documentation)

 SRCDIRS := subdir1 subdir2
 CFILES := $(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.c))

(不需要$(strip),....或者也许

 CFILES := $(wildcard  subdir1,subdir2/*.c)

使用remake,可能是remake -x,来调试此类问题。

【讨论】:

这对你有用吗?没有strip我已经测试过了,不行。

以上是关于无法在内核模块 makefile 中使用通配符的主要内容,如果未能解决你的问题,请参考以下文章

linux内核模块编译makefile -2

linux内核模块编译makefile

Linux驱动模块的Makefile分析

linux内核模块编译makefile

Makefile 编译内核模块以包含树源文件

无法让多文件内核模块工作