obj-m 变量如何导出到 sub-make?

How is obj-m variable exported to sub-make?

我正在尝试通过遵循 https://www.tldp.org/LDP/lkmpg/2.6/lkmpg.pdf 和阅读 GNU make 手册来学习 linux 内核模块构建和 kbuild。

这是 Linux 内核模块编程指南中第一个示例 Hello-1 的 Makefile:

obj-m += hello-1.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

AFAIK,obj-m 应该被 kbuild 读取。但是根据 GNU Make 手册,我明白 obj-m 不应该导出。

Except by explicit request, make exports a variable only if it is either defined in the environment initially or set on the command line, and if its name consists only of letters, numbers, and underscores. Some shells cannot cope with environment variable names consisting of characters other than letters, numbers, and underscores.

https://www.gnu.org/software/make/manual/html_node/Variables_002fRecursion.html

obj-m 最初既未在环境中定义,也未在命令行中设置。所以我希望它不应该导出到目标 all 的配方。 kbuild如何访问obj-m?

您的 makefile 调用 submake 并将指向当前目录的 make 变量 M 传递给它。 submake 是用 -C 选项调用的,因此它是 运行 就好像它是从指定目录调用的,即内核源目录。因此,使用的是具有自己的 makefile 的内核构建系统。多亏了 M 变量,内核 makefile 知道在哪里可以找到您的 makefile 并将其包含在其 obj-m 定义中。

注意:您显示的 makefile 可能应该用条件语句稍微修改一下,这样只有 obj-m 变量定义在 Linux 构建系统中可见。否则,您的 makefile 的 allclean 目标与内核 makefile 中具有相同名称的目标之间存在冲突的风险。而且,正如 MadScientist 所指出的,使用 make 并不是一个好主意; $(MAKE) 更可取。您可能应该使用类似的东西:

ifeq ($(KERNELRELEASE),)
all:
    $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
    $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
else
obj-m += hello-1.o
endif