无法在内核模块 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 只需要 CFILES
、OBJS
、obj-m
和 hello_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)))
应该是(见foreach
example in documentation)
SRCDIRS := subdir1 subdir2
CFILES := $(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.c))
(不需要$(strip
),....或者也许
CFILES := $(wildcard subdir1,subdir2/*.c)
使用remake,可能是remake -x
,来调试此类问题。
【讨论】:
这对你有用吗?没有strip
我已经测试过了,不行。以上是关于无法在内核模块 makefile 中使用通配符的主要内容,如果未能解决你的问题,请参考以下文章