我决定采用Eudyptula Challenge。 在我提交了第一个任务之后,就是构建一个简单的“Hello World!”模块,我收到了以下答案。
请阅读Makefile的要求并允许该模块 针对文件系统上的任何内核源代码树构建,而不仅仅是那些 在某个时间点碰巧安装在
/lib/
中的内核。
要求是:
Makefile应该能够构建内核模块 当前运行的内核的源代码以及能够接受的内容 来自环境变量的任意内核源目录。
我正在做的是检查是否设置了环境变量KERNELRELEASE
。如果是我构建模块
$(KERNELRELEASE)/build
如果不反对
/lib/modules/$(shell uname -r)/build
我无法理解为什么这不能满足这项任务的要求。
答案 0 :(得分:26)
根据Eudyptula challenge规则,禁止直接向您提供解决方案,因此我将尝试描述答案的元素,以便您自己提出解决方案。基本上,下面我写的所有内容都在Documentation/kbuild/modules.txt文件中进行了详细介绍(尤其是在section 3.1 - Shared Makefile文件中),因此我认为这不会违反某些规则。以下是对上述文档中描述内容的解释。
KERNELRELEASE
变量您错误的是认为$(KERNELRELEASE)
旨在保留内核的路径。 $(KERNELRELEASE)
变量实际意味着什么 - 您可以在Documentation/kbuild/makefiles.txt中找到它:
KERNELRELEASE
$(KERNELRELEASE)
是一个单独的字符串,例如"2.4.0-pre4"
,非常合适 用于构造安装目录名称或显示在 版本字符串。某些拱门Makefiles
将其用于此目的。
问题是,您的Makefile
将被执行2次:来自您的 make
命令以及内核 {{1} }。 Makefile
可以帮助您解决问题:
$(KERNELRELEASE)
正在运行Makefile
命令;在这一步,您将执行内核make
(使用Makefile
param提供内核目录)。为内核的Makefile(来自Makefile的里面)运行-C
后,您的make
将第二次执行(参见下一项)。 Makefile
正在从内核Makefile
执行(Makefile
(定义此变量并将Makefile
调回)。在此步骤中,您可以使用内核构建系统功能,例如obj-m。-C
param 您真正需要做的是在Makefile
中定义一些自定义变量,该变量将保存内核目录路径。例如,您可以将其称为KDIR
。如您所知,您的内核源位于此路径:/lib/modules/$(shell uname -r)/build
。接下来,您可以在执行内核的Makefile时将此变量提供给-C
param(请参阅man 1 make)。
接下来,您必须从Makefile
之外传递此变量。为此,可以使用conditional variable assignment operator:
KDIR ?= /lib/modules/$(shell uname -r)/build
这样,如果将KDIR
变量传递给Makefile,就像这样:
$ make KDIR=bla-bla-bla
KDIR
变量将具有您传递的值。否则它将包含默认值,即/lib/modules/$(shell uname -r)/build
。