我正在尝试通过关注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
。
除了显式请求之外,仅在导出时才导出变量 最初在环境中定义或在命令上设置 如果它的名称只包含字母,数字和 下划线。有些shell无法处理环境变量名称 由字母,数字和下划线以外的字符组成。
https://www.gnu.org/software/make/manual/html_node/Variables_002fRecursion.html
obj-m
既未在最初的环境中定义,也未在命令行上设置。所以我希望它不应该导出到目标all
的配方。 kbuild如何访问obj-m
?
答案 0 :(得分:1)
你的makefile调用一个submake并传递指向当前目录的make变量M
。使用-C
选项调用子制表,使其像从指定目录(即内核源目录)调用一样运行。因此,内核构建系统具有自己的makefile。感谢M
变量,内核makefile知道他们在哪里可以找到你的makefile并将其包含在obj-m
定义中。
注意:您显示的makefile可能应该使用条件进行一些修改,以便只能从Linux构建系统中看到obj-m
变量定义。否则,makefile的all
和clean
目标与内核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